diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7a0e61240a..fbe55071e4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -76,10 +77,13 @@ #include "ModelUploader.h" #include "Util.h" +#include "devices/DdeFaceTracker.h" +#include "devices/Faceshift.h" #include "devices/Leapmotion.h" #include "devices/MIDIManager.h" #include "devices/OculusManager.h" #include "devices/TV3DManager.h" +#include "devices/Visage.h" #include "renderer/ProgramObject.h" #include "gpu/Batch.h" @@ -1690,9 +1694,13 @@ int Application::getMouseDragStartedY() const { } FaceTracker* Application::getActiveFaceTracker() { - return (_dde.isActive() ? static_cast(&_dde) : - (_faceshift.isActive() ? static_cast(&_faceshift) : - (_visage.isActive() ? static_cast(&_visage) : NULL))); + Faceshift* faceshift = DependencyManager::get(); + Visage* visage = DependencyManager::get(); + DdeFaceTracker* dde = DependencyManager::get(); + + return (dde->isActive() ? static_cast(dde) : + (faceshift->isActive() ? static_cast(faceshift) : + (visage->isActive() ? static_cast(visage) : NULL))); } struct SendVoxelsOperationArgs { @@ -1976,8 +1984,8 @@ void Application::init() { #endif // initialize our face trackers after loading the menu settings - _faceshift.init(); - _visage.init(); + DependencyManager::get()->init(); + DependencyManager::get()->init(); Leapmotion::init(); @@ -2101,13 +2109,13 @@ void Application::updateMouseRay() { void Application::updateFaceshift() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateFaceshift()"); - + Faceshift* faceshift = DependencyManager::get(); // Update faceshift - _faceshift.update(); + faceshift->update(); // Copy angular velocity if measured by faceshift, to the head - if (_faceshift.isActive()) { - _myAvatar->getHead()->setAngularVelocity(_faceshift.getHeadAngularVelocity()); + if (faceshift->isActive()) { + _myAvatar->getHead()->setAngularVelocity(faceshift->getHeadAngularVelocity()); } } @@ -2116,7 +2124,7 @@ void Application::updateVisage() { PerformanceWarning warn(showWarnings, "Application::updateVisage()"); // Update Visage - _visage.update(); + DependencyManager::get()->update(); } void Application::updateDDE() { @@ -2124,7 +2132,7 @@ void Application::updateDDE() { PerformanceWarning warn(showWarnings, "Application::updateDDE()"); // Update Cara - _dde.update(); + DependencyManager::get()->update(); } void Application::updateMyAvatarLookAtPosition() { @@ -3549,9 +3557,9 @@ void Application::deleteVoxelAt(const VoxelDetail& voxel) { } void Application::resetSensors() { - _faceshift.reset(); - _visage.reset(); - _dde.reset(); + DependencyManager::get()->reset(); + DependencyManager::get()->reset(); + DependencyManager::get()->reset(); OculusManager::reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index f82b14b47e..833f1374ce 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -54,11 +54,8 @@ #include "avatar/Avatar.h" #include "avatar/AvatarManager.h" #include "avatar/MyAvatar.h" -#include "devices/Faceshift.h" #include "devices/PrioVR.h" #include "devices/SixenseManager.h" -#include "devices/Visage.h" -#include "devices/DdeFaceTracker.h" #include "entities/EntityTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" @@ -100,6 +97,7 @@ class QMouseEvent; class QSettings; class QWheelEvent; +class FaceTracker; class Node; class ProgramObject; @@ -220,10 +218,7 @@ public: int getMouseDragStartedY() const; int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } int getTrueMouseDragStartedY() const { return _mouseDragStartedY; } - bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated;; } - Faceshift* getFaceshift() { return &_faceshift; } - Visage* getVisage() { return &_visage; } - DdeFaceTracker* getDDE() { return &_dde; } + bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } FaceTracker* getActiveFaceTracker(); PrioVR* getPrioVR() { return &_prioVR; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } @@ -532,10 +527,6 @@ private: AvatarManager _avatarManager; MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) - Faceshift _faceshift; - Visage _visage; - DdeFaceTracker _dde; - PrioVR _prioVR; Camera _myCamera; // My view onto the world diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 5e35f08e95..6c2c3966fc 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -31,12 +31,16 @@ #include #include -#include +#include #include #include +#include #include "Application.h" #include "AccountManager.h" +#include "devices/Faceshift.h" +#include "devices/OculusManager.h" +#include "devices/Visage.h" #include "Menu.h" #include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" @@ -49,7 +53,6 @@ #include "ui/ModelsBrowser.h" #include "ui/LoginDialog.h" #include "ui/NodeBounds.h" -#include "devices/OculusManager.h" Menu* Menu::_instance = NULL; @@ -432,12 +435,12 @@ Menu::Menu() : MenuOption::Faceshift, 0, true, - appInstance->getFaceshift(), + DependencyManager::get(), SLOT(setTCPEnabled(bool))); #endif #ifdef HAVE_VISAGE addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Visage, 0, false, - appInstance->getVisage(), SLOT(updateEnabled())); + DependencyManager::get(), SLOT(updateEnabled())); #endif addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 660ebfcbb3..42b3c968e1 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -10,6 +10,9 @@ #include +#include +#include +#include #include #include "Application.h" @@ -75,11 +78,13 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { // Only use face trackers when not playing back a recording. if (!myAvatar->isPlaying()) { FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); - if ((_isFaceshiftConnected = faceTracker)) { + DdeFaceTracker* dde = DependencyManager::get(); + Faceshift* faceshift = DependencyManager::get(); + + if ((_isFaceshiftConnected = (faceshift == faceTracker))) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); - _isFaceshiftConnected = true; - } else if (Application::getInstance()->getDDE()->isActive()) { - faceTracker = Application::getInstance()->getDDE(); + } else if (dde->isActive()) { + faceTracker = dde; _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); } } @@ -196,14 +201,14 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { _mouth2 = glm::mix(_audioJawOpen * MMMM_POWER, _mouth2, MMMM_PERIOD + randFloat() * MMMM_RANDOM_PERIOD); _mouth4 = glm::mix(_audioJawOpen, _mouth4, SMILE_PERIOD + randFloat() * SMILE_RANDOM_PERIOD); - Application::getInstance()->getFaceshift()->updateFakeCoefficients(_leftEyeBlink, - _rightEyeBlink, - _browAudioLift, - _audioJawOpen, - _mouth2, - _mouth3, - _mouth4, - _blendshapeCoefficients); + DependencyManager::get()->updateFakeCoefficients(_leftEyeBlink, + _rightEyeBlink, + _browAudioLift, + _audioJawOpen, + _mouth2, + _mouth3, + _mouth4, + _blendshapeCoefficients); } else { _saccade = glm::vec3(); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 32053ea076..17cda19980 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -421,8 +422,7 @@ void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bo } void MyAvatar::renderHeadMouse(int screenWidth, int screenHeight) const { - - Faceshift* faceshift = Application::getInstance()->getFaceshift(); + Faceshift* faceshift = DependencyManager::get(); float pixelsPerDegree = screenHeight / Menu::getInstance()->getFieldOfView(); diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 68d9e7d487..d80aa043e4 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -14,16 +14,14 @@ #include +#include + #include "FaceTracker.h" -class DdeFaceTracker : public FaceTracker { +class DdeFaceTracker : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: - DdeFaceTracker(); - DdeFaceTracker(const QHostAddress& host, quint16 port); - ~DdeFaceTracker(); - //initialization void init(); void reset(); @@ -57,6 +55,11 @@ private slots: void socketStateChanged(QAbstractSocket::SocketState socketState); private: + DdeFaceTracker(); + DdeFaceTracker(const QHostAddress& host, quint16 port); + ~DdeFaceTracker(); + friend DependencyManager; + float getBlendshapeCoefficient(int index) const; void decodePacket(const QByteArray& buffer); diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h index 459f38cafc..75954871e5 100644 --- a/interface/src/devices/FaceTracker.h +++ b/interface/src/devices/FaceTracker.h @@ -23,8 +23,8 @@ class FaceTracker : public QObject { Q_OBJECT public: - FaceTracker(); + virtual ~FaceTracker() {} const glm::vec3& getHeadTranslation() const { return _headTranslation; } const glm::quat& getHeadRotation() const { return _headRotation; } diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index fb74f416a9..5c1bbfe709 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -14,7 +14,6 @@ #include #include -#include "Application.h" #include "Faceshift.h" #include "Menu.h" #include "Util.h" diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 3b4092c099..3cca8f2bb1 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -19,15 +19,15 @@ #include #endif +#include + #include "FaceTracker.h" /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. -class Faceshift : public FaceTracker { +class Faceshift : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: - Faceshift(); - void init(); bool isConnectedOrConnecting() const; @@ -87,6 +87,9 @@ private slots: void readFromSocket(); private: + Faceshift(); + virtual ~Faceshift() {} + friend DependencyManager; float getBlendshapeCoefficient(int index) const; diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 9c7416c219..51b927df75 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -11,12 +11,14 @@ #include + +#include +#include #include #include -#include - #include "Application.h" +#include "Faceshift.h" #include "Visage.h" // this has to go after our normal includes, because its definition of HANDLE conflicts with Qt's @@ -119,7 +121,7 @@ static const QMultiHash >& getActionUnitNameMap() const float TRANSLATION_SCALE = 20.0f; void Visage::init() { - connect(Application::getInstance()->getFaceshift(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); + connect(DependencyManager::get(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); updateEnabled(); } @@ -171,7 +173,7 @@ void Visage::reset() { void Visage::updateEnabled() { setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && - Application::getInstance()->getFaceshift()->isConnectedOrConnecting())); + DependencyManager::get()->isConnectedOrConnecting())); } void Visage::setEnabled(bool enabled) { diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 33e2f0a7e1..73edddc4d7 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -16,6 +16,8 @@ #include #include +#include + #include "FaceTracker.h" namespace VisageSDK { @@ -24,14 +26,10 @@ namespace VisageSDK { } /// Handles input from the Visage webcam feature tracking software. -class Visage : public FaceTracker { +class Visage : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: - - Visage(); - virtual ~Visage(); - void init(); bool isActive() const { return _active; } @@ -44,6 +42,9 @@ public slots: void updateEnabled(); private: + Visage(); + virtual ~Visage(); + friend DependencyManager; #ifdef HAVE_VISAGE VisageSDK::VisageTracker2* _tracker; diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp new file mode 100644 index 0000000000..c858cb7059 --- /dev/null +++ b/libraries/shared/src/DependencyManager.cpp @@ -0,0 +1,24 @@ +// +// DependencyManager.cpp +// +// +// Created by Clément Brisset on 12/10/14. +// Copyright 2014 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 "DependencyManager.h" + +DependencyManager& DependencyManager::getInstance() { + static DependencyManager instance; + return instance; +} + +DependencyManager::~DependencyManager() { + foreach (Dependency* instance, _instanceHash) { + delete instance; + } + _instanceHash.clear(); +} \ No newline at end of file diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h new file mode 100644 index 0000000000..87c7c7b4a6 --- /dev/null +++ b/libraries/shared/src/DependencyManager.h @@ -0,0 +1,66 @@ +// +// DependencyManager.h +// +// +// Created by Clément Brisset on 12/10/14. +// Copyright 2014 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_DependencyManager_h +#define hifi_DependencyManager_h + +#include +#include + +#include +#include + +class DependencyManager { +public: + // Only accessible method. + // usage: T* instance = DependencyManager::get(); + template + static T* get(); + + // Any class T in the DependencyManager needs to subclass Dependency + // They also need to have protected constructor(s) and virtual destructor + // As well as declare DependencyManager a friend class + class Dependency { + protected: + Dependency() {} + virtual ~Dependency() {} // Ensure the proper destruction of the object + friend DependencyManager; + }; + +private: + static DependencyManager& getInstance(); + DependencyManager() {} + ~DependencyManager(); + + typedef QHash InstanceHash; + static InstanceHash& getInstanceHash() { return getInstance()._instanceHash; } + InstanceHash _instanceHash; +}; + +template +T* DependencyManager::get() { + const QString& typeId = typeid(T).name(); + + // Search the hash for global instance + Dependency* instance = getInstanceHash().value(typeId, NULL); + if (instance) { + return dynamic_cast(instance); + } + + // Found no instance in hash so we create one. + T* newInstance = new T(); + instance = dynamic_cast(newInstance); + assert(instance != NULL); // If this triggers, check that T is derived from Dependency + getInstanceHash().insert(typeId, instance); + return newInstance; +} + +#endif // hifi_DependencyManager_h