diff --git a/BUILD.md b/BUILD.md
index 93aafcc3e0..32c35a4c2b 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -262,3 +262,8 @@ If you need to debug Interface, you can run interface from within Visual Studio
* In the Solution Explorer, right click interface and click Set as StartUp Project
* Set the "Working Directory" for the Interface debugging sessions to the Debug output directory so that your application can load resources. Do this: right click interface and click Properties, choose Debugging from Configuration Properties, set Working Directory to .\Debug
* Now you can run and debug interface through Visual Studio
+
+#### Devices
+
+You can support external input/output devices such as Leap Motion, Faceplus, Faceshift PrioVR, RTmidi, SixSense and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in /hifi/interface/external/ for the detailed explanation of the requirements to use the device.
+
diff --git a/cmake/modules/FindLeapMotion.cmake b/cmake/modules/FindLeapMotion.cmake
new file mode 100644
index 0000000000..40958ece95
--- /dev/null
+++ b/cmake/modules/FindLeapMotion.cmake
@@ -0,0 +1,47 @@
+# Try to find the LeapMotion library
+#
+# You must provide a LEAPMOTION_ROOT_DIR which contains lib and include directories
+#
+# Once done this will define
+#
+# LEAPMOTION_FOUND - system found LEAPMOTION
+# LEAPMOTION_INCLUDE_DIRS - the LEAPMOTION include directory
+# LEAPMOTION_LIBRARIES - Link this to use LEAPMOTION
+#
+# Created on 6/2/2014 by Sam Cake
+# Copyright (c) 2014 High Fidelity
+#
+
+if (LEAPMOTION_LIBRARIES AND LEAPMOTION_INCLUDE_DIRS)
+ # in cache already
+ set(LEAPMOTION_FOUND TRUE)
+else (LEAPMOTION_LIBRARIES AND LEAPMOTION_INCLUDE_DIRS)
+ set(LEAPMOTION_SEARCH_DIRS "${LEAPMOTION_ROOT_DIR}" "$ENV{HIFI_LIB_DIR}/leapmotion")
+
+ find_path(LEAPMOTION_INCLUDE_DIRS Leap.h PATH_SUFFIXES include HINTS ${LEAPMOTION_SEARCH_DIRS})
+
+ if (WIN32)
+ find_library(LEAPMOTION_LIBRARIES "lib/x86/Leap.lib" HINTS ${LEAPMOTION_SEARCH_DIRS})
+ endif (WIN32)
+ if (APPLE)
+ find_library(LEAPMOTION_LIBRARIES "lib/libLeap.dylib" HINTS ${LEAPMOTION_SEARCH_DIRS})
+ endif (APPLE)
+
+ if (LEAPMOTION_INCLUDE_DIRS AND LEAPMOTION_LIBRARIES)
+ set(LEAPMOTION_FOUND TRUE)
+ endif (LEAPMOTION_INCLUDE_DIRS AND LEAPMOTION_LIBRARIES)
+
+ if (LEAPMOTION_FOUND)
+ if (NOT LEAPMOTION_FIND_QUIETLY)
+ message(STATUS "Found LEAPMOTION... ${LEAPMOTION_LIBRARIES}")
+ endif (NOT LEAPMOTION_FIND_QUIETLY)
+ else ()
+ if (LEAPMOTION_FIND_REQUIRED)
+ message(FATAL_ERROR "Could not find LEAPMOTION")
+ endif (LEAPMOTION_FIND_REQUIRED)
+ endif ()
+
+ # show the LEAPMOTION_INCLUDE_DIRS and LEAPMOTION_LIBRARIES variables only in the advanced view
+ mark_as_advanced(LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES)
+
+endif (LEAPMOTION_LIBRARIES AND LEAPMOTION_INCLUDE_DIRS)
diff --git a/examples/leapOfFaith.js b/examples/leapOfFaith.js
new file mode 100644
index 0000000000..4e6bb708bb
--- /dev/null
+++ b/examples/leapOfFaith.js
@@ -0,0 +1,258 @@
+//
+// leapOfFaith.js
+// examples
+//
+// Created by Sam Cake on 6/22/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
+//
+
+
+
+
+
+var jointList = MyAvatar.getJointNames();
+var jointMappings = "\n# Joint list start";
+for (var i = 0; i < jointList.length; i++) {
+ jointMappings = jointMappings + "\njointIndex = " + jointList[i] + " = " + i;
+}
+print(jointMappings + "\n# Joint list end");
+
+function vec3ToString( v ) {
+ return ("(" + v.x +", " + v.y + ", " + v.z + ")" );
+}
+function quatToString( q ) {
+ return ("(" + q.x +", " + q.y + ", " + q.z + ", " + q.w + ")" );
+}
+
+function printSpatialEvent( label, spatialEvent ) {
+ if ( false ){//label == "RightHandIndex1" ) {
+ var dataString = label + " " +
+ /*vec3ToString( spatialEvent.locTranslation ) + " " +
+ quatToString( spatialEvent.locRotation ) + " " +*/
+ vec3ToString( spatialEvent.absTranslation ) + " " +
+ quatToString( spatialEvent.absRotation );
+ print( dataString );
+ }
+}
+
+function avatarToWorldPos( apos ) {
+
+ // apply offset ?
+ var offset = { x: 0, y: 0.5, z: -0.5 };
+ var lpos = Vec3.sum(apos, offset);
+
+ var wpos = Vec3.sum( MyAvatar.position , Vec3.multiplyQbyV(MyAvatar.orientation, lpos) );
+
+ return wpos;
+}
+
+function avatarToWorldQuat( aori) {
+
+ var wori = Quat.multiply(MyAvatar.orientation, aori);
+ return wori;
+}
+
+function controlerToSkeletonOri( jointName, isRightSide, event ) {
+
+ var qAvatarRootOffset = Quat.angleAxis( -180, {x:0, y:1, z:0});
+ var qAxisOffset = Quat.angleAxis( -( 2 * isRightSide - 1) * 90, {x:0, y:1, z:0});
+ var qAbsJoint = event.absRotation;
+
+
+ return Quat.multiply( qAvatarRootOffset, Quat.multiply( qAbsJoint, qAxisOffset ) );
+}
+
+
+var jointParticles = [];
+function updateJointParticle( joint, pos, ori, look ) {
+ /* print( "debug 1" );
+ var jointID = jointParticles[ joint ];
+ if ( jointID == null ) {
+ print( "debug create " + joint );
+*/
+ var radius = 0.005* look.r;
+ var ballProperties = {
+ position: pos,
+ velocity: { x: 0, y: 0, z: 0},
+ gravity: { x: 0, y: 0, z: 0 },
+ damping: 0,
+ radius : radius,
+ color: look.c,
+ lifetime: 0.05
+ };
+ var atomPos = Particles.addParticle(ballProperties);
+
+/* // Zaxis
+ var Zaxis = Vec3.multiply( Quat.getFront( ori ), - 1.5 * radius ) ;
+ ballProperties.position = Vec3.sum(pos, Zaxis );
+ ballProperties.radius = 0.35* radius;
+ ballProperties.color= { red: 255, green: 255, blue: 255 };
+
+ var atomZ = Particles.addParticle(ballProperties);
+
+ var up = Vec3.multiply( Quat.getUp( ori ), 1.5 * radius ) ;
+ ballProperties.position = Vec3.sum(pos, up) ;
+ ballProperties.radius = 0.35* radius;
+ ballProperties.color= { red: 0, green: 255, blue: 0 };
+
+ var atomY = Particles.addParticle(ballProperties);
+
+ var right = Vec3.multiply( Quat.getRight( ori ), 1.5 * radius ) ;
+ ballProperties.position = Vec3.sum(pos, right) ;
+ ballProperties.radius = 0.35* radius;
+ ballProperties.color= { red: 255, green: 0, blue: 225 };
+
+ var atomX = Particles.addParticle(ballProperties);
+*/
+ // jointParticles[ joint ] = { p: atomPos, x: atomX, y: atomY, z: atomZ };
+/*
+ } else {
+ //print( "debug update " + joint );
+
+ var p = Particles.getParticleProperties( jointID.p );
+ p.position = pos;
+ // p.lifetime = 1.0;
+ Particles.editParticle( jointID.p, p );
+
+
+ }*/
+}
+
+function evalArmBoneLook( isRightSide, bone ) {
+ return { c: { red: (255 * ( 1 - isRightSide )),
+ green: 255 * ( ((bone)) / 2 ),
+ blue: (255 * isRightSide) },
+ r: 3 ,
+ side: isRightSide };
+}
+
+function evalFingerBoneLook( isRightSide, finger, bone ) {
+ return { c: { red: (255 * ( 1 - isRightSide )),
+ green: 255 * ( ((bone - 1)) / 3 ),
+ blue: (255 * isRightSide) },
+ r: (5 + (5 - (finger-1))) / 10.0,
+ side: isRightSide };
+}
+
+var leapJoints = [
+
+ { n: "joint_L_elbow", l: evalArmBoneLook( 0, 2) },
+ { n: "joint_L_hand", l: evalArmBoneLook( 0, 1) },
+ { n: "joint_L_wrist", l: evalArmBoneLook( 0, 0) },
+
+ { n: "joint_L_thumb2", l: evalFingerBoneLook( 0, 1, 2) },
+ { n: "joint_L_thumb3", l: evalFingerBoneLook( 0, 1, 3) },
+ { n: "joint_L_thumb4", l: evalFingerBoneLook( 0, 1, 4) },
+
+ { n: "joint_L_index1", l: evalFingerBoneLook( 0, 2, 1) },
+ { n: "joint_L_index2", l: evalFingerBoneLook( 0, 2, 2) },
+ { n: "joint_L_index3", l: evalFingerBoneLook( 0, 2, 3) },
+ { n: "joint_L_index4", l: evalFingerBoneLook( 0, 2, 4) },
+
+ { n: "joint_L_middle1", l: evalFingerBoneLook( 0, 3, 1) },
+ { n: "joint_L_middle2", l: evalFingerBoneLook( 0, 3, 2) },
+ { n: "joint_L_middle3", l: evalFingerBoneLook( 0, 3, 3) },
+ { n: "joint_L_middle4", l: evalFingerBoneLook( 0, 3, 4) },
+
+ { n: "joint_L_ring1", l: evalFingerBoneLook( 0, 4, 1) },
+ { n: "joint_L_ring2", l: evalFingerBoneLook( 0, 4, 2) },
+ { n: "joint_L_ring3", l: evalFingerBoneLook( 0, 4, 3) },
+ { n: "joint_L_ring4", l: evalFingerBoneLook( 0, 4, 4) },
+
+ { n: "joint_L_pinky1", l: evalFingerBoneLook( 0, 5, 1) },
+ { n: "joint_L_pinky2", l: evalFingerBoneLook( 0, 5, 2) },
+ { n: "joint_L_pinky3", l: evalFingerBoneLook( 0, 5, 3) },
+ { n: "joint_L_pinky4", l: evalFingerBoneLook( 0, 5, 4) },
+
+ { n: "joint_R_elbow", l: evalArmBoneLook( 1, 2) },
+ { n: "joint_R_hand", l: evalArmBoneLook( 1, 1) },
+ { n: "joint_R_wrist", l: evalArmBoneLook( 1, 0) },
+
+ { n: "joint_R_thumb2", l: evalFingerBoneLook( 1, 1, 2) },
+ { n: "joint_R_thumb3", l: evalFingerBoneLook( 1, 1, 3) },
+ { n: "joint_R_thumb4", l: evalFingerBoneLook( 1, 1, 4) },
+
+ { n: "joint_R_index1", l: evalFingerBoneLook( 1, 2, 1) },
+ { n: "joint_R_index2", l: evalFingerBoneLook( 1, 2, 2) },
+ { n: "joint_R_index3", l: evalFingerBoneLook( 1, 2, 3) },
+ { n: "joint_R_index4", l: evalFingerBoneLook( 1, 2, 4) },
+
+ { n: "joint_R_middle1", l: evalFingerBoneLook( 1, 3, 1) },
+ { n: "joint_R_middle2", l: evalFingerBoneLook( 1, 3, 2) },
+ { n: "joint_R_middle3", l: evalFingerBoneLook( 1, 3, 3) },
+ { n: "joint_R_middle4", l: evalFingerBoneLook( 1, 3, 4) },
+
+ { n: "joint_R_ring1", l: evalFingerBoneLook( 1, 4, 1) },
+ { n: "joint_R_ring2", l: evalFingerBoneLook( 1, 4, 2) },
+ { n: "joint_R_ring3", l: evalFingerBoneLook( 1, 4, 3) },
+ { n: "joint_R_ring4", l: evalFingerBoneLook( 1, 4, 4) },
+
+ { n: "joint_R_pinky1", l: evalFingerBoneLook( 1, 5, 1) },
+ { n: "joint_R_pinky2", l: evalFingerBoneLook( 1, 5, 2) },
+ { n: "joint_R_pinky3", l: evalFingerBoneLook( 1, 5, 3) },
+ { n: "joint_R_pinky4", l: evalFingerBoneLook( 1, 5, 4) },
+
+ ];
+
+function onSpatialEventHandler( jointName, look ) {
+ var _jointName = jointName;
+ var _look = look;
+ var _side = look.side;
+ return (function( spatialEvent ) {
+
+ // THis should be the call to update the skeleton joint from
+ // the absolute joint transform coming from the Leap controller
+ // WE need a new method on MyAvatar which will ultimately call
+ // state.setRotationFromBindFrame(rotation, priority) in
+ // Avatar::simulate=>void Model::setJointState(int index, bool valid, const glm::quat& rotation, float priority)
+
+ // MyAvatar.setJointRotationFromBindSpace(_jointName, controlerToSkeletonOri( _jointName, _side, spatialEvent ));
+
+
+ updateJointParticle(_jointName,
+ avatarToWorldPos( spatialEvent.absTranslation ),
+ avatarToWorldQuat( spatialEvent.absRotation ),
+ _look );
+ printSpatialEvent(_jointName, spatialEvent );
+ });
+}
+
+var isPullingSpatialData = true;
+
+var jointControllers = [];
+for ( i in leapJoints ) {
+
+ print( leapJoints[i].n );
+ // In the current implementation, the LEapmotion is the only "Spatial" device
+ // Each jointTracker is retreived from the joint name following the rigging convention
+ var controller = Controller.createInputController( "Spatial", leapJoints[i].n );
+ var handler = onSpatialEventHandler( leapJoints[i].n, leapJoints[i].l );
+ jointControllers.push( { c: controller, h: handler } );
+
+ if ( ! isPullingSpatialData ) {
+ controller.spatialEvent.connect( handler );
+ }
+}
+
+
+Script.update.connect(function(deltaTime) {
+
+ if ( isPullingSpatialData )
+ {
+ for ( i in jointControllers ) {
+ if ( jointControllers[i].c.isActive() ) {
+ var spatialEvent = { absTranslation: jointControllers[i].c.getAbsTranslation(),
+ absRotation: jointControllers[i].c.getAbsRotation(),
+ locTranslation: jointControllers[i].c.getLocTranslation(),
+ locRotation: jointControllers[i].c.getLocRotation() };
+ jointControllers[i].h( spatialEvent );
+ }
+ }
+ }
+});
+
+Script.scriptEnding.connect(function() {
+});
diff --git a/images/bg_hr.png b/images/bg_hr.png
new file mode 100644
index 0000000000..7973bd6988
Binary files /dev/null and b/images/bg_hr.png differ
diff --git a/images/blacktocat.png b/images/blacktocat.png
new file mode 100644
index 0000000000..6e264fe57a
Binary files /dev/null and b/images/blacktocat.png differ
diff --git a/images/body-bg.png b/images/body-bg.png
new file mode 100644
index 0000000000..d0618fe749
Binary files /dev/null and b/images/body-bg.png differ
diff --git a/images/highlight-bg.jpg b/images/highlight-bg.jpg
new file mode 100644
index 0000000000..4c4a78effb
Binary files /dev/null and b/images/highlight-bg.jpg differ
diff --git a/images/hr.png b/images/hr.png
new file mode 100644
index 0000000000..6c723a5602
Binary files /dev/null and b/images/hr.png differ
diff --git a/images/icon_download.png b/images/icon_download.png
new file mode 100644
index 0000000000..a2a287f642
Binary files /dev/null and b/images/icon_download.png differ
diff --git a/images/octocat-icon.png b/images/octocat-icon.png
new file mode 100644
index 0000000000..f0ba137d26
Binary files /dev/null and b/images/octocat-icon.png differ
diff --git a/images/sprite_download.png b/images/sprite_download.png
new file mode 100644
index 0000000000..f2babd575d
Binary files /dev/null and b/images/sprite_download.png differ
diff --git a/images/tar-gz-icon.png b/images/tar-gz-icon.png
new file mode 100644
index 0000000000..d50f34f6de
Binary files /dev/null and b/images/tar-gz-icon.png differ
diff --git a/images/zip-icon.png b/images/zip-icon.png
new file mode 100644
index 0000000000..162c425b43
Binary files /dev/null and b/images/zip-icon.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000000..992030cad3
--- /dev/null
+++ b/index.html
@@ -0,0 +1,52 @@
+
+
+
+
+
+ Hifi by highfidelity
+
+
+
+
+
+
+
+
+
+
Hifi
+
Open, decentralized virtual worlds using sensors to control avatars and dynamically assigned devices as servers. San Francisco based startup, we are hiring: http://highfidelity.io/jobs You can also contribute by doing jobs listed at http://worklist.net -
+
+
+
+
\ No newline at end of file
diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt
index 49a6da7438..a5d1b0193e 100644
--- a/interface/CMakeLists.txt
+++ b/interface/CMakeLists.txt
@@ -18,8 +18,10 @@ set(LIBOVR_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/oculus")
set(PRIOVR_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/priovr")
set(SIXENSE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/Sixense")
set(VISAGE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/visage")
+set(LEAPMOTION_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/leapmotion")
set(RTMIDI_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/rtmidi")
+
find_package(Qt5LinguistTools REQUIRED)
find_package(Qt5LinguistToolsMacros)
@@ -139,6 +141,7 @@ find_package(PrioVR)
find_package(SDL)
find_package(Sixense)
find_package(Visage)
+find_package(LeapMotion)
find_package(ZLIB)
find_package(Qxmpp)
find_package(RtMidi)
@@ -199,6 +202,17 @@ if (PRIOVR_FOUND AND NOT DISABLE_PRIOVR)
target_link_libraries(${TARGET_NAME} "${PRIOVR_LIBRARIES}")
endif (PRIOVR_FOUND AND NOT DISABLE_PRIOVR)
+# and with LeapMotion library
+if (LEAPMOTION_FOUND AND NOT DISABLE_LEAPMOTION)
+ add_definitions(-DHAVE_LEAPMOTION)
+ include_directories(SYSTEM "${LEAPMOTION_INCLUDE_DIRS}")
+
+ if (APPLE OR UNIX)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${LEAPMOTION_INCLUDE_DIRS}")
+ endif ()
+ target_link_libraries(${TARGET_NAME} "${LEAPMOTION_LIBRARIES}")
+endif (LEAPMOTION_FOUND AND NOT DISABLE_LEAPMOTION)
+
# and with SDL for joysticks
if (SDL_FOUND AND NOT DISABLE_SDL)
add_definitions(-DHAVE_SDL)
diff --git a/interface/external/leapmotion/readme.txt b/interface/external/leapmotion/readme.txt
new file mode 100644
index 0000000000..51a65caf22
--- /dev/null
+++ b/interface/external/leapmotion/readme.txt
@@ -0,0 +1,33 @@
+
+Instructions for adding the Leap Motion library (LeapSDK) to Interface
+Sam Cake, June 10, 2014
+
+You can download the Leap Developer Kit from https://developer.leapmotion.com/ (account creation required).
+Interface has been tested with SDK versions:
+ - LeapDeveloperKit_2.0.3+17004_win
+ - LeapDeveloperKit_2.0.3+17004_mac
+
+1. Copy the LeapSDK folders from the LeapDeveloperKit installation directory (Lib, Include) into the interface/externals/leapmotion folder.
+ This readme.txt should be there as well.
+
+ The files neeeded in the folders are:
+
+ include/
+ - Leap.h
+ - Leap.i
+ - LeapMath.h
+
+ lib/
+ x86/
+ - Leap.dll
+ - Leap.lib
+ - mscvcp120.dll (optional if you already have the Msdev 2012 SDK redistriuable installed)
+ - mscvcr120.dll (optional if you already have the Msdev 2012 SDK redistriuable installed)
+ - lipLeap.dylib
+ libc++/
+ -libLeap.dylib
+
+ You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects).
+ If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'leapmotion' that contains the 2 folders mentioned above (Include, Lib).
+
+2. Clear your build directory, run cmake and build, and you should be all set.
\ No newline at end of file
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index bc6db5d7b6..1d5cbabd32 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -89,6 +89,8 @@
#include "ui/Stats.h"
#include "ui/TextRenderer.h"
+#include "devices/Leapmotion.h"
+
using namespace std;
// Starfield information
@@ -1720,6 +1722,8 @@ void Application::init() {
_faceplus.init();
_visage.init();
+ Leapmotion::init();
+
// fire off an immediate domain-server check in now that settings are loaded
NodeList::getInstance()->sendDomainServerCheckIn();
@@ -2053,11 +2057,13 @@ void Application::update(float deltaTime) {
updateMouseRay(); // check what's under the mouse and update the mouse voxel
{
PerformanceTimer perfTimer("devices");
+ DeviceTracker::updateAll();
updateFaceshift();
updateVisage();
_sixenseManager.update(deltaTime);
_joystickManager.update();
_prioVR.update(deltaTime);
+
}
{
PerformanceTimer perfTimer("myAvatar");
@@ -2065,6 +2071,10 @@ void Application::update(float deltaTime) {
updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
}
+
+ // Dispatch input events
+ _controllerScriptingInterface.updateInputControllers();
+
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
_avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...
@@ -3177,6 +3187,7 @@ void Application::resetSensors() {
OculusManager::reset();
_prioVR.reset();
+ //_leapmotion.reset();
QCursor::setPos(_mouseX, _mouseY);
_myAvatar->reset();
diff --git a/interface/src/devices/DeviceTracker.cpp b/interface/src/devices/DeviceTracker.cpp
new file mode 100644
index 0000000000..47301ad826
--- /dev/null
+++ b/interface/src/devices/DeviceTracker.cpp
@@ -0,0 +1,88 @@
+//
+// DeviceTracker.cpp
+// interface/src/devices
+//
+// Created by Sam Cake on 6/20/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 "DeviceTracker.h"
+
+DeviceTracker::SingletonData::~SingletonData() {
+ // Destroy all the device registered
+ //TODO C++11 for (auto device = _devicesVector.begin(); device != _devicesVector.end(); device++) {
+ for (Vector::iterator device = _devicesVector.begin(); device != _devicesVector.end(); device++) {
+ delete (*device);
+ }
+}
+
+int DeviceTracker::getNumDevices() {
+ return Singleton::get()->_devicesMap.size();
+}
+
+DeviceTracker::ID DeviceTracker::getDeviceID(const Name& name) {
+ //TODO C++11 auto deviceIt = Singleton::get()->_devicesMap.find(name);
+ Map::iterator deviceIt = Singleton::get()->_devicesMap.find(name);
+ if (deviceIt != Singleton::get()->_devicesMap.end()) {
+ return (*deviceIt).second;
+ } else {
+ return INVALID_DEVICE;
+ }
+}
+
+DeviceTracker* DeviceTracker::getDevice(const Name& name) {
+ return getDevice(getDeviceID(name));
+}
+
+DeviceTracker* DeviceTracker::getDevice(DeviceTracker::ID deviceID) {
+ if ((deviceID >= 0) && (deviceID < Singleton::get()->_devicesVector.size())) {
+ return Singleton::get()->_devicesVector[ deviceID ];
+ } else {
+ return NULL;
+ }
+}
+
+DeviceTracker::ID DeviceTracker::registerDevice(const Name& name, DeviceTracker* device) {
+ // Check that the device exists, if not exit
+ if (!device) {
+ return INVALID_DEVICE;
+ }
+
+ // Look if the name is not already used
+ ID deviceID = getDeviceID(name);
+ if (deviceID >= 0) {
+ return INVALID_DEVICE_NAME;
+ }
+
+ // Good to register the device
+ deviceID = Singleton::get()->_devicesVector.size();
+ Singleton::get()->_devicesMap.insert(Map::value_type(name, deviceID));
+ Singleton::get()->_devicesVector.push_back(device);
+ device->assignIDAndName(deviceID, name);
+
+ return deviceID;
+}
+
+void DeviceTracker::updateAll() {
+ //TODO C++11 for (auto deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) {
+ for (Vector::iterator deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) {
+ if ((*deviceIt))
+ (*deviceIt)->update();
+ }
+}
+
+// Core features of the Device Tracker
+DeviceTracker::DeviceTracker() :
+ _ID(INVALID_DEVICE),
+ _name("Unkown")
+{
+}
+
+DeviceTracker::~DeviceTracker() {
+}
+
+void DeviceTracker::update() {
+}
diff --git a/interface/src/devices/DeviceTracker.h b/interface/src/devices/DeviceTracker.h
new file mode 100644
index 0000000000..2e0f69b371
--- /dev/null
+++ b/interface/src/devices/DeviceTracker.h
@@ -0,0 +1,114 @@
+//
+// DeviceTracker.h
+// interface/src/devices
+//
+// Created by Sam Cake on 6/20/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_DeviceTracker_h
+#define hifi_DeviceTracker_h
+
+#include
+#include
+#include