From f6bf1d414188415e8e65841cfc6947543e57958a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 3 Apr 2015 17:41:19 -0700 Subject: [PATCH 01/18] Disable DDE code if not Windows or OSX --- interface/src/Application.cpp | 4 +++- interface/src/Menu.cpp | 4 ++-- interface/src/devices/DdeFaceTracker.h | 4 ++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f0324b7361..b49b8188c5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1730,8 +1730,10 @@ FaceTracker* Application::getActiveFaceTracker() { void Application::setActiveFaceTracker() { #ifdef HAVE_FACESHIFT DependencyManager::get()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)); -#endif +#endif +#ifdef HAVE_DDE DependencyManager::get()->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression)); +#endif #ifdef HAVE_VISAGE DependencyManager::get()->updateEnabled(); #endif diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f95ffddbfb..2313cb569e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -370,12 +370,12 @@ Menu::Menu() { qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(faceshiftFaceTracker); #endif - +#ifdef HAVE_DDE QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression, 0, false, qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(ddeFaceTracker); - +#endif #ifdef HAVE_VISAGE QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Visage, 0, false, diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 3c95666a6c..1a998d4b7f 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -12,6 +12,10 @@ #ifndef hifi_DdeFaceTracker_h #define hifi_DdeFaceTracker_h +#if defined(Q_OS_WIN) || defined(Q_OS_OSX) + #define HAVE_DDE +#endif + #include #include From 0d42c7a1c1addd1978a26044c360193366b99809 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 3 Apr 2015 19:16:07 -0700 Subject: [PATCH 02/18] Start and stop DDE as separate process --- interface/src/devices/DdeFaceTracker.cpp | 23 +++++++++++++++++++++++ interface/src/devices/DdeFaceTracker.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 9d753d228d..9449084c5d 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -11,6 +11,7 @@ #include +#include #include #include #include @@ -19,6 +20,13 @@ #include "DdeFaceTracker.h" #include "FaceshiftConstants.h" +#if defined(Q_OS_WIN) +static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde.exe"; +static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:5555 --headless"; +#elif defined(Q_OS_MAC) +static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde"; +static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:5555 --headless"; +#endif static const QHostAddress DDE_FEATURE_POINT_SERVER_ADDR("127.0.0.1"); static const quint16 DDE_FEATURE_POINT_SERVER_PORT = 5555; @@ -125,6 +133,7 @@ DdeFaceTracker::DdeFaceTracker() : } DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) : + _ddeProcess(NULL), _host(host), _port(port), _lastReceiveTimestamp(0), @@ -161,11 +170,25 @@ DdeFaceTracker::~DdeFaceTracker() { } void DdeFaceTracker::setEnabled(bool enabled) { +#ifdef HAVE_DDE + if (enabled && !_ddeProcess) { + qDebug() << "[Info] DDE Face Tracker Starting"; + _ddeProcess = new QProcess(qApp); + _ddeProcess->start(QCoreApplication::applicationDirPath() + DDE_PROGRAM_PATH, DDE_ARGUMENTS.split(" ")); + } + // 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); } + + if (!enabled && _ddeProcess) { + _ddeProcess->kill(); + _ddeProcess = NULL; + qDebug() << "[Info] DDE Face Tracker Stopped"; + } +#endif } bool DdeFaceTracker::isActive() const { diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 1a998d4b7f..d7008a57b9 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -16,6 +16,7 @@ #define HAVE_DDE #endif +#include #include #include @@ -62,6 +63,8 @@ private: DdeFaceTracker(const QHostAddress& host, quint16 port); ~DdeFaceTracker(); + QProcess* _ddeProcess; + QHostAddress _host; quint16 _port; From 00f5469fa82e50995d12db7a6504f25605a755aa Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 4 Apr 2015 17:31:32 -0700 Subject: [PATCH 03/18] Add menu item that resets DDE tracking --- interface/src/Application.h | 4 ++-- interface/src/Menu.cpp | 23 +++++++++++++++++++---- interface/src/Menu.h | 2 ++ interface/src/devices/DdeFaceTracker.cpp | 24 ++++++++++++++++-------- interface/src/devices/DdeFaceTracker.h | 6 ++++-- 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index e9b8deff55..b6d2a5cc10 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -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; } @@ -388,8 +390,6 @@ public slots: void notifyPacketVersionMismatch(); - void setActiveFaceTracker(); - void domainConnectionDenied(const QString& reason); private slots: diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 2313cb569e..ac27030ee3 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -361,28 +361,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().data(), SLOT(resetTracking())); + ddeFaceTrackerReset->setVisible(false); + faceTrackingMenu->addAction(ddeFaceTrackerReset); +#endif addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes); @@ -1002,3 +1010,10 @@ void Menu::visibilityChanged(Discoverability::Mode discoverabilityMode) { qDebug() << "ERROR Menu::visibilityChanged() called with unrecognized value."; } } + +void Menu::setActiveFaceTracker() { + bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression); + Menu::getInstance()->getActionForOption(MenuOption::ResetDDETracking)->setVisible(isUsingDDE); + + qApp->setActiveFaceTracker(); +} diff --git a/interface/src/Menu.h b/interface/src/Menu.h index db126a3c9b..00f876a539 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -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"; diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 9449084c5d..000ddf6069 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -22,13 +22,14 @@ #if defined(Q_OS_WIN) static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde.exe"; -static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:5555 --headless"; +static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:64204 --receiver=64205 --headless"; #elif defined(Q_OS_MAC) static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde"; -static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:5555 --headless"; +static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:64204 --receiver=64205 --headless"; #endif -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; static const int NUM_EXPRESSIONS = 46; static const int MIN_PACKET_SIZE = (8 + NUM_EXPRESSIONS) * sizeof(float) + sizeof(int); @@ -127,15 +128,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 @@ -180,7 +182,7 @@ void DdeFaceTracker::setEnabled(bool enabled) { // 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) { @@ -191,6 +193,12 @@ void DdeFaceTracker::setEnabled(bool enabled) { #endif } +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 { static const quint64 ACTIVE_TIMEOUT_USECS = 3000000; //3 secs return (usecTimestampNow() - _lastReceiveTimestamp < ACTIVE_TIMEOUT_USECS); diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index d7008a57b9..a53fbdb379 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -50,6 +50,7 @@ public: public slots: void setEnabled(bool enabled); + void resetTracking(); private slots: @@ -60,13 +61,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); From 1eb5716ab77079736a326803e3d83919388991b1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 4 Apr 2015 19:04:47 -0700 Subject: [PATCH 04/18] Shut down DDE when Interface shuts down --- interface/src/Application.cpp | 2 ++ interface/src/devices/DdeFaceTracker.cpp | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b49b8188c5..a26364cb06 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -610,6 +610,8 @@ void Application::cleanupBeforeQuit() { // destroy the AudioClient so it and its thread have a chance to go down safely DependencyManager::destroy(); + + DependencyManager::destroy(); } Application::~Application() { diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 000ddf6069..cadf48d98b 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -166,9 +166,7 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui } DdeFaceTracker::~DdeFaceTracker() { - if (_udpSocket.isOpen()) { - _udpSocket.close(); - } + setEnabled(false); } void DdeFaceTracker::setEnabled(bool enabled) { From 65c1fea689bf21e2438fb3156ec43b990f29fe8d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 4 Apr 2015 19:08:23 -0700 Subject: [PATCH 05/18] Increase DDE head translation to make avatar better reflect RL --- interface/src/devices/DdeFaceTracker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index cadf48d98b..d654a493ed 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -266,7 +266,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; From 765d66eee55597c4af1fc9cc8811fc5fe9bc661c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 4 Apr 2015 19:20:44 -0700 Subject: [PATCH 06/18] Fix running without DDE available --- interface/src/Application.cpp | 2 ++ interface/src/Menu.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a26364cb06..b1f7d65441 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -611,7 +611,9 @@ void Application::cleanupBeforeQuit() { // destroy the AudioClient so it and its thread have a chance to go down safely DependencyManager::destroy(); +#ifdef HAVE_DDE DependencyManager::destroy(); +#endif } Application::~Application() { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ac27030ee3..6e8763426d 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1012,8 +1012,9 @@ void Menu::visibilityChanged(Discoverability::Mode discoverabilityMode) { } void Menu::setActiveFaceTracker() { +#ifdef HAVE_DDE bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression); Menu::getInstance()->getActionForOption(MenuOption::ResetDDETracking)->setVisible(isUsingDDE); - +#endif qApp->setActiveFaceTracker(); } From 2b23108e616260989c27afdec1be5a109c474b06 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 7 Apr 2015 01:06:39 +0200 Subject: [PATCH 07/18] ScriptsScripting Interface --- interface/src/Application.cpp | 4 +++ .../scripting/ScriptsScriptingInterface.cpp | 27 +++++++++++++++++++ .../src/scripting/ScriptsScriptingInterface.h | 27 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 interface/src/scripting/ScriptsScriptingInterface.cpp create mode 100644 interface/src/scripting/ScriptsScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a8f9efd672..943f2bd491 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -121,6 +121,7 @@ #include "scripting/GlobalServicesScriptingInterface.h" #include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" +#include "scripting/ScriptsScriptingInterface.h" #include "scripting/SettingsScriptingInterface.h" #include "scripting/WindowScriptingInterface.h" #include "scripting/WebWindowClass.h" @@ -3595,6 +3596,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Scene", DependencyManager::get().data()); + QScriptValue scriptsScriptingInterface = scriptEngine->registerGlobalObject("Scripts", ScriptsScriptingInterface::getInstance()); + scriptEngine->registerFunction(scriptsScriptingInterface, "getPublic", ScriptsScriptingInterface::getPublic, 0); + #ifdef HAVE_RTMIDI scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); #endif diff --git a/interface/src/scripting/ScriptsScriptingInterface.cpp b/interface/src/scripting/ScriptsScriptingInterface.cpp new file mode 100644 index 0000000000..93bfe967ad --- /dev/null +++ b/interface/src/scripting/ScriptsScriptingInterface.cpp @@ -0,0 +1,27 @@ +// +// ScriptsScriptingInterface.cpp +// interface/src/scripting +// +// Created by Thijs Wenker on 3/31/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 "Application.h" + +#include "ScriptsScriptingInterface.h" + +ScriptsScriptingInterface* ScriptsScriptingInterface::getInstance() { + static ScriptsScriptingInterface sharedInstance; + return &sharedInstance; +} + +QStringList ScriptsScriptingInterface::getRunning() { + return Application::getInstance()->getRunningScripts(); +} + +QScriptValue ScriptsScriptingInterface::getPublic(QScriptContext* context, QScriptEngine* engine) { + return QScriptValue::NullValue; +} diff --git a/interface/src/scripting/ScriptsScriptingInterface.h b/interface/src/scripting/ScriptsScriptingInterface.h new file mode 100644 index 0000000000..ad7f4d2cea --- /dev/null +++ b/interface/src/scripting/ScriptsScriptingInterface.h @@ -0,0 +1,27 @@ +// +// ScriptsScriptingInterface.h +// interface/src/scripting +// +// Created by Thijs Wenker on 3/31/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 +// + +#ifndef hifi_ScriptsScriptingInterface_h +#define hifi_ScriptsScriptingInterface_h + +#include + +class ScriptsScriptingInterface : public QObject { + Q_OBJECT +public: + ScriptsScriptingInterface() {}; + static ScriptsScriptingInterface* getInstance(); + static QScriptValue getPublic(QScriptContext* context, QScriptEngine* engine); +public slots: + QStringList getRunning(); +}; + +#endif // hifi_ScriptsScriptingInterface_h From a783f0302558c9af828991ab17591c7138d32efb Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 7 Apr 2015 16:48:11 +0200 Subject: [PATCH 08/18] New scripting functions Scripts.getPublic(), Scripts.getLocal() and Scripts.getRunning() functional. --- interface/src/Application.cpp | 3 +- .../scripting/ScriptsScriptingInterface.cpp | 71 +++++++++++++++++-- .../src/scripting/ScriptsScriptingInterface.h | 9 ++- interface/src/ui/RunningScriptsWidget.h | 2 + 4 files changed, 77 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index af6c600bf8..9bbc10a7d5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3609,8 +3609,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Scene", DependencyManager::get().data()); - QScriptValue scriptsScriptingInterface = scriptEngine->registerGlobalObject("Scripts", ScriptsScriptingInterface::getInstance()); - scriptEngine->registerFunction(scriptsScriptingInterface, "getPublic", ScriptsScriptingInterface::getPublic, 0); + scriptEngine->registerGlobalObject("Scripts", ScriptsScriptingInterface::getInstance()); #ifdef HAVE_RTMIDI scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); diff --git a/interface/src/scripting/ScriptsScriptingInterface.cpp b/interface/src/scripting/ScriptsScriptingInterface.cpp index 93bfe967ad..72a0807bce 100644 --- a/interface/src/scripting/ScriptsScriptingInterface.cpp +++ b/interface/src/scripting/ScriptsScriptingInterface.cpp @@ -18,10 +18,73 @@ ScriptsScriptingInterface* ScriptsScriptingInterface::getInstance() { return &sharedInstance; } -QStringList ScriptsScriptingInterface::getRunning() { - return Application::getInstance()->getRunningScripts(); +QVariantList ScriptsScriptingInterface::getRunning() { + const int WINDOWS_DRIVE_LETTER_SIZE = 1; + QVariantList result; + QStringList runningScripts = Application::getInstance()->getRunningScripts(); + for (int i = 0; i < runningScripts.size(); i++) { + QUrl runningScriptURL = QUrl(runningScripts.at(i)); + if (runningScriptURL.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { + runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); + } + QVariantMap resultNode; + resultNode.insert("name", runningScriptURL.fileName()); + resultNode.insert("path", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); + resultNode.insert("local", runningScriptURL.isLocalFile()); + result.append(resultNode); + } + return result; } -QScriptValue ScriptsScriptingInterface::getPublic(QScriptContext* context, QScriptEngine* engine) { - return QScriptValue::NullValue; +QVariantList ScriptsScriptingInterface::getPublic() { + return getPublicChildNodes(NULL); +} + +QVariantList ScriptsScriptingInterface::getPublicChildNodes(TreeNodeFolder* parent) { + QVariantList result; + QList treeNodes = Application::getInstance()->getRunningScriptsWidget()->getScriptsModel() + ->getFolderNodes(parent); + for (int i = 0; i < treeNodes.size(); i++) { + TreeNodeBase* node = treeNodes.at(i); + if (node->getType() == TREE_NODE_TYPE_FOLDER) { + TreeNodeFolder* folder = static_cast(node); + QVariantMap resultNode; + resultNode.insert("name", node->getName()); + resultNode.insert("type", "folder"); + resultNode.insert("children", getPublicChildNodes(folder)); + result.append(resultNode); + continue; + } + TreeNodeScript* script = static_cast(node); + if (script->getOrigin() == ScriptOrigin::SCRIPT_ORIGIN_LOCAL) { + continue; + } + QVariantMap resultNode; + resultNode.insert("name", node->getName()); + resultNode.insert("type", "script"); + resultNode.insert("path", script->getFullPath()); + result.append(resultNode); + } + return result; +} + +QVariantList ScriptsScriptingInterface::getLocal() { + QVariantList result; + QList treeNodes = Application::getInstance()->getRunningScriptsWidget()->getScriptsModel() + ->getFolderNodes(NULL); + for (int i = 0; i < treeNodes.size(); i++) { + TreeNodeBase* node = treeNodes.at(i); + if (node->getType() != TREE_NODE_TYPE_SCRIPT) { + continue; + } + TreeNodeScript* script = static_cast(node); + if (script->getOrigin() != ScriptOrigin::SCRIPT_ORIGIN_LOCAL) { + continue; + } + QVariantMap resultNode; + resultNode.insert("name", node->getName()); + resultNode.insert("path", script->getFullPath()); + result.append(resultNode); + } + return result; } diff --git a/interface/src/scripting/ScriptsScriptingInterface.h b/interface/src/scripting/ScriptsScriptingInterface.h index ad7f4d2cea..6833c4d064 100644 --- a/interface/src/scripting/ScriptsScriptingInterface.h +++ b/interface/src/scripting/ScriptsScriptingInterface.h @@ -19,9 +19,14 @@ class ScriptsScriptingInterface : public QObject { public: ScriptsScriptingInterface() {}; static ScriptsScriptingInterface* getInstance(); - static QScriptValue getPublic(QScriptContext* context, QScriptEngine* engine); + public slots: - QStringList getRunning(); + QVariantList getRunning(); + QVariantList getPublic(); + QVariantList getLocal(); + +private: + QVariantList getPublicChildNodes(TreeNodeFolder* parent); }; #endif // hifi_ScriptsScriptingInterface_h diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h index 3ec5590dee..38ca3d46cf 100644 --- a/interface/src/ui/RunningScriptsWidget.h +++ b/interface/src/ui/RunningScriptsWidget.h @@ -33,6 +33,8 @@ public: void setRunningScripts(const QStringList& list); + const ScriptsModel* getScriptsModel() { return &_scriptsModel; } + signals: void stopScriptName(const QString& name); From af34add63c5322bffd53f5990a9823a664b21e3b Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 7 Apr 2015 17:39:50 +0200 Subject: [PATCH 09/18] added example for the new Scripts functions: example\misc\scriptsExample.js --- examples/example/misc/scriptsExample.js | 41 +++++++++++++++++++ .../scripting/ScriptsScriptingInterface.cpp | 4 +- 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 examples/example/misc/scriptsExample.js diff --git a/examples/example/misc/scriptsExample.js b/examples/example/misc/scriptsExample.js new file mode 100644 index 0000000000..1ffeaa30c4 --- /dev/null +++ b/examples/example/misc/scriptsExample.js @@ -0,0 +1,41 @@ +// +// scriptsExample.js +// examples/example/misc +// +// Created by Thijs Wenker on 7 Apr 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Outputs the running, public and local scripts to the console. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var runningScripts = Scripts.getRunning(); +print("Running Scripts:"); +for (var i = 0; i < runningScripts.length; i++) { + print(" - " + runningScripts[i].name + (runningScripts[i].local ? "[Local]" : "") + " {" + runningScripts[i].url + "}"); +} + +var localScripts = Scripts.getLocal(); +print("Local Scripts:"); +for (var i = 0; i < localScripts.length; i++) { + print(" - " + localScripts[i].name + " {" + localScripts[i].path + "}"); +} + +// recursive function to walk through all folders in public scripts +// adding 2 spaces to the prefix per depth level +function displayPublicScriptFolder(nodes, prefix) { + for (var i = 0; i < nodes.length; i++) { + if (nodes[i].type == "folder") { + print(prefix + "<" + nodes[i].name + ">"); + displayPublicScriptFolder(nodes[i].children, " " + prefix); + continue; + } + print(prefix + nodes[i].name + " {" + nodes[i].url + "}"); + } +} + +var publicScripts = Scripts.getPublic(); +print("Public Scripts:"); +displayPublicScriptFolder(publicScripts, " - "); \ No newline at end of file diff --git a/interface/src/scripting/ScriptsScriptingInterface.cpp b/interface/src/scripting/ScriptsScriptingInterface.cpp index 72a0807bce..7cf02fd27b 100644 --- a/interface/src/scripting/ScriptsScriptingInterface.cpp +++ b/interface/src/scripting/ScriptsScriptingInterface.cpp @@ -29,7 +29,7 @@ QVariantList ScriptsScriptingInterface::getRunning() { } QVariantMap resultNode; resultNode.insert("name", runningScriptURL.fileName()); - resultNode.insert("path", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); + resultNode.insert("url", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); resultNode.insert("local", runningScriptURL.isLocalFile()); result.append(resultNode); } @@ -62,7 +62,7 @@ QVariantList ScriptsScriptingInterface::getPublicChildNodes(TreeNodeFolder* pare QVariantMap resultNode; resultNode.insert("name", node->getName()); resultNode.insert("type", "script"); - resultNode.insert("path", script->getFullPath()); + resultNode.insert("url", script->getFullPath()); result.append(resultNode); } return result; From 0cb5ee5bd18889cd808c96b0001e6cd8628cd403 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 9 Apr 2015 23:46:49 +0200 Subject: [PATCH 10/18] - Scripts JS object renamed to ScriptDiscoveryService. - Renamed Example script file for the ScriptDiscoveryService. - Moved ScriptDiscoveryService functions to the RunningScriptWidget --- .../{scriptsExample.js => listAllScripts.js} | 8 +- interface/src/Application.cpp | 3 +- .../scripting/ScriptsScriptingInterface.cpp | 90 ------------------- .../src/scripting/ScriptsScriptingInterface.h | 32 ------- interface/src/ui/RunningScriptsWidget.cpp | 71 +++++++++++++++ interface/src/ui/RunningScriptsWidget.h | 7 +- 6 files changed, 82 insertions(+), 129 deletions(-) rename examples/example/misc/{scriptsExample.js => listAllScripts.js} (86%) delete mode 100644 interface/src/scripting/ScriptsScriptingInterface.cpp delete mode 100644 interface/src/scripting/ScriptsScriptingInterface.h diff --git a/examples/example/misc/scriptsExample.js b/examples/example/misc/listAllScripts.js similarity index 86% rename from examples/example/misc/scriptsExample.js rename to examples/example/misc/listAllScripts.js index 1ffeaa30c4..1baa40751e 100644 --- a/examples/example/misc/scriptsExample.js +++ b/examples/example/misc/listAllScripts.js @@ -1,5 +1,5 @@ // -// scriptsExample.js +// listAllScripts.js // examples/example/misc // // Created by Thijs Wenker on 7 Apr 2015 @@ -11,13 +11,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var runningScripts = Scripts.getRunning(); +var runningScripts = ScriptDiscoveryService.getRunning(); print("Running Scripts:"); for (var i = 0; i < runningScripts.length; i++) { print(" - " + runningScripts[i].name + (runningScripts[i].local ? "[Local]" : "") + " {" + runningScripts[i].url + "}"); } -var localScripts = Scripts.getLocal(); +var localScripts = ScriptDiscoveryService.getLocal(); print("Local Scripts:"); for (var i = 0; i < localScripts.length; i++) { print(" - " + localScripts[i].name + " {" + localScripts[i].path + "}"); @@ -36,6 +36,6 @@ function displayPublicScriptFolder(nodes, prefix) { } } -var publicScripts = Scripts.getPublic(); +var publicScripts = ScriptDiscoveryService.getPublic(); print("Public Scripts:"); displayPublicScriptFolder(publicScripts, " - "); \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9bbc10a7d5..fe5a73b056 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -121,7 +121,6 @@ #include "scripting/GlobalServicesScriptingInterface.h" #include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" -#include "scripting/ScriptsScriptingInterface.h" #include "scripting/SettingsScriptingInterface.h" #include "scripting/WindowScriptingInterface.h" #include "scripting/WebWindowClass.h" @@ -3609,7 +3608,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Scene", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Scripts", ScriptsScriptingInterface::getInstance()); + scriptEngine->registerGlobalObject("ScriptDiscoveryService", this->getRunningScriptsWidget()); #ifdef HAVE_RTMIDI scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); diff --git a/interface/src/scripting/ScriptsScriptingInterface.cpp b/interface/src/scripting/ScriptsScriptingInterface.cpp deleted file mode 100644 index 7cf02fd27b..0000000000 --- a/interface/src/scripting/ScriptsScriptingInterface.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// ScriptsScriptingInterface.cpp -// interface/src/scripting -// -// Created by Thijs Wenker on 3/31/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 "Application.h" - -#include "ScriptsScriptingInterface.h" - -ScriptsScriptingInterface* ScriptsScriptingInterface::getInstance() { - static ScriptsScriptingInterface sharedInstance; - return &sharedInstance; -} - -QVariantList ScriptsScriptingInterface::getRunning() { - const int WINDOWS_DRIVE_LETTER_SIZE = 1; - QVariantList result; - QStringList runningScripts = Application::getInstance()->getRunningScripts(); - for (int i = 0; i < runningScripts.size(); i++) { - QUrl runningScriptURL = QUrl(runningScripts.at(i)); - if (runningScriptURL.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { - runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); - } - QVariantMap resultNode; - resultNode.insert("name", runningScriptURL.fileName()); - resultNode.insert("url", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); - resultNode.insert("local", runningScriptURL.isLocalFile()); - result.append(resultNode); - } - return result; -} - -QVariantList ScriptsScriptingInterface::getPublic() { - return getPublicChildNodes(NULL); -} - -QVariantList ScriptsScriptingInterface::getPublicChildNodes(TreeNodeFolder* parent) { - QVariantList result; - QList treeNodes = Application::getInstance()->getRunningScriptsWidget()->getScriptsModel() - ->getFolderNodes(parent); - for (int i = 0; i < treeNodes.size(); i++) { - TreeNodeBase* node = treeNodes.at(i); - if (node->getType() == TREE_NODE_TYPE_FOLDER) { - TreeNodeFolder* folder = static_cast(node); - QVariantMap resultNode; - resultNode.insert("name", node->getName()); - resultNode.insert("type", "folder"); - resultNode.insert("children", getPublicChildNodes(folder)); - result.append(resultNode); - continue; - } - TreeNodeScript* script = static_cast(node); - if (script->getOrigin() == ScriptOrigin::SCRIPT_ORIGIN_LOCAL) { - continue; - } - QVariantMap resultNode; - resultNode.insert("name", node->getName()); - resultNode.insert("type", "script"); - resultNode.insert("url", script->getFullPath()); - result.append(resultNode); - } - return result; -} - -QVariantList ScriptsScriptingInterface::getLocal() { - QVariantList result; - QList treeNodes = Application::getInstance()->getRunningScriptsWidget()->getScriptsModel() - ->getFolderNodes(NULL); - for (int i = 0; i < treeNodes.size(); i++) { - TreeNodeBase* node = treeNodes.at(i); - if (node->getType() != TREE_NODE_TYPE_SCRIPT) { - continue; - } - TreeNodeScript* script = static_cast(node); - if (script->getOrigin() != ScriptOrigin::SCRIPT_ORIGIN_LOCAL) { - continue; - } - QVariantMap resultNode; - resultNode.insert("name", node->getName()); - resultNode.insert("path", script->getFullPath()); - result.append(resultNode); - } - return result; -} diff --git a/interface/src/scripting/ScriptsScriptingInterface.h b/interface/src/scripting/ScriptsScriptingInterface.h deleted file mode 100644 index 6833c4d064..0000000000 --- a/interface/src/scripting/ScriptsScriptingInterface.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// ScriptsScriptingInterface.h -// interface/src/scripting -// -// Created by Thijs Wenker on 3/31/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 -// - -#ifndef hifi_ScriptsScriptingInterface_h -#define hifi_ScriptsScriptingInterface_h - -#include - -class ScriptsScriptingInterface : public QObject { - Q_OBJECT -public: - ScriptsScriptingInterface() {}; - static ScriptsScriptingInterface* getInstance(); - -public slots: - QVariantList getRunning(); - QVariantList getPublic(); - QVariantList getLocal(); - -private: - QVariantList getPublicChildNodes(TreeNodeFolder* parent); -}; - -#endif // hifi_ScriptsScriptingInterface_h diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 9ff600675f..f892deabb6 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -210,3 +210,74 @@ void RunningScriptsWidget::scriptStopped(const QString& scriptName) { void RunningScriptsWidget::allScriptsStopped() { Application::getInstance()->stopAllScripts(); } + +QVariantList RunningScriptsWidget::getRunning() { + const int WINDOWS_DRIVE_LETTER_SIZE = 1; + QVariantList result; + QStringList runningScripts = Application::getInstance()->getRunningScripts(); + for (int i = 0; i < runningScripts.size(); i++) { + QUrl runningScriptURL = QUrl(runningScripts.at(i)); + if (runningScriptURL.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { + runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); + } + QVariantMap resultNode; + resultNode.insert("name", runningScriptURL.fileName()); + resultNode.insert("url", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); + resultNode.insert("local", runningScriptURL.isLocalFile()); + result.append(resultNode); + } + return result; +} + +QVariantList RunningScriptsWidget::getPublic() { + return getPublicChildNodes(NULL); +} + +QVariantList RunningScriptsWidget::getPublicChildNodes(TreeNodeFolder* parent) { + QVariantList result; + QList treeNodes = Application::getInstance()->getRunningScriptsWidget()->getScriptsModel() + ->getFolderNodes(parent); + for (int i = 0; i < treeNodes.size(); i++) { + TreeNodeBase* node = treeNodes.at(i); + if (node->getType() == TREE_NODE_TYPE_FOLDER) { + TreeNodeFolder* folder = static_cast(node); + QVariantMap resultNode; + resultNode.insert("name", node->getName()); + resultNode.insert("type", "folder"); + resultNode.insert("children", getPublicChildNodes(folder)); + result.append(resultNode); + continue; + } + TreeNodeScript* script = static_cast(node); + if (script->getOrigin() == ScriptOrigin::SCRIPT_ORIGIN_LOCAL) { + continue; + } + QVariantMap resultNode; + resultNode.insert("name", node->getName()); + resultNode.insert("type", "script"); + resultNode.insert("url", script->getFullPath()); + result.append(resultNode); + } + return result; +} + +QVariantList RunningScriptsWidget::getLocal() { + QVariantList result; + QList treeNodes = Application::getInstance()->getRunningScriptsWidget()->getScriptsModel() + ->getFolderNodes(NULL); + for (int i = 0; i < treeNodes.size(); i++) { + TreeNodeBase* node = treeNodes.at(i); + if (node->getType() != TREE_NODE_TYPE_SCRIPT) { + continue; + } + TreeNodeScript* script = static_cast(node); + if (script->getOrigin() != ScriptOrigin::SCRIPT_ORIGIN_LOCAL) { + continue; + } + QVariantMap resultNode; + resultNode.insert("name", node->getName()); + resultNode.insert("path", script->getFullPath()); + result.append(resultNode); + } + return result; +} diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h index 38ca3d46cf..5d3f6843af 100644 --- a/interface/src/ui/RunningScriptsWidget.h +++ b/interface/src/ui/RunningScriptsWidget.h @@ -46,7 +46,10 @@ protected: public slots: void scriptStopped(const QString& scriptName); - + QVariantList getRunning(); + QVariantList getPublic(); + QVariantList getLocal(); + private slots: void allScriptsStopped(); void updateFileFilter(const QString& filter); @@ -62,6 +65,8 @@ private: ScriptsTableWidget* _recentlyLoadedScriptsTable; QStringList _recentlyLoadedScripts; QString _lastStoppedScript; + + QVariantList getPublicChildNodes(TreeNodeFolder* parent); }; #endif // hifi_RunningScriptsWidget_h From 809c7919aa705994a21744888f26c5113c4121ea Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 13 Apr 2015 15:57:36 +0200 Subject: [PATCH 11/18] Fix ghost avatars --- interface/src/avatar/AvatarManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 5ee09ba1cf..38144dfe5f 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -149,7 +149,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { while (fadingIterator != _avatarFades.end()) { Avatar* avatar = static_cast(fadingIterator->data()); - avatar->setTargetScale(avatar->getScale() * SHRINK_RATE); + avatar->setTargetScale(avatar->getScale() * SHRINK_RATE, true); if (avatar->getTargetScale() < MIN_FADE_SCALE) { fadingIterator = _avatarFades.erase(fadingIterator); } else { From 8479f0d4c130944925a61cafb5653b8bd60ed1c2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 09:34:38 -0700 Subject: [PATCH 12/18] don't compute shape info until both render and collision geometries are fully loaded --- .../src/RenderableModelEntityItem.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 73968607f7..1d601d1294 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -297,10 +297,17 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { // no collision-model url, so we're ready to compute a shape (of type None). return true; } + if (_model->getURL().isEmpty()) { + // we need a render geometry with a scale to proceed, so give up. + return true; + } const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); - if (! collisionNetworkGeometry.isNull() && collisionNetworkGeometry->isLoadedWithTextures()) { - // we have a _collisionModelURL AND a collisionNetworkGeometry AND it's fully loaded. + const QSharedPointer renderNetworkGeometry = _model->getGeometry(); + + if ((! collisionNetworkGeometry.isNull() && collisionNetworkGeometry->isLoadedWithTextures()) && + (! renderNetworkGeometry.isNull() && renderNetworkGeometry->isLoadedWithTextures())) { + // we have both URLs AND both geometries AND they are both fully loaded. return true; } @@ -309,7 +316,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { } void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { - if (_model->getCollisionURL().isEmpty()) { + if (_model->getCollisionURL().isEmpty() || _model->getURL().isEmpty()) { info.setParams(getShapeType(), 0.5f * getDimensions()); } else { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); From 86f89a1d6f52427966966ec8d64b96d53543b562 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 13 Apr 2015 13:23:15 -0700 Subject: [PATCH 13/18] fix bug where fly speed is limited to walk speed --- libraries/physics/src/DynamicCharacterController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/DynamicCharacterController.cpp b/libraries/physics/src/DynamicCharacterController.cpp index db84bea540..aaabe21e9b 100644 --- a/libraries/physics/src/DynamicCharacterController.cpp +++ b/libraries/physics/src/DynamicCharacterController.cpp @@ -245,7 +245,6 @@ void DynamicCharacterController::setEnabled(bool enabled) { // Don't bother clearing REMOVE bit since it might be paired with an UPDATE_SHAPE bit. // Setting the ADD bit here works for all cases so we don't even bother checking other bits. _pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION; - setHovering(true); } else { if (_dynamicsWorld) { _pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION; @@ -253,6 +252,7 @@ void DynamicCharacterController::setEnabled(bool enabled) { _pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION; _isOnGround = false; } + setHovering(true); _enabled = enabled; } } From 2c4f049851efed0c15b390b2c5d0379deb66d5c4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 13 Apr 2015 17:11:27 -0700 Subject: [PATCH 14/18] Change OSX DDE program path per build system requirements --- interface/src/devices/DdeFaceTracker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index d654a493ed..7228358532 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -24,7 +24,7 @@ static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde.exe"; static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:64204 --receiver=64205 --headless"; #elif defined(Q_OS_MAC) -static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde"; +static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde.app/Contents/MacOS/dde"; static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:64204 --receiver=64205 --headless"; #endif static const QHostAddress DDE_SERVER_ADDR("127.0.0.1"); From 13c038879dbcbec386e697191eaf577db2703275 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 13 Apr 2015 17:13:03 -0700 Subject: [PATCH 15/18] Don't repeat constant values --- interface/src/devices/DdeFaceTracker.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 7228358532..78c665b7a0 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -20,16 +20,18 @@ #include "DdeFaceTracker.h" #include "FaceshiftConstants.h" -#if defined(Q_OS_WIN) -static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde.exe"; -static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:64204 --receiver=64205 --headless"; -#elif defined(Q_OS_MAC) -static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde.app/Contents/MacOS/dde"; -static const QString DDE_ARGUMENTS = "--udp=127.0.0.1:64204 --receiver=64205 --headless"; -#endif 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); @@ -174,7 +176,7 @@ void DdeFaceTracker::setEnabled(bool enabled) { if (enabled && !_ddeProcess) { qDebug() << "[Info] DDE Face Tracker Starting"; _ddeProcess = new QProcess(qApp); - _ddeProcess->start(QCoreApplication::applicationDirPath() + DDE_PROGRAM_PATH, DDE_ARGUMENTS.split(" ")); + _ddeProcess->start(QCoreApplication::applicationDirPath() + DDE_PROGRAM_PATH, DDE_ARGUMENTS); } // isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket. From b7f7cebb808cbbe5e051bee86dcc39ba1fe6f157 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 13 Apr 2015 22:41:17 -0700 Subject: [PATCH 16/18] Handle DDE stopping unexpectedly --- interface/src/devices/DdeFaceTracker.cpp | 12 ++++++++++++ interface/src/devices/DdeFaceTracker.h | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 55a9b7979b..4ab2d70509 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -20,6 +20,7 @@ #include "DdeFaceTracker.h" #include "FaceshiftConstants.h" #include "InterfaceLogging.h" +#include "Menu.h" static const QHostAddress DDE_SERVER_ADDR("127.0.0.1"); @@ -178,6 +179,7 @@ void DdeFaceTracker::setEnabled(bool enabled) { if (enabled && !_ddeProcess) { 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); } @@ -195,6 +197,16 @@ void DdeFaceTracker::setEnabled(bool enabled) { #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"; diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index a53fbdb379..490020e511 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -53,7 +53,8 @@ public slots: void resetTracking(); private slots: - + void processFinished(int exitCode, QProcess::ExitStatus exitStatus); + //sockets void socketErrorOccurred(QAbstractSocket::SocketError socketError); void readPendingDatagrams(); From f509d08378c62523b50e1132b3996b9463f3dd8b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 13 Apr 2015 23:12:13 -0700 Subject: [PATCH 17/18] Handle DDE already running --- interface/src/devices/DdeFaceTracker.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 4ab2d70509..a701160198 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -176,21 +176,25 @@ DdeFaceTracker::~DdeFaceTracker() { void DdeFaceTracker::setEnabled(bool enabled) { #ifdef HAVE_DDE - if (enabled && !_ddeProcess) { - 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); - } - // isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket. _udpSocket.close(); if (enabled) { _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(); + _ddeProcess->kill(); // More robust than trying to send an "exit" command to DDE _ddeProcess = NULL; qDebug() << "[Info] DDE Face Tracker Stopped"; } From b6942e2300ef061aadde288c9b36a6450ccd504c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 14 Apr 2015 10:11:52 -0700 Subject: [PATCH 18/18] Fix stuck-spinners in entity properties --- examples/html/entityProperties.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 4ac1b70e33..dd5bced393 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -508,18 +508,22 @@ // To make this work we block the first mouseup event after the elements // received focus. If we block all mouseup events the user will not // be able to click within the selected text. + // We also check to see if the value has changed to make sure we aren't + // blocking a mouse-up event when clicking on an input spinner. var els = document.querySelectorAll("input, textarea"); for (var i = 0; i < els.length; i++) { var clicked = false; + var originalText; els[i].onfocus = function() { + originalText = this.value; this.select(); clicked = false; }; els[i].onmouseup = function(e) { - if (!clicked) { + if (!clicked && originalText == this.value) { e.preventDefault(); - clicked = true; } + clicked = true; }; } }