From 3f99e70af0698cd21ecb8d925a3b8821e53e977c Mon Sep 17 00:00:00 2001
From: Bradley Austin Davis <bdavis@saintandreas.org>
Date: Mon, 16 Oct 2017 14:20:31 -0700
Subject: [PATCH 1/6] C++ cleanup for pointers / picking

---
 interface/CMakeLists.txt                      |   1 +
 interface/src/raypick/JointRayPick.cpp        |   1 -
 interface/src/raypick/JointRayPick.h          |   2 +-
 interface/src/raypick/LaserPointer.cpp        | 126 ++++++--------
 interface/src/raypick/LaserPointer.h          |  22 +--
 interface/src/raypick/LaserPointerManager.cpp | 160 +++++++----------
 interface/src/raypick/LaserPointerManager.h   |  34 ++--
 .../LaserPointerScriptingInterface.cpp        |  19 +-
 .../raypick/LaserPointerScriptingInterface.h  |  30 ++--
 interface/src/raypick/MouseRayPick.h          |   2 +-
 interface/src/raypick/RayPick.cpp             |  62 -------
 interface/src/raypick/RayPickManager.cpp      | 162 ++++++++----------
 interface/src/raypick/RayPickManager.h        |  35 ++--
 .../src/raypick/RayPickScriptingInterface.cpp |  34 +---
 .../src/raypick/RayPickScriptingInterface.h   |  29 ++--
 libraries/pointers/CMakeLists.txt             |   5 +
 .../pointers/src/pointers/PointerManager.cpp  |   1 +
 .../pointers/src/pointers/PointerManager.h    |  29 ++++
 .../pointers/src/pointers/rays/RayPick.cpp    |  75 ++++++++
 .../pointers/src/pointers/rays}/RayPick.h     | 103 ++++++-----
 .../src/pointers/rays}/StaticRayPick.cpp      |   3 -
 .../src/pointers/rays}/StaticRayPick.h        |   3 -
 22 files changed, 454 insertions(+), 484 deletions(-)
 delete mode 100644 interface/src/raypick/RayPick.cpp
 create mode 100644 libraries/pointers/CMakeLists.txt
 create mode 100644 libraries/pointers/src/pointers/PointerManager.cpp
 create mode 100644 libraries/pointers/src/pointers/PointerManager.h
 create mode 100644 libraries/pointers/src/pointers/rays/RayPick.cpp
 rename {interface/src/raypick => libraries/pointers/src/pointers/rays}/RayPick.h (63%)
 rename {interface/src/raypick => libraries/pointers/src/pointers/rays}/StaticRayPick.cpp (92%)
 rename {interface/src/raypick => libraries/pointers/src/pointers/rays}/StaticRayPick.h (92%)

diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt
index b16ad58431..764e5ef201 100644
--- a/interface/CMakeLists.txt
+++ b/interface/CMakeLists.txt
@@ -198,6 +198,7 @@ endif()
 # link required hifi libraries
 link_hifi_libraries(
   shared octree ktx gpu gl gpu-gl procedural model render
+  pointers
   recording fbx networking model-networking entities avatars trackers
   audio audio-client animation script-engine physics
   render-utils entities-renderer avatars-renderer ui auto-updater midi
diff --git a/interface/src/raypick/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp
index b4f0dde687..cf3f380ca0 100644
--- a/interface/src/raypick/JointRayPick.cpp
+++ b/interface/src/raypick/JointRayPick.cpp
@@ -10,7 +10,6 @@
 //
 #include "JointRayPick.h"
 
-#include "DependencyManager.h"
 #include "avatar/AvatarManager.h"
 
 JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) :
diff --git a/interface/src/raypick/JointRayPick.h b/interface/src/raypick/JointRayPick.h
index 3cd622fbbe..e3e5670e20 100644
--- a/interface/src/raypick/JointRayPick.h
+++ b/interface/src/raypick/JointRayPick.h
@@ -11,7 +11,7 @@
 #ifndef hifi_JointRayPick_h
 #define hifi_JointRayPick_h
 
-#include "RayPick.h"
+#include <pointers/rays/RayPick.h>
 
 class JointRayPick : public RayPick {
 
diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp
index 0e0f13cd6c..7fa5eaed5f 100644
--- a/interface/src/raypick/LaserPointer.cpp
+++ b/interface/src/raypick/LaserPointer.cpp
@@ -11,8 +11,8 @@
 #include "LaserPointer.h"
 
 #include "Application.h"
-#include "ui/overlays/Overlay.h"
 #include "avatar/AvatarManager.h"
+#include "RayPickScriptingInterface.h"
 
 LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
         const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) :
@@ -21,9 +21,10 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende
     _defaultRenderStates(defaultRenderStates),
     _faceAvatar(faceAvatar),
     _centerEndY(centerEndY),
-    _lockEnd(lockEnd)
+    _lockEnd(lockEnd),
+    _rayPickUID(DependencyManager::get<RayPickScriptingInterface>()->createRayPick(rayProps))
 {
-    _rayPickUID = DependencyManager::get<RayPickScriptingInterface>()->createRayPick(rayProps);
+    
 
     for (auto& state : _renderStates) {
         if (!enabled || state.first != _currentRenderState) {
@@ -38,7 +39,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende
 }
 
 LaserPointer::~LaserPointer() {
-    DependencyManager::get<RayPickScriptingInterface>()->removeRayPick(_rayPickUID);
+    qApp->getRayPickManager().removeRayPick(_rayPickUID);
 
     for (auto& renderState : _renderStates) {
         renderState.second.deleteOverlays();
@@ -49,43 +50,47 @@ LaserPointer::~LaserPointer() {
 }
 
 void LaserPointer::enable() {
-    QWriteLocker lock(getLock());
-    DependencyManager::get<RayPickScriptingInterface>()->enableRayPick(_rayPickUID);
-    _renderingEnabled = true;
+    qApp->getRayPickManager().enableRayPick(_rayPickUID);
+    withWriteLock([&] {
+        _renderingEnabled = true;
+    });
 }
 
 void LaserPointer::disable() {
-    QWriteLocker lock(getLock());
-    DependencyManager::get<RayPickScriptingInterface>()->disableRayPick(_rayPickUID);
+    qApp->getRayPickManager().disableRayPick(_rayPickUID);
     _renderingEnabled = false;
-    if (!_currentRenderState.empty()) {
-        if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
-            disableRenderState(_renderStates[_currentRenderState]);
+    withWriteLock([&] {
+        if (!_currentRenderState.empty()) {
+            if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
+                disableRenderState(_renderStates[_currentRenderState]);
+            }
+            if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
+                disableRenderState(_defaultRenderStates[_currentRenderState].second);
+            }
         }
-        if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
-            disableRenderState(_defaultRenderStates[_currentRenderState].second);
-        }
-    }
+    });
 }
 
 void LaserPointer::setRenderState(const std::string& state) {
-    QWriteLocker lock(getLock());
-    if (!_currentRenderState.empty() && state != _currentRenderState) {
-        if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
-            disableRenderState(_renderStates[_currentRenderState]);
+    withWriteLock([&] {
+        if (!_currentRenderState.empty() && state != _currentRenderState) {
+            if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
+                disableRenderState(_renderStates[_currentRenderState]);
+            }
+            if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
+                disableRenderState(_defaultRenderStates[_currentRenderState].second);
+            }
         }
-        if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
-            disableRenderState(_defaultRenderStates[_currentRenderState].second);
-        }
-    }
-    _currentRenderState = state;
+        _currentRenderState = state;
+    });
 }
 
 void LaserPointer::editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) {
-    QWriteLocker lock(getLock());
-    updateRenderStateOverlay(_renderStates[state].getStartID(), startProps);
-    updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps);
-    updateRenderStateOverlay(_renderStates[state].getEndID(), endProps);
+    withWriteLock([&] {
+        updateRenderStateOverlay(_renderStates[state].getStartID(), startProps);
+        updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps);
+        updateRenderStateOverlay(_renderStates[state].getEndID(), endProps);
+    });
 }
 
 void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) {
@@ -97,7 +102,6 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant&
 }
 
 const RayPickResult LaserPointer::getPrevRayPickResult() {
-    QReadLocker lock(getLock());
     return DependencyManager::get<RayPickScriptingInterface>()->getPrevRayPickResult(_rayPickUID);
 }
 
@@ -193,65 +197,41 @@ void LaserPointer::disableRenderState(const RenderState& renderState) {
 
 void LaserPointer::update() {
     // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
-    QReadLocker lock(getLock());
-    RayPickResult prevRayPickResult = DependencyManager::get<RayPickScriptingInterface>()->getPrevRayPickResult(_rayPickUID);
-    if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
+    withReadLock([&] {
+        RayPickResult prevRayPickResult = qApp->getRayPickManager().getPrevRayPickResult(_rayPickUID);
+        if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
             (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) {
-        float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance;
-        updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false);
-        disableRenderState(_defaultRenderStates[_currentRenderState].second);
-    } else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
-        disableRenderState(_renderStates[_currentRenderState]);
-        updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true);
-    } else if (!_currentRenderState.empty()) {
-        disableRenderState(_renderStates[_currentRenderState]);
-        disableRenderState(_defaultRenderStates[_currentRenderState].second);
-    }
+            float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance;
+            updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false);
+            disableRenderState(_defaultRenderStates[_currentRenderState].second);
+        } else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
+            disableRenderState(_renderStates[_currentRenderState]);
+            updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true);
+        } else if (!_currentRenderState.empty()) {
+            disableRenderState(_renderStates[_currentRenderState]);
+            disableRenderState(_defaultRenderStates[_currentRenderState].second);
+        }
+    });
 }
 
 void LaserPointer::setPrecisionPicking(const bool precisionPicking) {
-    QWriteLocker lock(getLock());
-    DependencyManager::get<RayPickScriptingInterface>()->setPrecisionPicking(_rayPickUID, precisionPicking);
+    qApp->getRayPickManager().setPrecisionPicking(_rayPickUID, precisionPicking);
 }
 
 void LaserPointer::setLaserLength(const float laserLength) {
-    QWriteLocker lock(getLock());
     _laserLength = laserLength;
 }
 
 void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) {
-    QWriteLocker lock(getLock());
     _objectLockEnd = std::pair<QUuid, bool>(objectID, isOverlay);
 }
 
-void LaserPointer::setIgnoreEntities(const QScriptValue& ignoreEntities) {
-    QWriteLocker lock(getLock());
-    DependencyManager::get<RayPickScriptingInterface>()->setIgnoreEntities(_rayPickUID, ignoreEntities);
+void LaserPointer::setIgnoreItems(const QVector<QUuid>& ignoreItems) const {
+    qApp->getRayPickManager().setIgnoreItems(_rayPickUID, ignoreItems);
 }
 
-void LaserPointer::setIncludeEntities(const QScriptValue& includeEntities) {
-    QWriteLocker lock(getLock());
-    DependencyManager::get<RayPickScriptingInterface>()->setIncludeEntities(_rayPickUID, includeEntities);
-}
-
-void LaserPointer::setIgnoreOverlays(const QScriptValue& ignoreOverlays) {
-    QWriteLocker lock(getLock());
-    DependencyManager::get<RayPickScriptingInterface>()->setIgnoreOverlays(_rayPickUID, ignoreOverlays);
-}
-
-void LaserPointer::setIncludeOverlays(const QScriptValue& includeOverlays) {
-    QWriteLocker lock(getLock());
-    DependencyManager::get<RayPickScriptingInterface>()->setIncludeOverlays(_rayPickUID, includeOverlays);
-}
-
-void LaserPointer::setIgnoreAvatars(const QScriptValue& ignoreAvatars) {
-    QWriteLocker lock(getLock());
-    DependencyManager::get<RayPickScriptingInterface>()->setIgnoreAvatars(_rayPickUID, ignoreAvatars);
-}
-
-void LaserPointer::setIncludeAvatars(const QScriptValue& includeAvatars) {
-    QWriteLocker lock(getLock());
-    DependencyManager::get<RayPickScriptingInterface>()->setIncludeAvatars(_rayPickUID, includeAvatars);
+void LaserPointer::setIncludeItems(const QVector<QUuid>& includeItems) const {
+    qApp->getRayPickManager().setIncludeItems(_rayPickUID, includeItems);
 }
 
 RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) :
diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h
index 01dfe01cfd..20ea824f50 100644
--- a/interface/src/raypick/LaserPointer.h
+++ b/interface/src/raypick/LaserPointer.h
@@ -12,10 +12,12 @@
 #define hifi_LaserPointer_h
 
 #include <QString>
-#include "glm/glm.hpp"
+#include <glm/glm.hpp>
 
 #include <DependencyManager.h>
-#include "raypick/RayPickScriptingInterface.h"
+#include <shared/ReadWriteLockable.h>
+
+#include "ui/overlays/Overlay.h"
 
 class RayPickResult;
 
@@ -44,9 +46,10 @@ private:
 };
 
 
-class LaserPointer {
+class LaserPointer : public ReadWriteLockable {
 
 public:
+    using Pointer = std::shared_ptr<LaserPointer>;
 
     typedef std::unordered_map<std::string, RenderState> RenderStateMap;
     typedef std::unordered_map<std::string, std::pair<float, RenderState>> DefaultRenderStateMap;
@@ -68,14 +71,8 @@ public:
     void setLaserLength(const float laserLength);
     void setLockEndUUID(QUuid objectID, const bool isOverlay);
 
-    void setIgnoreEntities(const QScriptValue& ignoreEntities);
-    void setIncludeEntities(const QScriptValue& includeEntities);
-    void setIgnoreOverlays(const QScriptValue& ignoreOverlays);
-    void setIncludeOverlays(const QScriptValue& includeOverlays);
-    void setIgnoreAvatars(const QScriptValue& ignoreAvatars);
-    void setIncludeAvatars(const QScriptValue& includeAvatars);
-
-    QReadWriteLock* getLock() { return &_lock; }
+    void setIgnoreItems(const QVector<QUuid>& ignoreItems) const;
+    void setIncludeItems(const QVector<QUuid>& includeItems) const;
 
     void update();
 
@@ -90,8 +87,7 @@ private:
     bool _lockEnd;
     std::pair<QUuid, bool> _objectLockEnd { std::pair<QUuid, bool>(QUuid(), false)};
 
-    QUuid _rayPickUID;
-    QReadWriteLock _lock;
+    const QUuid _rayPickUID;
 
     void updateRenderStateOverlay(const OverlayID& id, const QVariant& props);
     void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState);
diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp
index 8615a96c3f..f65a8a1a84 100644
--- a/interface/src/raypick/LaserPointerManager.cpp
+++ b/interface/src/raypick/LaserPointerManager.cpp
@@ -12,138 +12,110 @@
 
 QUuid LaserPointerManager::createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates,
     const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) {
+    QUuid result;
     std::shared_ptr<LaserPointer> laserPointer = std::make_shared<LaserPointer>(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled);
     if (!laserPointer->getRayUID().isNull()) {
-        QWriteLocker containsLock(&_containsLock);
-        QUuid id = QUuid::createUuid();
-        _laserPointers[id] = laserPointer;
-        return id;
+        result = QUuid::createUuid();
+        withWriteLock([&] { _laserPointers[result] = laserPointer; });
     }
-    return QUuid();
+    return result;
 }
 
-void LaserPointerManager::removeLaserPointer(const QUuid uid) {
-    QWriteLocker lock(&_containsLock);
-    _laserPointers.remove(uid);
+
+LaserPointer::Pointer LaserPointerManager::find(const QUuid& uid) const {
+    return resultWithReadLock<LaserPointer::Pointer>([&] {
+        auto itr = _laserPointers.find(uid);
+        if (itr != _laserPointers.end()) {
+            return *itr;
+        }
+        return LaserPointer::Pointer();
+    });
 }
 
-void LaserPointerManager::enableLaserPointer(const QUuid uid) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->enable();
+
+void LaserPointerManager::removeLaserPointer(const QUuid& uid) {
+    withWriteLock([&] {
+        _laserPointers.remove(uid);
+    });
+}
+
+void LaserPointerManager::enableLaserPointer(const QUuid& uid) const {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        laserPointer->enable();
     }
 }
 
-void LaserPointerManager::disableLaserPointer(const QUuid uid) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->disable();
+void LaserPointerManager::disableLaserPointer(const QUuid& uid) const  {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        laserPointer->disable();
     }
 }
 
-void LaserPointerManager::setRenderState(QUuid uid, const std::string& renderState) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setRenderState(renderState);
+void LaserPointerManager::setRenderState(const QUuid& uid, const std::string& renderState) const {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        laserPointer->setRenderState(renderState);
     }
 }
 
-void LaserPointerManager::editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->editRenderState(state, startProps, pathProps, endProps);
+void LaserPointerManager::editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        laserPointer->editRenderState(state, startProps, pathProps, endProps);
     }
 }
 
-const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        return laserPointer.value()->getPrevRayPickResult();
+const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid& uid) const {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        return laserPointer->getPrevRayPickResult();
     }
     return RayPickResult();
 }
 
 void LaserPointerManager::update() {
-    QReadLocker lock(&_containsLock);
-    for (QUuid& uid : _laserPointers.keys()) {
-        auto laserPointer = _laserPointers.find(uid);
-        laserPointer.value()->update();
+    auto cachedLaserPointers = resultWithReadLock<QList<std::shared_ptr<LaserPointer>>>([&] { 
+        return _laserPointers.values(); 
+    });
+
+    for (const auto& laserPointer : cachedLaserPointers) {
+        laserPointer->update();
     }
 }
 
-void LaserPointerManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setPrecisionPicking(precisionPicking);
+void LaserPointerManager::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        laserPointer->setPrecisionPicking(precisionPicking);
     }
 }
 
-void LaserPointerManager::setLaserLength(QUuid uid, const float laserLength) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setLaserLength(laserLength);
+void LaserPointerManager::setLaserLength(const QUuid& uid, const float laserLength) const {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        laserPointer->setLaserLength(laserLength);
     }
 }
 
-void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setIgnoreEntities(ignoreEntities);
+void LaserPointerManager::setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignoreEntities) const {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        laserPointer->setIgnoreItems(ignoreEntities);
     }
 }
 
-void LaserPointerManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setIncludeEntities(includeEntities);
+void LaserPointerManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& includeEntities) const {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        laserPointer->setIncludeItems(includeEntities);
     }
 }
 
-void LaserPointerManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setIgnoreOverlays(ignoreOverlays);
-    }
-}
-
-void LaserPointerManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setIncludeOverlays(includeOverlays);
-    }
-}
-
-void LaserPointerManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setIgnoreAvatars(ignoreAvatars);
-    }
-}
-
-void LaserPointerManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setIncludeAvatars(includeAvatars);
-    }
-}
-
-void LaserPointerManager::setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) {
-    QReadLocker lock(&_containsLock);
-    auto laserPointer = _laserPointers.find(uid);
-    if (laserPointer != _laserPointers.end()) {
-        laserPointer.value()->setLockEndUUID(objectID, isOverlay);
+void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const {
+    auto laserPointer = find(uid);
+    if (laserPointer) {
+        laserPointer->setLockEndUUID(objectID, isOverlay);
     }
 }
diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h
index b841877578..a4689cf16d 100644
--- a/interface/src/raypick/LaserPointerManager.h
+++ b/interface/src/raypick/LaserPointerManager.h
@@ -14,39 +14,37 @@
 #include <memory>
 #include <glm/glm.hpp>
 
+#include <shared/ReadWriteLockable.h>
+
 #include "LaserPointer.h"
 
 class RayPickResult;
 
-class LaserPointerManager {
+
+class LaserPointerManager : protected ReadWriteLockable {
 
 public:
     QUuid createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates,
         const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled);
-    void removeLaserPointer(const QUuid uid);
-    void enableLaserPointer(const QUuid uid);
-    void disableLaserPointer(const QUuid uid);
-    void setRenderState(QUuid uid, const std::string& renderState);
-    void editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
-    const RayPickResult getPrevRayPickResult(const QUuid uid);
+    void removeLaserPointer(const QUuid& uid);
+    void enableLaserPointer(const QUuid& uid) const;
+    void disableLaserPointer(const QUuid& uid) const;
+    void setRenderState(const QUuid& uid, const std::string& renderState) const;
+    void editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const;
+    const RayPickResult getPrevRayPickResult(const QUuid& uid) const;
 
-    void setPrecisionPicking(QUuid uid, const bool precisionPicking);
-    void setLaserLength(QUuid uid, const float laserLength);
-    void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
-    void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
-    void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
-    void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays);
-    void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
-    void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
+    void setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const;
+    void setLaserLength(const QUuid& uid, const float laserLength) const;
+    void setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignoreEntities) const;
+    void setIncludeItems(const QUuid& uid, const QVector<QUuid>& includeEntities) const;
 
-    void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay);
+    void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const;
 
     void update();
 
 private:
+    LaserPointer::Pointer find(const QUuid& uid) const;
     QHash<QUuid, std::shared_ptr<LaserPointer>> _laserPointers;
-    QReadWriteLock _containsLock;
-
 };
 
 #endif // hifi_LaserPointerManager_h
diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp
index d5e435f490..96839160fa 100644
--- a/interface/src/raypick/LaserPointerScriptingInterface.cpp
+++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp
@@ -11,10 +11,19 @@
 
 #include "LaserPointerScriptingInterface.h"
 
-#include <QVariant>
-#include "GLMHelpers.h"
+#include <QtCore/QVariant>
 
-QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) {
+#include <GLMHelpers.h>
+#include <RegisteredMetaTypes.h>
+
+void LaserPointerScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) const { 
+    qApp->getLaserPointerManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
+}
+void LaserPointerScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) const {
+    qApp->getLaserPointerManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); 
+}
+
+QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) const {
     QVariantMap propertyMap = properties.toMap();
 
     bool faceAvatar = false;
@@ -69,7 +78,7 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert
     return qApp->getLaserPointerManager().createLaserPointer(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled);
 }
 
-void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& renderState, const QVariant& properties) {
+void LaserPointerScriptingInterface::editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const {
     QVariantMap propMap = properties.toMap();
 
     QVariant startProps;
@@ -90,7 +99,7 @@ void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& r
     qApp->getLaserPointerManager().editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps);
 }
 
-const RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) {
+RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) {
     QUuid startID;
     if (propMap["start"].isValid()) {
         QVariantMap startMap = propMap["start"].toMap();
diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h
index 2f6da87b5f..19262e6e5d 100644
--- a/interface/src/raypick/LaserPointerScriptingInterface.h
+++ b/interface/src/raypick/LaserPointerScriptingInterface.h
@@ -22,27 +22,23 @@ class LaserPointerScriptingInterface : public QObject, public Dependency {
     SINGLETON_DEPENDENCY
 
 public slots:
-    Q_INVOKABLE QUuid createLaserPointer(const QVariant& properties);
-    Q_INVOKABLE void enableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().enableLaserPointer(uid); }
-    Q_INVOKABLE void disableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().disableLaserPointer(uid); }
-    Q_INVOKABLE void removeLaserPointer(QUuid uid) { qApp->getLaserPointerManager().removeLaserPointer(uid); }
-    Q_INVOKABLE void editRenderState(QUuid uid, const QString& renderState, const QVariant& properties);
-    Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
-    Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
+    Q_INVOKABLE QUuid createLaserPointer(const QVariant& properties) const;
+    Q_INVOKABLE void enableLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().enableLaserPointer(uid); }
+    Q_INVOKABLE void disableLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().disableLaserPointer(uid); }
+    Q_INVOKABLE void removeLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().removeLaserPointer(uid); }
+    Q_INVOKABLE void editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const;
+    Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
+    Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) const { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
 
-    Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking) { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); }
-    Q_INVOKABLE void setLaserLength(QUuid uid, const float laserLength) { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); }
-    Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); }
-    Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { qApp->getLaserPointerManager().setIncludeEntities(uid, includeEntities); }
-    Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { qApp->getLaserPointerManager().setIgnoreOverlays(uid, ignoreOverlays); }
-    Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { qApp->getLaserPointerManager().setIncludeOverlays(uid, includeOverlays); }
-    Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { qApp->getLaserPointerManager().setIgnoreAvatars(uid, ignoreAvatars); }
-    Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { qApp->getLaserPointerManager().setIncludeAvatars(uid, includeAvatars); }
+    Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); }
+    Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); }
+    Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities) const;
+    Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities) const;
 
-    Q_INVOKABLE void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); }
+    Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); }
 
 private:
-    const RenderState buildRenderState(const QVariantMap& propMap);
+    static RenderState buildRenderState(const QVariantMap& propMap);
 
 };
 
diff --git a/interface/src/raypick/MouseRayPick.h b/interface/src/raypick/MouseRayPick.h
index 848a5de336..47f9404f3a 100644
--- a/interface/src/raypick/MouseRayPick.h
+++ b/interface/src/raypick/MouseRayPick.h
@@ -11,7 +11,7 @@
 #ifndef hifi_MouseRayPick_h
 #define hifi_MouseRayPick_h
 
-#include "RayPick.h"
+#include <pointers/rays/RayPick.h>
 
 class MouseRayPick : public RayPick {
 
diff --git a/interface/src/raypick/RayPick.cpp b/interface/src/raypick/RayPick.cpp
deleted file mode 100644
index a5b1299210..0000000000
--- a/interface/src/raypick/RayPick.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-//  RayPick.cpp
-//  interface/src/raypick
-//
-//  Created by Sam Gondelman 7/11/2017
-//  Copyright 2017 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 "RayPick.h"
-
-RayPick::RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) :
-    _filter(filter),
-    _maxDistance(maxDistance),
-    _enabled(enabled)
-{
-}
-void RayPick::enable() {
-    QWriteLocker lock(getLock());
-    _enabled = true;
-}
-
-void RayPick::disable() {
-    QWriteLocker lock(getLock());
-    _enabled = false;
-}
-
-const RayPickResult& RayPick::getPrevRayPickResult() {
-    QReadLocker lock(getLock());
-    return _prevResult;
-}
-
-void RayPick::setIgnoreEntities(const QScriptValue& ignoreEntities) {
-    QWriteLocker lock(getLock());
-    _ignoreEntities = qVectorEntityItemIDFromScriptValue(ignoreEntities);
-}
-
-void RayPick::setIncludeEntities(const QScriptValue& includeEntities) {
-    QWriteLocker lock(getLock());
-    _includeEntities = qVectorEntityItemIDFromScriptValue(includeEntities);
-}
-
-void RayPick::setIgnoreOverlays(const QScriptValue& ignoreOverlays) {
-    QWriteLocker lock(getLock());
-    _ignoreOverlays = qVectorOverlayIDFromScriptValue(ignoreOverlays);
-}
-
-void RayPick::setIncludeOverlays(const QScriptValue& includeOverlays) {
-    QWriteLocker lock(getLock());
-    _includeOverlays = qVectorOverlayIDFromScriptValue(includeOverlays);
-}
-
-void RayPick::setIgnoreAvatars(const QScriptValue& ignoreAvatars) {
-    QWriteLocker lock(getLock());
-    _ignoreAvatars = qVectorEntityItemIDFromScriptValue(ignoreAvatars);
-}
-
-void RayPick::setIncludeAvatars(const QScriptValue& includeAvatars) {
-    QWriteLocker lock(getLock());
-    _includeAvatars = qVectorEntityItemIDFromScriptValue(includeAvatars);
-}
\ No newline at end of file
diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp
index 1728ecd01a..f3425a2b28 100644
--- a/interface/src/raypick/RayPickManager.cpp
+++ b/interface/src/raypick/RayPickManager.cpp
@@ -10,6 +10,8 @@
 //
 #include "RayPickManager.h"
 
+#include <pointers/rays/StaticRayPick.h>
+
 #include "Application.h"
 #include "EntityScriptingInterface.h"
 #include "ui/overlays/Overlays.h"
@@ -18,7 +20,6 @@
 #include "DependencyManager.h"
 
 #include "JointRayPick.h"
-#include "StaticRayPick.h"
 #include "MouseRayPick.h"
 
 bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask) {
@@ -43,20 +44,26 @@ void RayPickManager::cacheResult(const bool intersects, const RayPickResult& res
 }
 
 void RayPickManager::update() {
-    QReadLocker lock(&_containsLock);
     RayPickCache results;
-    for (auto& uid : _rayPicks.keys()) {
-        std::shared_ptr<RayPick> rayPick = _rayPicks[uid];
-        QWriteLocker lock(rayPick->getLock());
+    QHash<QUuid, RayPick::Pointer> cachedRayPicks;
+    withReadLock([&] {
+        cachedRayPicks = _rayPicks;
+    });
+
+    for (const auto& uid : cachedRayPicks.keys()) {
+        std::shared_ptr<RayPick> rayPick = cachedRayPicks[uid];
         if (!rayPick->isEnabled() || rayPick->getFilter().doesPickNothing() || rayPick->getMaxDistance() < 0.0f) {
             continue;
         }
 
-        bool valid;
-        PickRay ray = rayPick->getPickRay(valid);
+        PickRay ray;
 
-        if (!valid) {
-            continue;
+        {
+            bool valid;
+            ray = rayPick->getPickRay(valid);
+            if (!valid) {
+                continue;
+            }
         }
 
         QPair<glm::vec3, glm::vec3> rayKey = QPair<glm::vec3, glm::vec3>(ray.origin, ray.direction);
@@ -69,8 +76,8 @@ void RayPickManager::update() {
             bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
             RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags();
             if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) {
-                entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
-                    rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !nonCollidable);
+                entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
+                    rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>(), !invisible, !nonCollidable);
                 fromCache = false;
             }
 
@@ -87,8 +94,8 @@ void RayPickManager::update() {
             bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
             RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags();
             if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) {
-                overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
-                    rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !nonCollidable);
+                overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
+                    rayPick->getIncludeItemsAs<OverlayID>(), rayPick->getIgnoreItemsAs<OverlayID>(), !invisible, !nonCollidable);
                 fromCache = false;
             }
 
@@ -101,7 +108,8 @@ void RayPickManager::update() {
         if (rayPick->getFilter().doesPickAvatars()) {
             RayPickFilter::Flags avatarMask = rayPick->getFilter().getAvatarFlags();
             if (!checkAndCompareCachedResults(rayKey, results, res, avatarMask)) {
-                RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars());
+                RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(ray, 
+                    rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>());
                 cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarMask, res, rayKey, results);
             }
         }
@@ -123,109 +131,87 @@ void RayPickManager::update() {
     }
 }
 
-QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) {
-    QWriteLocker lock(&_containsLock);
+QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, float maxDistance, bool enabled) {
+    auto newRayPick = std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
     QUuid id = QUuid::createUuid();
-    _rayPicks[id] = std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
+    withWriteLock([&] {
+        _rayPicks[id] = newRayPick;
+    });
     return id;
 }
 
-QUuid RayPickManager::createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) {
-    QWriteLocker lock(&_containsLock);
+QUuid RayPickManager::createRayPick(const RayPickFilter& filter, float maxDistance, bool enabled) {
     QUuid id = QUuid::createUuid();
-    _rayPicks[id] = std::make_shared<MouseRayPick>(filter, maxDistance, enabled);
+    auto newRayPick = std::make_shared<MouseRayPick>(filter, maxDistance, enabled);
+    withWriteLock([&] {
+        _rayPicks[id] = newRayPick;
+    });
     return id;
 }
 
-QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) {
-    QWriteLocker lock(&_containsLock);
+QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, float maxDistance, bool enabled) {
     QUuid id = QUuid::createUuid();
-    _rayPicks[id] = std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled);
+    auto newRayPick = std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled);
+    withWriteLock([&] {
+        _rayPicks[id] = newRayPick;
+    });
     return id;
 }
 
-void RayPickManager::removeRayPick(const QUuid uid) {
-    QWriteLocker lock(&_containsLock);
-    _rayPicks.remove(uid);
+void RayPickManager::removeRayPick(const QUuid& uid) {
+    withWriteLock([&] {
+        _rayPicks.remove(uid);
+    });
 }
 
-void RayPickManager::enableRayPick(const QUuid uid) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        rayPick.value()->enable();
+RayPick::Pointer RayPickManager::findRayPick(const QUuid& uid) const {
+    return resultWithReadLock<RayPick::Pointer>([&] {
+        if (_rayPicks.contains(uid)) {
+            return _rayPicks[uid];
+        }
+        return RayPick::Pointer();
+    });
+}
+
+void RayPickManager::enableRayPick(const QUuid& uid) const {
+    auto rayPick = findRayPick(uid);
+    if (rayPick) {
+        rayPick->enable();
     }
 }
 
-void RayPickManager::disableRayPick(const QUuid uid) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        rayPick.value()->disable();
+void RayPickManager::disableRayPick(const QUuid& uid) const {
+    auto rayPick = findRayPick(uid);
+    if (rayPick) {
+        rayPick->disable();
     }
 }
 
-const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        return rayPick.value()->getPrevRayPickResult();
+RayPickResult RayPickManager::getPrevRayPickResult(const QUuid& uid) const {
+    auto rayPick = findRayPick(uid);
+    if (rayPick) {
+        return rayPick->getPrevRayPickResult();
     }
     return RayPickResult();
 }
 
-void RayPickManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        rayPick.value()->setPrecisionPicking(precisionPicking);
+void RayPickManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const {
+    auto rayPick = findRayPick(uid);
+    if (rayPick) {
+        rayPick->setPrecisionPicking(precisionPicking);
     }
 }
 
-void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        rayPick.value()->setIgnoreEntities(ignoreEntities);
+void RayPickManager::setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const {
+    auto rayPick = findRayPick(uid);
+    if (rayPick) {
+        rayPick->setIgnoreItems(ignore);
     }
 }
 
-void RayPickManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        rayPick.value()->setIncludeEntities(includeEntities);
+void RayPickManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const {
+    auto rayPick = findRayPick(uid);
+    if (rayPick) {
+        rayPick->setIncludeItems(include);
     }
 }
-
-void RayPickManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        rayPick.value()->setIgnoreOverlays(ignoreOverlays);
-    }
-}
-
-void RayPickManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        rayPick.value()->setIncludeOverlays(includeOverlays);
-    }
-}
-
-void RayPickManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        rayPick.value()->setIgnoreAvatars(ignoreAvatars);
-    }
-}
-
-void RayPickManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
-    QReadLocker containsLock(&_containsLock);
-    auto rayPick = _rayPicks.find(uid);
-    if (rayPick != _rayPicks.end()) {
-        rayPick.value()->setIncludeAvatars(includeAvatars);
-    }
-}
\ No newline at end of file
diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h
index 974022eb4d..8c6c28ceab 100644
--- a/interface/src/raypick/RayPickManager.h
+++ b/interface/src/raypick/RayPickManager.h
@@ -11,19 +11,20 @@
 #ifndef hifi_RayPickManager_h
 #define hifi_RayPickManager_h
 
-#include "RayPick.h"
 
 #include <memory>
-#include <QtCore/QObject>
-
-#include "RegisteredMetaTypes.h"
-
 #include <unordered_map>
 #include <queue>
 
+#include <QtCore/QObject>
+
+#include <RegisteredMetaTypes.h>
+#include <pointers/rays/RayPick.h>
+
+
 class RayPickResult;
 
-class RayPickManager {
+class RayPickManager : protected ReadWriteLockable {
 
 public:
     void update();
@@ -31,22 +32,18 @@ public:
     QUuid createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled);
     QUuid createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled);
     QUuid createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled);
-    void removeRayPick(const QUuid uid);
-    void enableRayPick(const QUuid uid);
-    void disableRayPick(const QUuid uid);
-    const RayPickResult getPrevRayPickResult(const QUuid uid);
+    void removeRayPick(const QUuid& uid);
+    void enableRayPick(const QUuid& uid) const;
+    void disableRayPick(const QUuid& uid) const;
+    RayPickResult getPrevRayPickResult(const QUuid& uid) const;
 
-    void setPrecisionPicking(QUuid uid, const bool precisionPicking);
-    void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
-    void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
-    void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
-    void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays);
-    void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
-    void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
+    void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const;
+    void setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const;
+    void setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const;
 
 private:
-    QHash<QUuid, std::shared_ptr<RayPick>> _rayPicks;
-    QReadWriteLock _containsLock;
+    RayPick::Pointer findRayPick(const QUuid& uid) const;
+    QHash<QUuid, RayPick::Pointer> _rayPicks;
 
     typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayPickFilter::Flags, RayPickResult>> RayPickCache;
 
diff --git a/interface/src/raypick/RayPickScriptingInterface.cpp b/interface/src/raypick/RayPickScriptingInterface.cpp
index cb2b3e4471..621ae9b738 100644
--- a/interface/src/raypick/RayPickScriptingInterface.cpp
+++ b/interface/src/raypick/RayPickScriptingInterface.cpp
@@ -66,46 +66,30 @@ QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) {
     return QUuid();
 }
 
-void RayPickScriptingInterface::enableRayPick(QUuid uid) {
+void RayPickScriptingInterface::enableRayPick(const QUuid& uid) {
     qApp->getRayPickManager().enableRayPick(uid);
 }
 
-void RayPickScriptingInterface::disableRayPick(QUuid uid) {
+void RayPickScriptingInterface::disableRayPick(const QUuid& uid) {
     qApp->getRayPickManager().disableRayPick(uid);
 }
 
-void RayPickScriptingInterface::removeRayPick(QUuid uid) {
+void RayPickScriptingInterface::removeRayPick(const QUuid& uid) {
     qApp->getRayPickManager().removeRayPick(uid);
 }
 
-RayPickResult RayPickScriptingInterface::getPrevRayPickResult(QUuid uid) {
+RayPickResult RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) {
     return qApp->getRayPickManager().getPrevRayPickResult(uid);
 }
 
-void RayPickScriptingInterface::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
+void RayPickScriptingInterface::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) {
     qApp->getRayPickManager().setPrecisionPicking(uid, precisionPicking);
 }
 
-void RayPickScriptingInterface::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
-    qApp->getRayPickManager().setIgnoreEntities(uid, ignoreEntities);
+void RayPickScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) {
+    qApp->getRayPickManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
 }
 
-void RayPickScriptingInterface::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
-    qApp->getRayPickManager().setIncludeEntities(uid, includeEntities);
-}
-
-void RayPickScriptingInterface::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
-    qApp->getRayPickManager().setIgnoreOverlays(uid, ignoreOverlays);
-}
-
-void RayPickScriptingInterface::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
-    qApp->getRayPickManager().setIncludeOverlays(uid, includeOverlays);
-}
-
-void RayPickScriptingInterface::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
-    qApp->getRayPickManager().setIgnoreAvatars(uid, ignoreAvatars);
-}
-
-void RayPickScriptingInterface::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
-    qApp->getRayPickManager().setIncludeAvatars(uid, includeAvatars);
+void RayPickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) {
+    qApp->getRayPickManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
 }
diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h
index f7ed2e6fa6..59c5804d72 100644
--- a/interface/src/raypick/RayPickScriptingInterface.h
+++ b/interface/src/raypick/RayPickScriptingInterface.h
@@ -13,10 +13,9 @@
 
 #include <QtCore/QObject>
 
-#include "RegisteredMetaTypes.h"
-#include "DependencyManager.h"
-
-#include "RayPick.h"
+#include <RegisteredMetaTypes.h>
+#include <DependencyManager.h>
+#include <pointers/rays/RayPick.h>
 
 class RayPickScriptingInterface : public QObject, public Dependency {
     Q_OBJECT
@@ -38,25 +37,21 @@ class RayPickScriptingInterface : public QObject, public Dependency {
 
 public slots:
     Q_INVOKABLE QUuid createRayPick(const QVariant& properties);
-    Q_INVOKABLE void enableRayPick(QUuid uid);
-    Q_INVOKABLE void disableRayPick(QUuid uid);
-    Q_INVOKABLE void removeRayPick(QUuid uid);
-    Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid);
+    Q_INVOKABLE void enableRayPick(const QUuid& uid);
+    Q_INVOKABLE void disableRayPick(const QUuid& uid);
+    Q_INVOKABLE void removeRayPick(const QUuid& uid);
+    Q_INVOKABLE RayPickResult getPrevRayPickResult(const QUuid& uid);
 
-    Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking);
-    Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
-    Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
-    Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
-    Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays);
-    Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
-    Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
+    Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, const bool precisionPicking);
+    Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities);
+    Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities);
 
-    unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); }
+    unsigned int PICK_NOTHING() { return 0; }
     unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); }
     unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); }
     unsigned int PICK_AVATARS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_AVATARS); }
     unsigned int PICK_HUD() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_HUD); }
-    unsigned int PICK_COURSE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COURSE); }
+    unsigned int PICK_COARSE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COARSE); }
     unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); }
     unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); }
     unsigned int PICK_ALL_INTERSECTIONS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ALL_INTERSECTIONS); }
diff --git a/libraries/pointers/CMakeLists.txt b/libraries/pointers/CMakeLists.txt
new file mode 100644
index 0000000000..504484574c
--- /dev/null
+++ b/libraries/pointers/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(TARGET_NAME pointers)
+setup_hifi_library()
+GroupSources(src)
+link_hifi_libraries(shared)
+
diff --git a/libraries/pointers/src/pointers/PointerManager.cpp b/libraries/pointers/src/pointers/PointerManager.cpp
new file mode 100644
index 0000000000..dddc84279b
--- /dev/null
+++ b/libraries/pointers/src/pointers/PointerManager.cpp
@@ -0,0 +1 @@
+#include "PointerManager.h"
diff --git a/libraries/pointers/src/pointers/PointerManager.h b/libraries/pointers/src/pointers/PointerManager.h
new file mode 100644
index 0000000000..0a045997c2
--- /dev/null
+++ b/libraries/pointers/src/pointers/PointerManager.h
@@ -0,0 +1,29 @@
+//
+//  Created by Bradley Austin Davis on 2017/10/16
+//  Copyright 2013-2017 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_pointers_PointerManager_h
+#define hifi_pointers_PointerManager_h
+
+#include <DependencyManager.h>
+#include <PointerEvent.h>
+
+class PointerManager : public QObject, public Dependency {
+    Q_OBJECT
+    SINGLETON_DEPENDENCY
+public:
+
+signals:
+    void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent);
+    void triggerContinue(const QUuid& id, const PointerEvent& pointerEvent);
+    void triggerEnd(const QUuid& id, const PointerEvent& pointerEvent);
+
+    void hoverEnter(const QUuid& id, const PointerEvent& pointerEvent);
+    void hoverOver(const QUuid& id, const PointerEvent& pointerEvent);
+    void hoverLeave(const QUuid& id, const PointerEvent& pointerEvent);
+};
+
+#endif // hifi_RayPick_h
diff --git a/libraries/pointers/src/pointers/rays/RayPick.cpp b/libraries/pointers/src/pointers/rays/RayPick.cpp
new file mode 100644
index 0000000000..36756cdb79
--- /dev/null
+++ b/libraries/pointers/src/pointers/rays/RayPick.cpp
@@ -0,0 +1,75 @@
+//
+//  Created by Sam Gondelman 7/11/2017
+//  Copyright 2017 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 "RayPick.h"
+
+const RayPickFilter RayPickFilter::NOTHING;
+
+RayPick::RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) :
+    _filter(filter),
+    _maxDistance(maxDistance),
+    _enabled(enabled)
+{
+}
+
+void RayPick::enable(bool enabled) {
+    withWriteLock([&] {
+        _enabled = enabled;
+    });
+}
+
+RayPickFilter RayPick::getFilter() const { 
+    return resultWithReadLock<RayPickFilter>([&] {
+        return _filter;
+    });
+}
+
+float RayPick::getMaxDistance() const { 
+    return _maxDistance; 
+}
+
+bool RayPick::isEnabled() const { 
+    return _enabled; 
+}
+
+void RayPick::setPrecisionPicking(bool precisionPicking) { 
+    withWriteLock([&]{
+        _filter.setFlag(RayPickFilter::PICK_COARSE, !precisionPicking);
+    });
+}
+
+void RayPick::setRayPickResult(const RayPickResult& rayPickResult) {
+    withWriteLock([&] {
+        _prevResult = rayPickResult;
+    });
+}
+
+QVector<QUuid> RayPick::getIgnoreItems() const {
+    return _ignoreItems; 
+}
+
+QVector<QUuid> RayPick::getIncludeItems() const {
+    return _includeItems; 
+}
+
+RayPickResult RayPick::getPrevRayPickResult() const {
+    return resultWithReadLock<RayPickResult>([&] {
+        return _prevResult;
+    });
+}
+
+void RayPick::setIgnoreItems(const QVector<QUuid>& ignoreItems) {
+    withWriteLock([&] {
+        _ignoreItems = ignoreItems;
+    });
+}
+
+void RayPick::setIncludeItems(const QVector<QUuid>& includeItems) {
+    withWriteLock([&] {
+        _includeItems = includeItems;
+    });
+}
diff --git a/interface/src/raypick/RayPick.h b/libraries/pointers/src/pointers/rays/RayPick.h
similarity index 63%
rename from interface/src/raypick/RayPick.h
rename to libraries/pointers/src/pointers/rays/RayPick.h
index 6dacc084b4..3691ac9985 100644
--- a/interface/src/raypick/RayPick.h
+++ b/libraries/pointers/src/pointers/rays/RayPick.h
@@ -1,7 +1,4 @@
 //
-//  RayPick.h
-//  interface/src/raypick
-//
 //  Created by Sam Gondelman 7/11/2017
 //  Copyright 2017 High Fidelity, Inc.
 //
@@ -12,22 +9,22 @@
 #define hifi_RayPick_h
 
 #include <stdint.h>
-#include "RegisteredMetaTypes.h"
+#include <bitset>
 
-#include "EntityItemID.h"
-#include "ui/overlays/Overlay.h"
-#include <QReadWriteLock>
+#include <QtCore/QUuid>
+
+#include <RegisteredMetaTypes.h>
+#include <shared/ReadWriteLockable.h>
 
 class RayPickFilter {
 public:
     enum FlagBit {
-        PICK_NOTHING = 0,
-        PICK_ENTITIES,
+        PICK_ENTITIES = 0,
         PICK_OVERLAYS,
         PICK_AVATARS,
         PICK_HUD,
 
-        PICK_COURSE, // if not set, does precise intersection, otherwise, doesn't
+        PICK_COARSE, // if not set, does precise intersection, otherwise, doesn't
 
         PICK_INCLUDE_INVISIBLE, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements
         PICK_INCLUDE_NONCOLLIDABLE, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements
@@ -42,7 +39,7 @@ public:
     // The key is the Flags
     Flags _flags;
 
-    RayPickFilter() : _flags(getBitMask(PICK_NOTHING)) {}
+    RayPickFilter() {}
     RayPickFilter(const Flags& flags) : _flags(flags) {}
 
     bool operator== (const RayPickFilter& rhs) const { return _flags == rhs._flags; }
@@ -50,13 +47,13 @@ public:
 
     void setFlag(FlagBit flag, bool value) { _flags[flag] = value; }
 
-    bool doesPickNothing() const { return _flags[PICK_NOTHING]; }
+    bool doesPickNothing() const { return _flags == NOTHING._flags; }
     bool doesPickEntities() const { return _flags[PICK_ENTITIES]; }
     bool doesPickOverlays() const { return _flags[PICK_OVERLAYS]; }
     bool doesPickAvatars() const { return _flags[PICK_AVATARS]; }
     bool doesPickHUD() const { return _flags[PICK_HUD]; }
 
-    bool doesPickCourse() const { return _flags[PICK_COURSE]; }
+    bool doesPickCoarse() const { return _flags[PICK_COARSE]; }
     bool doesPickInvisible() const { return _flags[PICK_INCLUDE_INVISIBLE]; }
     bool doesPickNonCollidable() const { return _flags[PICK_INCLUDE_NONCOLLIDABLE]; }
 
@@ -71,8 +68,8 @@ public:
         if (doesPickNonCollidable()) {
             toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
         }
-        if (doesPickCourse()) {
-            toReturn |= getBitMask(PICK_COURSE);
+        if (doesPickCoarse()) {
+            toReturn |= getBitMask(PICK_COARSE);
         }
         return Flags(toReturn);
     }
@@ -84,66 +81,84 @@ public:
         if (doesPickNonCollidable()) {
             toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
         }
-        if (doesPickCourse()) {
-            toReturn |= getBitMask(PICK_COURSE);
+        if (doesPickCoarse()) {
+            toReturn |= getBitMask(PICK_COARSE);
         }
         return Flags(toReturn);
     }
     Flags getAvatarFlags() const { return Flags(getBitMask(PICK_AVATARS)); }
     Flags getHUDFlags() const { return Flags(getBitMask(PICK_HUD)); }
 
-    static unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
+    static constexpr unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
 
+    static const RayPickFilter NOTHING;
 };
 
-class RayPick {
+class RayPick : protected ReadWriteLockable {
 
 public:
+    using Pointer = std::shared_ptr<RayPick>;
+
     RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled);
 
     virtual const PickRay getPickRay(bool& valid) const = 0;
 
-    void enable();
-    void disable();
+    void enable(bool enabled = true);
+    void disable() { enable(false); }
 
-    const RayPickFilter& getFilter() { return _filter; }
-    float getMaxDistance() { return _maxDistance; }
-    bool isEnabled() { return _enabled; }
-    const RayPickResult& getPrevRayPickResult();
+    RayPickFilter getFilter() const;
+    float getMaxDistance() const;
+    bool isEnabled() const;
+    RayPickResult getPrevRayPickResult() const;
 
-    void setPrecisionPicking(bool precisionPicking) { _filter.setFlag(RayPickFilter::PICK_COURSE, !precisionPicking); }
+    void setPrecisionPicking(bool precisionPicking);
 
-    void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; }
+    void setRayPickResult(const RayPickResult& rayPickResult);
 
-    const QVector<EntityItemID>& getIgnoreEntites() { return _ignoreEntities; }
-    const QVector<EntityItemID>& getIncludeEntites() { return _includeEntities; }
-    const QVector<OverlayID>& getIgnoreOverlays() { return _ignoreOverlays; }
-    const QVector<OverlayID>& getIncludeOverlays() { return _includeOverlays; }
-    const QVector<EntityItemID>& getIgnoreAvatars() { return _ignoreAvatars; }
-    const QVector<EntityItemID>& getIncludeAvatars() { return _includeAvatars; }
+    QVector<QUuid> getIgnoreItems() const;
+    QVector<QUuid> getIncludeItems() const;
+
+    template <typename T> 
+    QVector<T> getIgnoreItemsAs() const {
+        QVector<T> result;
+        withReadLock([&] {
+            for (const auto& uid : _ignoreItems) {
+                result.push_back(uid);
+            }
+        });
+        return result;
+    }
+
+    template <typename T>
+    QVector<T> getIncludeItemsAs() const {
+        QVector<T> result;
+        withReadLock([&] {
+            for (const auto& uid : _includeItems) {
+                result.push_back(uid);
+            }
+        });
+        return result;
+    }
+
+    void setIgnoreItems(const QVector<QUuid>& items);
+    void setIncludeItems(const QVector<QUuid>& items);
+#if 0
     void setIgnoreEntities(const QScriptValue& ignoreEntities);
     void setIncludeEntities(const QScriptValue& includeEntities);
     void setIgnoreOverlays(const QScriptValue& ignoreOverlays);
     void setIncludeOverlays(const QScriptValue& includeOverlays);
     void setIgnoreAvatars(const QScriptValue& ignoreAvatars);
     void setIncludeAvatars(const QScriptValue& includeAvatars);
-
-    QReadWriteLock* getLock() { return &_lock; }
+#endif
 
 private:
     RayPickFilter _filter;
-    float _maxDistance;
+    const float _maxDistance;
     bool _enabled;
     RayPickResult _prevResult;
 
-    QVector<EntityItemID> _ignoreEntities;
-    QVector<EntityItemID> _includeEntities;
-    QVector<OverlayID> _ignoreOverlays;
-    QVector<OverlayID> _includeOverlays;
-    QVector<EntityItemID> _ignoreAvatars;
-    QVector<EntityItemID> _includeAvatars;
-
-    QReadWriteLock _lock;
+    QVector<QUuid> _ignoreItems;
+    QVector<QUuid> _includeItems;
 };
 
 #endif // hifi_RayPick_h
diff --git a/interface/src/raypick/StaticRayPick.cpp b/libraries/pointers/src/pointers/rays/StaticRayPick.cpp
similarity index 92%
rename from interface/src/raypick/StaticRayPick.cpp
rename to libraries/pointers/src/pointers/rays/StaticRayPick.cpp
index 89bcddb3df..e507341021 100644
--- a/interface/src/raypick/StaticRayPick.cpp
+++ b/libraries/pointers/src/pointers/rays/StaticRayPick.cpp
@@ -1,7 +1,4 @@
 //
-//  StaticRayPick.cpp
-//  interface/src/raypick
-//
 //  Created by Sam Gondelman 7/11/2017
 //  Copyright 2017 High Fidelity, Inc.
 //
diff --git a/interface/src/raypick/StaticRayPick.h b/libraries/pointers/src/pointers/rays/StaticRayPick.h
similarity index 92%
rename from interface/src/raypick/StaticRayPick.h
rename to libraries/pointers/src/pointers/rays/StaticRayPick.h
index fc09ee6a27..de5ec234a5 100644
--- a/interface/src/raypick/StaticRayPick.h
+++ b/libraries/pointers/src/pointers/rays/StaticRayPick.h
@@ -1,7 +1,4 @@
 //
-//  StaticRayPick.h
-//  interface/src/raypick
-//
 //  Created by Sam Gondelman 7/11/2017
 //  Copyright 2017 High Fidelity, Inc.
 //

From 429905de51d1f11ff9074f4797922b8c47f4b033 Mon Sep 17 00:00:00 2001
From: SamGondelman <samuel_gondelman@alumni.brown.edu>
Date: Mon, 16 Oct 2017 15:52:17 -0700
Subject: [PATCH 2/6] update scripts to use ignoreItems, fix caching bug

---
 interface/src/raypick/LaserPointer.cpp        | 10 +++--
 interface/src/raypick/RayPickManager.cpp      | 37 ++++++++++---------
 interface/src/raypick/RayPickManager.h        | 25 +++++++++++--
 .../src/raypick/RayPickScriptingInterface.h   |  2 +-
 .../pointers/src/pointers/PointerManager.h    |  2 +-
 .../pointers/src/pointers/rays/RayPick.h      |  8 ----
 .../controllers/controllerDispatcher.js       | 12 +++---
 .../controllerModules/inEditMode.js           |  9 ++++-
 .../controllerModules/overlayLaserInput.js    |  7 +++-
 .../controllers/controllerModules/teleport.js |  8 ++--
 scripts/system/controllers/grab.js            |  2 +-
 11 files changed, 76 insertions(+), 46 deletions(-)

diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp
index 7fa5eaed5f..a2f7c7a521 100644
--- a/interface/src/raypick/LaserPointer.cpp
+++ b/interface/src/raypick/LaserPointer.cpp
@@ -58,8 +58,8 @@ void LaserPointer::enable() {
 
 void LaserPointer::disable() {
     qApp->getRayPickManager().disableRayPick(_rayPickUID);
-    _renderingEnabled = false;
     withWriteLock([&] {
+        _renderingEnabled = false;
         if (!_currentRenderState.empty()) {
             if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
                 disableRenderState(_renderStates[_currentRenderState]);
@@ -219,11 +219,15 @@ void LaserPointer::setPrecisionPicking(const bool precisionPicking) {
 }
 
 void LaserPointer::setLaserLength(const float laserLength) {
-    _laserLength = laserLength;
+    withWriteLock([&] {
+        _laserLength = laserLength;
+    });
 }
 
 void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) {
-    _objectLockEnd = std::pair<QUuid, bool>(objectID, isOverlay);
+    withWriteLock([&] {
+        _objectLockEnd = std::pair<QUuid, bool>(objectID, isOverlay);
+    });
 }
 
 void LaserPointer::setIgnoreItems(const QVector<QUuid>& ignoreItems) const {
diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp
index f3425a2b28..beb0075428 100644
--- a/interface/src/raypick/RayPickManager.cpp
+++ b/interface/src/raypick/RayPickManager.cpp
@@ -22,24 +22,24 @@
 #include "JointRayPick.h"
 #include "MouseRayPick.h"
 
-bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask) {
-    if (cache.contains(ray) && cache[ray].find(mask) != cache[ray].end()) {
-        if (cache[ray][mask].distance < res.distance) {
-            res = cache[ray][mask];
+bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key) {
+    if (cache.contains(ray) && cache[ray].find(key) != cache[ray].end()) {
+        if (cache[ray][key].distance < res.distance) {
+            res = cache[ray][key];
         }
         return true;
     }
     return false;
 }
 
-void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache) {
+void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache) {
     if (intersects) {
-        cache[ray][mask] = resTemp;
+        cache[ray][key] = resTemp;
         if (resTemp.distance < res.distance) {
             res = resTemp;
         }
     } else {
-        cache[ray][mask] = RayPickResult(res.searchRay);
+        cache[ray][key] = RayPickResult(res.searchRay);
     }
 }
 
@@ -74,8 +74,8 @@ void RayPickManager::update() {
             bool fromCache = true;
             bool invisible = rayPick->getFilter().doesPickInvisible();
             bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
-            RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags();
-            if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) {
+            RayCacheKey entityKey = { rayPick->getFilter().getEntityFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
+            if (!checkAndCompareCachedResults(rayKey, results, res, entityKey)) {
                 entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
                     rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>(), !invisible, !nonCollidable);
                 fromCache = false;
@@ -83,7 +83,7 @@ void RayPickManager::update() {
 
             if (!fromCache) {
                 cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, ray, entityRes.surfaceNormal),
-                    entityMask, res, rayKey, results);
+                    entityKey, res, rayKey, results);
             }
         }
 
@@ -92,8 +92,8 @@ void RayPickManager::update() {
             bool fromCache = true;
             bool invisible = rayPick->getFilter().doesPickInvisible();
             bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
-            RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags();
-            if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) {
+            RayCacheKey overlayKey = { rayPick->getFilter().getOverlayFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
+            if (!checkAndCompareCachedResults(rayKey, results, res, overlayKey)) {
                 overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
                     rayPick->getIncludeItemsAs<OverlayID>(), rayPick->getIgnoreItemsAs<OverlayID>(), !invisible, !nonCollidable);
                 fromCache = false;
@@ -101,25 +101,26 @@ void RayPickManager::update() {
 
             if (!fromCache) {
                 cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, ray, overlayRes.surfaceNormal),
-                    overlayMask, res, rayKey, results);
+                    overlayKey, res, rayKey, results);
             }
         }
 
         if (rayPick->getFilter().doesPickAvatars()) {
-            RayPickFilter::Flags avatarMask = rayPick->getFilter().getAvatarFlags();
-            if (!checkAndCompareCachedResults(rayKey, results, res, avatarMask)) {
+            RayCacheKey avatarKey = { rayPick->getFilter().getAvatarFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
+            if (!checkAndCompareCachedResults(rayKey, results, res, avatarKey)) {
                 RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(ray, 
                     rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>());
-                cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarMask, res, rayKey, results);
+                cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarKey, res, rayKey, results);
             }
         }
 
         // Can't intersect with HUD in desktop mode
         if (rayPick->getFilter().doesPickHUD() && DependencyManager::get<HMDScriptingInterface>()->isHMDMode()) {
             RayPickFilter::Flags hudMask = rayPick->getFilter().getHUDFlags();
-            if (!checkAndCompareCachedResults(rayKey, results, res, hudMask)) {
+            RayCacheKey hudKey = { rayPick->getFilter().getHUDFlags() };
+            if (!checkAndCompareCachedResults(rayKey, results, res, hudKey)) {
                 glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(ray.origin, ray.direction);
-                cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudMask, res, rayKey, results);
+                cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudKey, res, rayKey, results);
             }
         }
 
diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h
index 8c6c28ceab..fd2c6f4a6b 100644
--- a/interface/src/raypick/RayPickManager.h
+++ b/interface/src/raypick/RayPickManager.h
@@ -24,6 +24,25 @@
 
 class RayPickResult;
 
+typedef struct RayCacheKey {
+    RayPickFilter::Flags mask;
+    QVector<QUuid> include;
+    QVector<QUuid> ignore;
+
+    bool operator==(const RayCacheKey& other) const {
+        return (mask == other.mask && include == other.include && ignore == other.ignore);
+    }
+} RayCacheKey;
+
+namespace std {
+    template <>
+    struct hash<RayCacheKey> {
+        size_t operator()(const RayCacheKey& k) const {
+            return ((hash<RayPickFilter::Flags>()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1);
+        }
+    };
+}
+
 class RayPickManager : protected ReadWriteLockable {
 
 public:
@@ -45,11 +64,11 @@ private:
     RayPick::Pointer findRayPick(const QUuid& uid) const;
     QHash<QUuid, RayPick::Pointer> _rayPicks;
 
-    typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayPickFilter::Flags, RayPickResult>> RayPickCache;
+    typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayCacheKey, RayPickResult>> RayPickCache;
 
     // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer
-    bool checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask);
-    void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache);
+    bool checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key);
+    void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache);
 };
 
 #endif // hifi_RayPickManager_h
\ No newline at end of file
diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h
index 59c5804d72..099103e4c5 100644
--- a/interface/src/raypick/RayPickScriptingInterface.h
+++ b/interface/src/raypick/RayPickScriptingInterface.h
@@ -24,7 +24,7 @@ class RayPickScriptingInterface : public QObject, public Dependency {
     Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT)
     Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT)
     Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT)
-    Q_PROPERTY(unsigned int PICK_COURSE READ PICK_COURSE CONSTANT)
+    Q_PROPERTY(unsigned int PICK_COARSE READ PICK_COARSE CONSTANT)
     Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT)
     Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT)
     Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT)
diff --git a/libraries/pointers/src/pointers/PointerManager.h b/libraries/pointers/src/pointers/PointerManager.h
index 0a045997c2..df21ab7cf2 100644
--- a/libraries/pointers/src/pointers/PointerManager.h
+++ b/libraries/pointers/src/pointers/PointerManager.h
@@ -26,4 +26,4 @@ signals:
     void hoverLeave(const QUuid& id, const PointerEvent& pointerEvent);
 };
 
-#endif // hifi_RayPick_h
+#endif // hifi_pointers_PointerManager_h
diff --git a/libraries/pointers/src/pointers/rays/RayPick.h b/libraries/pointers/src/pointers/rays/RayPick.h
index 3691ac9985..5a53891dc6 100644
--- a/libraries/pointers/src/pointers/rays/RayPick.h
+++ b/libraries/pointers/src/pointers/rays/RayPick.h
@@ -142,14 +142,6 @@ public:
 
     void setIgnoreItems(const QVector<QUuid>& items);
     void setIncludeItems(const QVector<QUuid>& items);
-#if 0
-    void setIgnoreEntities(const QScriptValue& ignoreEntities);
-    void setIncludeEntities(const QScriptValue& includeEntities);
-    void setIgnoreOverlays(const QScriptValue& ignoreOverlays);
-    void setIncludeOverlays(const QScriptValue& includeOverlays);
-    void setIgnoreAvatars(const QScriptValue& ignoreAvatars);
-    void setIncludeAvatars(const QScriptValue& includeAvatars);
-#endif
 
 private:
     RayPickFilter _filter;
diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js
index 9295f50518..2deef5f9fa 100644
--- a/scripts/system/controllers/controllerDispatcher.js
+++ b/scripts/system/controllers/controllerDispatcher.js
@@ -141,8 +141,11 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
         };
 
         this.setIgnoreTablet = function() {
-            RayPick.setIgnoreOverlays(_this.leftControllerRayPick, [HMD.tabletID]);
-            RayPick.setIgnoreOverlays(_this.rightControllerRayPick, [HMD.tabletID]);
+            if (HMD.tabletID !== this.tabletID) {
+                this.tabletID = HMD.tabletID;
+                RayPick.setIgnoreItems(_this.leftControllerRayPick, _this.blacklist.concat([HMD.tabletID]));
+                RayPick.setIgnoreItems(_this.rightControllerRayPick, _this.blacklist.concat([HMD.tabletID]));
+            }
         };
 
         this.update = function () {
@@ -367,9 +370,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
         };
 
         this.setBlacklist = function() {
-            RayPick.setIgnoreEntities(_this.leftControllerRayPick, this.blacklist);
-            RayPick.setIgnoreEntities(_this.rightControllerRayPick, this.blacklist);
-
+            RayPick.setIgnoreItems(_this.leftControllerRayPick, this.blacklist.concat(HMD.tabletID));
+            RayPick.setIgnoreItems(_this.rightControllerRayPick, this.blacklist.concat(HMD.tabletID));
         };
 
         var MAPPING_NAME = "com.highfidelity.controllerDispatcher";
diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js
index cbe64b1870..5049185827 100644
--- a/scripts/system/controllers/controllerModules/inEditMode.js
+++ b/scripts/system/controllers/controllerModules/inEditMode.js
@@ -134,6 +134,13 @@ Script.include("/~/system/libraries/utils.js");
 
             LaserPointers.enableLaserPointer(this.laserPointer);
             LaserPointers.setRenderState(this.laserPointer, this.mode);
+
+            if (HMD.tabletID !== this.tabletID || HMD.tabletButtonID !== this.tabletButtonID || HMD.tabletScreenID !== this.tabletScreenID) {
+                this.tabletID = HMD.tabletID;
+                this.tabletButtonID = HMD.tabletButtonID;
+                this.tabletScreenID = HMD.tabletScreenID;
+                LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID, HMD.tabletButtonID, HMD.tabletScreenID]);
+            }
         };
 
         this.pointingAtTablet = function(objectID) {
@@ -244,7 +251,7 @@ Script.include("/~/system/libraries/utils.js");
             defaultRenderStates: defaultRenderStates
         });
 
-        LaserPointers.setIgnoreOverlays(this.laserPointer, [HMD.tabletID, HMD.tabletButtonID, HMD.tabletScreenID]);
+        LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID, HMD.tabletButtonID, HMD.tabletScreenID]);
     }
 
     var leftHandInEditMode = new InEditMode(LEFT_HAND);
diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js
index 7dace85ec4..7c86a01c5d 100644
--- a/scripts/system/controllers/controllerModules/overlayLaserInput.js
+++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js
@@ -184,6 +184,11 @@ Script.include("/~/system/libraries/controllers.js");
 
             LaserPointers.enableLaserPointer(this.laserPointer);
             LaserPointers.setRenderState(this.laserPointer, this.mode);
+
+            if (HMD.tabletID !== this.tabletID) {
+                this.tabletID = HMD.tabletID;
+                LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID]);
+            }
         };
 
         this.processControllerTriggers = function(controllerData) {
@@ -378,7 +383,7 @@ Script.include("/~/system/libraries/controllers.js");
             defaultRenderStates: defaultRenderStates
         });
 
-        LaserPointers.setIgnoreOverlays(this.laserPointer, [HMD.tabletID]);
+        LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID]);
     }
 
     var leftOverlayLaserInput = new OverlayLaserInput(LEFT_HAND);
diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js
index d2717a1348..86ad9c56ca 100644
--- a/scripts/system/controllers/controllerModules/teleport.js
+++ b/scripts/system/controllers/controllerModules/teleport.js
@@ -347,10 +347,10 @@ Script.include("/~/system/libraries/controllers.js");
         };
 
         this.setIgnoreEntities = function(entitiesToIgnore) {
-            LaserPointers.setIgnoreEntities(this.teleportRayHandVisible, entitiesToIgnore);
-            LaserPointers.setIgnoreEntities(this.teleportRayHandInvisible, entitiesToIgnore);
-            LaserPointers.setIgnoreEntities(this.teleportRayHeadVisible, entitiesToIgnore);
-            LaserPointers.setIgnoreEntities(this.teleportRayHeadInvisible, entitiesToIgnore);
+            LaserPointers.setIgnoreItems(this.teleportRayHandVisible, entitiesToIgnore);
+            LaserPointers.setIgnoreItems(this.teleportRayHandInvisible, entitiesToIgnore);
+            LaserPointers.setIgnoreItems(this.teleportRayHeadVisible, entitiesToIgnore);
+            LaserPointers.setIgnoreItems(this.teleportRayHeadInvisible, entitiesToIgnore);
         };
     }
 
diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js
index 2f046cbce3..a1846e7ad7 100644
--- a/scripts/system/controllers/grab.js
+++ b/scripts/system/controllers/grab.js
@@ -263,7 +263,7 @@ function Grabber() {
         filter: RayPick.PICK_OVERLAYS,
         enabled: true
     });
-    RayPick.setIncludeOverlays(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
+    RayPick.setIncludeItems(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
     var renderStates = [{name: "grabbed", end: beacon}];
     this.mouseRayEntities = LaserPointers.createLaserPointer({
         joint: "Mouse",

From 2e69d2b1ad3576120aa917e462da5968fc59616d Mon Sep 17 00:00:00 2001
From: Sam Gondelman <samuel_gondelman@alumni.brown.edu>
Date: Tue, 17 Oct 2017 11:13:02 -0700
Subject: [PATCH 3/6] missed one scripting interface reference

---
 interface/src/raypick/LaserPointer.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp
index a2f7c7a521..320c2a6809 100644
--- a/interface/src/raypick/LaserPointer.cpp
+++ b/interface/src/raypick/LaserPointer.cpp
@@ -102,7 +102,7 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant&
 }
 
 const RayPickResult LaserPointer::getPrevRayPickResult() {
-    return DependencyManager::get<RayPickScriptingInterface>()->getPrevRayPickResult(_rayPickUID);
+    return qApp->getRayPickManager().getPrevRayPickResult(_rayPickUID);
 }
 
 void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState) {
@@ -262,4 +262,4 @@ void RenderState::deleteOverlays() {
     if (!_endID.isNull()) {
         qApp->getOverlays().deleteOverlay(_endID);
     }
-}
\ No newline at end of file
+}

From ba4f41b59a2780826a75ea54880b398c9437fdce Mon Sep 17 00:00:00 2001
From: SamGondelman <samuel_gondelman@alumni.brown.edu>
Date: Tue, 17 Oct 2017 12:03:59 -0700
Subject: [PATCH 4/6] fix warnings

---
 interface/src/raypick/RayPickManager.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp
index beb0075428..15489ce93d 100644
--- a/interface/src/raypick/RayPickManager.cpp
+++ b/interface/src/raypick/RayPickManager.cpp
@@ -116,8 +116,7 @@ void RayPickManager::update() {
 
         // Can't intersect with HUD in desktop mode
         if (rayPick->getFilter().doesPickHUD() && DependencyManager::get<HMDScriptingInterface>()->isHMDMode()) {
-            RayPickFilter::Flags hudMask = rayPick->getFilter().getHUDFlags();
-            RayCacheKey hudKey = { rayPick->getFilter().getHUDFlags() };
+            RayCacheKey hudKey = { rayPick->getFilter().getHUDFlags(), QVector<QUuid>(), QVector<QUuid>() };
             if (!checkAndCompareCachedResults(rayKey, results, res, hudKey)) {
                 glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(ray.origin, ray.direction);
                 cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudKey, res, rayKey, results);

From 50929b780d962eb35e76b2ad98b939036c9cff44 Mon Sep 17 00:00:00 2001
From: Bradley Austin Davis <bdavis@saintandreas.org>
Date: Tue, 17 Oct 2017 12:59:41 -0700
Subject: [PATCH 5/6] Add constructor to suppress warning

---
 libraries/pointers/src/pointers/PointerManager.cpp | 5 +++++
 libraries/pointers/src/pointers/PointerManager.h   | 1 +
 2 files changed, 6 insertions(+)

diff --git a/libraries/pointers/src/pointers/PointerManager.cpp b/libraries/pointers/src/pointers/PointerManager.cpp
index dddc84279b..63bd983420 100644
--- a/libraries/pointers/src/pointers/PointerManager.cpp
+++ b/libraries/pointers/src/pointers/PointerManager.cpp
@@ -1 +1,6 @@
 #include "PointerManager.h"
+
+PointerManager::PointerManager() {
+
+}
+
diff --git a/libraries/pointers/src/pointers/PointerManager.h b/libraries/pointers/src/pointers/PointerManager.h
index df21ab7cf2..16f854bff5 100644
--- a/libraries/pointers/src/pointers/PointerManager.h
+++ b/libraries/pointers/src/pointers/PointerManager.h
@@ -15,6 +15,7 @@ class PointerManager : public QObject, public Dependency {
     Q_OBJECT
     SINGLETON_DEPENDENCY
 public:
+    PointerManager();
 
 signals:
     void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent);

From 315baeae1f690bfedffa75f9bdc1ab8e721de1ce Mon Sep 17 00:00:00 2001
From: SamGondelman <samuel_gondelman@alumni.brown.edu>
Date: Tue, 17 Oct 2017 13:22:40 -0700
Subject: [PATCH 6/6] threading fix

---
 libraries/pointers/src/pointers/rays/RayPick.cpp | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/libraries/pointers/src/pointers/rays/RayPick.cpp b/libraries/pointers/src/pointers/rays/RayPick.cpp
index 36756cdb79..bc3a05cd7a 100644
--- a/libraries/pointers/src/pointers/rays/RayPick.cpp
+++ b/libraries/pointers/src/pointers/rays/RayPick.cpp
@@ -32,8 +32,10 @@ float RayPick::getMaxDistance() const {
     return _maxDistance; 
 }
 
-bool RayPick::isEnabled() const { 
-    return _enabled; 
+bool RayPick::isEnabled() const {
+    return resultWithReadLock<bool>([&] {
+        return _enabled;
+    });
 }
 
 void RayPick::setPrecisionPicking(bool precisionPicking) { 
@@ -49,11 +51,15 @@ void RayPick::setRayPickResult(const RayPickResult& rayPickResult) {
 }
 
 QVector<QUuid> RayPick::getIgnoreItems() const {
-    return _ignoreItems; 
+    return resultWithReadLock<QVector<QUuid>>([&] {
+        return _ignoreItems;
+    });
 }
 
 QVector<QUuid> RayPick::getIncludeItems() const {
-    return _includeItems; 
+    return resultWithReadLock<QVector<QUuid>>([&] {
+        return _includeItems;
+    });
 }
 
 RayPickResult RayPick::getPrevRayPickResult() const {