From c1e41311fc3a32fe6ae38b0ed3068091724771df Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Feb 2017 17:18:09 -0800 Subject: [PATCH 01/25] working toward using uuids for overlay IDs --- interface/src/Application.cpp | 19 ++-- interface/src/Application.h | 6 +- interface/src/devices/DdeFaceTracker.h | 2 +- interface/src/ui/overlays/Overlay.cpp | 22 +++++ interface/src/ui/overlays/Overlay.h | 30 +++++- interface/src/ui/overlays/OverlayPanel.cpp | 6 +- interface/src/ui/overlays/OverlayPanel.h | 11 ++- interface/src/ui/overlays/Overlays.cpp | 88 +++++++++-------- interface/src/ui/overlays/Overlays.h | 108 +++++++++++---------- interface/src/ui/overlays/Web3DOverlay.cpp | 4 +- 10 files changed, 181 insertions(+), 115 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 488e97b5e6..a00cfb37d2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -170,6 +170,7 @@ #include "ui/StandAloneJSConsole.h" #include "ui/Stats.h" #include "ui/UpdateDialog.h" +#include "ui/overlays/Overlays.h" #include "Util.h" #include "InterfaceParentFinder.h" @@ -528,7 +529,7 @@ bool setupEssentials(int& argc, char** argv) { // to take care of highlighting keyboard focused items, rather than // continuing to overburden Application.cpp std::shared_ptr _keyboardFocusHighlight{ nullptr }; -int _keyboardFocusHighlightID{ -1 }; +OverlayID _keyboardFocusHighlightID{ -1 }; // FIXME hack access to the internal share context for the Chromium helper @@ -1227,12 +1228,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Keyboard focus handling for Web overlays. auto overlays = &(qApp->getOverlays()); - connect(overlays, &Overlays::mousePressOnOverlay, [=](unsigned int overlayID, const PointerEvent& event) { + connect(overlays, &Overlays::mousePressOnOverlay, [=](OverlayID overlayID, const PointerEvent& event) { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); setKeyboardFocusOverlay(overlayID); }); - connect(overlays, &Overlays::overlayDeleted, [=](unsigned int overlayID) { + connect(overlays, &Overlays::overlayDeleted, [=](OverlayID overlayID) { if (overlayID == _keyboardFocusedOverlay.get()) { setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); } @@ -1682,9 +1683,9 @@ void Application::cleanupBeforeQuit() { _applicationStateDevice.reset(); { - if (_keyboardFocusHighlightID > 0) { + if (_keyboardFocusHighlightID) { getOverlays().deleteOverlay(_keyboardFocusHighlightID); - _keyboardFocusHighlightID = -1; + _keyboardFocusHighlightID = UNKNOWN_OVERLAY_ID; } _keyboardFocusHighlight = nullptr; } @@ -4090,7 +4091,7 @@ void Application::rotationModeChanged() const { void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions) { // Create focus - if (_keyboardFocusHighlightID < 0 || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { + if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { _keyboardFocusHighlight = std::make_shared(); _keyboardFocusHighlight->setAlpha(1.0f); _keyboardFocusHighlight->setBorderSize(1.0f); @@ -4152,11 +4153,11 @@ void Application::setKeyboardFocusEntity(EntityItemID entityItemID) { } } -unsigned int Application::getKeyboardFocusOverlay() { +OverlayID Application::getKeyboardFocusOverlay() { return _keyboardFocusedOverlay.get(); } -void Application::setKeyboardFocusOverlay(unsigned int overlayID) { +void Application::setKeyboardFocusOverlay(OverlayID overlayID) { if (overlayID != _keyboardFocusedOverlay.get()) { _keyboardFocusedOverlay.set(overlayID); @@ -5527,6 +5528,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri auto entityScriptServerLog = DependencyManager::get(); scriptEngine->registerGlobalObject("EntityScriptServerLog", entityScriptServerLog.data()); + qScriptRegisterMetaType(scriptEngine, OverlayIDtoScriptValue, OverlayIDfromScriptValue); + // connect this script engines printedMessage signal to the global ScriptEngines these various messages connect(scriptEngine, &ScriptEngine::printedMessage, DependencyManager::get().data(), &ScriptEngines::onPrintedMessage); connect(scriptEngine, &ScriptEngine::errorMessage, DependencyManager::get().data(), &ScriptEngines::onErrorMessage); diff --git a/interface/src/Application.h b/interface/src/Application.h index cab830ec88..7dcb35babc 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -381,8 +381,8 @@ public slots: void setKeyboardFocusEntity(QUuid id); void setKeyboardFocusEntity(EntityItemID entityItemID); - unsigned int getKeyboardFocusOverlay(); - void setKeyboardFocusOverlay(unsigned int overlayID); + OverlayID getKeyboardFocusOverlay(); + void setKeyboardFocusOverlay(OverlayID overlayID); void addAssetToWorldMessageClose(); @@ -610,7 +610,7 @@ private: DialogsManagerScriptingInterface* _dialogsManagerScriptingInterface = new DialogsManagerScriptingInterface(); ThreadSafeValueCache _keyboardFocusedEntity; - ThreadSafeValueCache _keyboardFocusedOverlay; + ThreadSafeValueCache _keyboardFocusedOverlay; quint64 _lastAcceptedKeyPress = 0; bool _isForeground = true; // starts out assumed to be in foreground bool _inPaint = false; diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 931ab099e9..973c3b224e 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -149,7 +149,7 @@ private: int _calibrationCount; QVector _calibrationValues; TextOverlay* _calibrationBillboard; - int _calibrationBillboardID; + OverlayID _calibrationBillboardID; QString _calibrationMessage; bool _isCalibrated; void addCalibrationDatum(); diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 82b90d228c..8ce4b7e97a 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -204,3 +204,25 @@ void Overlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr qVectorOverlayIDFromScriptValue(const QScriptValue& array) { + if (!array.isArray()) { + return QVector(); + } + QVector newVector; + int length = array.property("length").toInteger(); + newVector.reserve(length); + for (int i = 0; i < length; i++) { + OverlayID id; + OverlayIDfromScriptValue(array.property(i), id); + newVector << id; + } + return newVector; +} diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 51792b24b3..d55b72a189 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -15,6 +15,24 @@ #include // for xColor #include +class OverlayID { +public: + OverlayID() {} + OverlayID(int value) { id = value; } + + OverlayID& operator=(const OverlayID& other) { id = other.id; return *this; } + OverlayID& operator++() { id++; return *this; } + + // OverlayID& operator=(unsigned int value) { id = value; return *this; } + bool operator==(const OverlayID& other) const { return id == other.id; } + bool operator!=(const OverlayID& other) const { return id != other.id; } + // bool operator<(const OverlayID& other) const { return id < other.id; } + // bool operator>(const OverlayID& other) const { return id > other.id; } + operator bool() const { return id != 0; } + + unsigned int id; +}; + class Overlay : public QObject { Q_OBJECT @@ -32,8 +50,8 @@ public: Overlay(const Overlay* overlay); ~Overlay(); - unsigned int getOverlayID() { return _overlayID; } - void setOverlayID(unsigned int overlayID) { _overlayID = overlayID; } + OverlayID getOverlayID() { return _overlayID; } + void setOverlayID(OverlayID overlayID) { _overlayID = overlayID; } virtual void update(float deltatime) {} virtual void render(RenderArgs* args) = 0; @@ -89,7 +107,7 @@ protected: render::ItemID _renderItemID{ render::Item::INVALID_ITEM_ID }; - unsigned int _overlayID; // what Overlays.cpp knows this instance as + OverlayID _overlayID; // what Overlays.cpp knows this instance as bool _isLoaded; float _alpha; @@ -117,5 +135,11 @@ namespace render { template <> const ShapeKey shapeGetShapeKey(const Overlay::Pointer& overlay); } +Q_DECLARE_METATYPE(OverlayID); +Q_DECLARE_METATYPE(QVector); +QScriptValue OverlayIDtoScriptValue(QScriptEngine* engine, const OverlayID& id); +void OverlayIDfromScriptValue(const QScriptValue &object, OverlayID& id); +QVector qVectorOverlayIDFromScriptValue(const QScriptValue& array); + #endif // hifi_Overlay_h diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index cb57c6ec6b..484e1da216 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -51,13 +51,13 @@ void propertyBindingFromVariant(const QVariant& objectVar, PropertyBinding& valu } -void OverlayPanel::addChild(unsigned int childId) { +void OverlayPanel::addChild(OverlayID childId) { if (!_children.contains(childId)) { _children.append(childId); } } -void OverlayPanel::removeChild(unsigned int childId) { +void OverlayPanel::removeChild(OverlayID childId) { if (_children.contains(childId)) { _children.removeOne(childId); } @@ -89,7 +89,7 @@ QVariant OverlayPanel::getProperty(const QString &property) { if (property == "children") { QVariantList array; for (int i = 0; i < _children.length(); i++) { - array.append(_children[i]); + array.append(OverlayIDtoScriptValue(nullptr, _children[i])); } return array; } diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index b0b8cdb989..5bffe3851e 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -20,6 +20,7 @@ #include "PanelAttachable.h" #include "Billboardable.h" +#include "Overlay.h" class PropertyBinding { public: @@ -54,10 +55,10 @@ public: void setAnchorScale(const glm::vec3& scale) { _anchorTransform.setScale(scale); } void setVisible(bool visible) { _visible = visible; } - const QList& getChildren() { return _children; } - void addChild(unsigned int childId); - void removeChild(unsigned int childId); - unsigned int popLastChild() { return _children.takeLast(); } + const QList& getChildren() { return _children; } + void addChild(OverlayID childId); + void removeChild(OverlayID childId); + OverlayID popLastChild() { return _children.takeLast(); } void setProperties(const QVariantMap& properties); QVariant getProperty(const QString& property); @@ -74,7 +75,7 @@ private: QUuid _anchorRotationBindEntity; bool _visible = true; - QList _children; + QList _children; QScriptEngine* _scriptEngine; }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index e81e48f2bc..42e6d2c679 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -139,7 +139,7 @@ void Overlays::enable() { _enabled = true; } -Overlay::Pointer Overlays::getOverlay(unsigned int id) const { +Overlay::Pointer Overlays::getOverlay(OverlayID id) const { if (_overlaysHUD.contains(id)) { return _overlaysHUD[id]; } @@ -149,7 +149,7 @@ Overlay::Pointer Overlays::getOverlay(unsigned int id) const { return nullptr; } -unsigned int Overlays::addOverlay(const QString& type, const QVariant& properties) { +OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) { Overlay::Pointer thisOverlay = nullptr; if (type == ImageOverlay::TYPE) { @@ -191,11 +191,11 @@ unsigned int Overlays::addOverlay(const QString& type, const QVariant& propertie return 0; } -unsigned int Overlays::addOverlay(Overlay::Pointer overlay) { +OverlayID Overlays::addOverlay(Overlay::Pointer overlay) { QWriteLocker lock(&_lock); - unsigned int thisID = _nextOverlayID; + OverlayID thisID = _nextOverlayID; overlay->setOverlayID(thisID); - _nextOverlayID++; + ++_nextOverlayID; if (overlay->is3D()) { _overlaysWorld[thisID] = overlay; @@ -210,11 +210,11 @@ unsigned int Overlays::addOverlay(Overlay::Pointer overlay) { return thisID; } -unsigned int Overlays::cloneOverlay(unsigned int id) { +OverlayID Overlays::cloneOverlay(OverlayID id) { Overlay::Pointer thisOverlay = getOverlay(id); if (thisOverlay) { - unsigned int cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone())); + OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone())); auto attachable = std::dynamic_pointer_cast(thisOverlay); if (attachable && attachable->getParentPanel()) { attachable->getParentPanel()->addChild(cloneId); @@ -225,7 +225,7 @@ unsigned int Overlays::cloneOverlay(unsigned int id) { return 0; // Not found } -bool Overlays::editOverlay(unsigned int id, const QVariant& properties) { +bool Overlays::editOverlay(OverlayID id, const QVariant& properties) { QWriteLocker lock(&_lock); Overlay::Pointer thisOverlay = getOverlay(id); @@ -243,7 +243,7 @@ bool Overlays::editOverlays(const QVariant& propertiesById) { QWriteLocker lock(&_lock); for (const auto& key : map.keys()) { bool convertSuccess; - unsigned int id = key.toUInt(&convertSuccess); + OverlayID id = key.toUInt(&convertSuccess); if (!convertSuccess) { success = false; continue; @@ -260,7 +260,7 @@ bool Overlays::editOverlays(const QVariant& propertiesById) { return success; } -void Overlays::deleteOverlay(unsigned int id) { +void Overlays::deleteOverlay(OverlayID id) { Overlay::Pointer overlayToDelete; { @@ -286,7 +286,7 @@ void Overlays::deleteOverlay(unsigned int id) { emit overlayDeleted(id); } -QString Overlays::getOverlayType(unsigned int overlayId) const { +QString Overlays::getOverlayType(OverlayID overlayId) const { Overlay::Pointer overlay = getOverlay(overlayId); if (overlay) { return overlay->getType(); @@ -294,7 +294,7 @@ QString Overlays::getOverlayType(unsigned int overlayId) const { return ""; } -QObject* Overlays::getOverlayObject(unsigned int id) { +QObject* Overlays::getOverlayObject(OverlayID id) { Overlay::Pointer thisOverlay = getOverlay(id); if (thisOverlay) { return qobject_cast(&(*thisOverlay)); @@ -302,7 +302,7 @@ QObject* Overlays::getOverlayObject(unsigned int id) { return nullptr; } -unsigned int Overlays::getParentPanel(unsigned int childId) const { +OverlayID Overlays::getParentPanel(OverlayID childId) const { Overlay::Pointer overlay = getOverlay(childId); auto attachable = std::dynamic_pointer_cast(overlay); if (attachable) { @@ -313,7 +313,7 @@ unsigned int Overlays::getParentPanel(unsigned int childId) const { return 0; } -void Overlays::setParentPanel(unsigned int childId, unsigned int panelId) { +void Overlays::setParentPanel(OverlayID childId, OverlayID panelId) { auto attachable = std::dynamic_pointer_cast(getOverlay(childId)); if (attachable) { if (_panels.contains(panelId)) { @@ -343,13 +343,13 @@ void Overlays::setParentPanel(unsigned int childId, unsigned int panelId) { } } -unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { +OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { glm::vec2 pointCopy = point; QReadLocker lock(&_lock); if (!_enabled) { return 0; } - QMapIterator i(_overlaysHUD); + QMapIterator i(_overlaysHUD); i.toBack(); const float LARGE_NEGATIVE_FLOAT = -9999999; @@ -361,7 +361,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { while (i.hasPrevious()) { i.previous(); - unsigned int thisID = i.key(); + OverlayID thisID = i.key(); if (i.value()->is3D()) { auto thisOverlay = std::dynamic_pointer_cast(i.value()); if (thisOverlay && !thisOverlay->getIgnoreRayIntersection()) { @@ -381,7 +381,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { return 0; // not found } -OverlayPropertyResult Overlays::getProperty(unsigned int id, const QString& property) { +OverlayPropertyResult Overlays::getProperty(OverlayID id, const QString& property) { OverlayPropertyResult result; Overlay::Pointer thisOverlay = getOverlay(id); QReadLocker lock(&_lock); @@ -406,15 +406,21 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPro } -RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { +RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, bool precisionPicking, + const QScriptValue& overlayIDsToInclude, + const QScriptValue& overlayIDsToDiscard, + bool visibleOnly, bool collidableOnly) { float bestDistance = std::numeric_limits::max(); bool bestIsFront = false; + const QVector overlaysToInclude = qVectorOverlayIDFromScriptValue(overlayIDsToInclude); + const QVector overlaysToDiscard = qVectorOverlayIDFromScriptValue(overlayIDsToDiscard); + RayToOverlayIntersectionResult result; - QMapIterator i(_overlaysWorld); + QMapIterator i(_overlaysWorld); i.toBack(); while (i.hasPrevious()) { i.previous(); - unsigned int thisID = i.key(); + OverlayID thisID = i.key(); auto thisOverlay = std::dynamic_pointer_cast(i.value()); if (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { float thisDistance; @@ -454,7 +460,7 @@ RayToOverlayIntersectionResult::RayToOverlayIntersectionResult() : QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) { auto obj = engine->newObject(); obj.setProperty("intersects", value.intersects); - obj.setProperty("overlayID", value.overlayID); + obj.setProperty("overlayID", OverlayIDtoScriptValue(engine, value.overlayID)); obj.setProperty("distance", value.distance); QString faceName = ""; @@ -523,7 +529,7 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& objectVar value.extraInfo = object["extraInfo"].toString(); } -bool Overlays::isLoaded(unsigned int id) { +bool Overlays::isLoaded(OverlayID id) { QReadLocker lock(&_lock); Overlay::Pointer thisOverlay = getOverlay(id); if (!thisOverlay) { @@ -532,7 +538,7 @@ bool Overlays::isLoaded(unsigned int id) { return thisOverlay->isLoaded(); } -QSizeF Overlays::textSize(unsigned int id, const QString& text) const { +QSizeF Overlays::textSize(OverlayID id, const QString& text) const { Overlay::Pointer thisOverlay = _overlaysHUD[id]; if (thisOverlay) { if (auto textOverlay = std::dynamic_pointer_cast(thisOverlay)) { @@ -547,30 +553,30 @@ QSizeF Overlays::textSize(unsigned int id, const QString& text) const { return QSizeF(0.0f, 0.0f); } -unsigned int Overlays::addPanel(OverlayPanel::Pointer panel) { +OverlayID Overlays::addPanel(OverlayPanel::Pointer panel) { QWriteLocker lock(&_lock); - unsigned int thisID = _nextOverlayID; - _nextOverlayID++; + OverlayID thisID = _nextOverlayID; + ++_nextOverlayID; _panels[thisID] = panel; return thisID; } -unsigned int Overlays::addPanel(const QVariant& properties) { +OverlayID Overlays::addPanel(const QVariant& properties) { OverlayPanel::Pointer panel = std::make_shared(); panel->init(_scriptEngine); panel->setProperties(properties.toMap()); return addPanel(panel); } -void Overlays::editPanel(unsigned int panelId, const QVariant& properties) { +void Overlays::editPanel(OverlayID panelId, const QVariant& properties) { if (_panels.contains(panelId)) { _panels[panelId]->setProperties(properties.toMap()); } } -OverlayPropertyResult Overlays::getPanelProperty(unsigned int panelId, const QString& property) { +OverlayPropertyResult Overlays::getPanelProperty(OverlayID panelId, const QString& property) { OverlayPropertyResult result; if (_panels.contains(panelId)) { OverlayPanel::Pointer thisPanel = getPanel(panelId); @@ -581,7 +587,7 @@ OverlayPropertyResult Overlays::getPanelProperty(unsigned int panelId, const QSt } -void Overlays::deletePanel(unsigned int panelId) { +void Overlays::deletePanel(OverlayID panelId) { OverlayPanel::Pointer panelToDelete; { @@ -594,7 +600,7 @@ void Overlays::deletePanel(unsigned int panelId) { } while (!panelToDelete->getChildren().isEmpty()) { - unsigned int childId = panelToDelete->popLastChild(); + OverlayID childId = panelToDelete->popLastChild(); deleteOverlay(childId); deletePanel(childId); } @@ -602,39 +608,39 @@ void Overlays::deletePanel(unsigned int panelId) { emit panelDeleted(panelId); } -bool Overlays::isAddedOverlay(unsigned int id) { +bool Overlays::isAddedOverlay(OverlayID id) { return _overlaysHUD.contains(id) || _overlaysWorld.contains(id); } -void Overlays::sendMousePressOnOverlay(unsigned int overlayID, const PointerEvent& event) { +void Overlays::sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event) { emit mousePressOnOverlay(overlayID, event); } -void Overlays::sendMouseReleaseOnOverlay(unsigned int overlayID, const PointerEvent& event) { +void Overlays::sendMouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event) { emit mouseReleaseOnOverlay(overlayID, event); } -void Overlays::sendMouseMoveOnOverlay(unsigned int overlayID, const PointerEvent& event) { +void Overlays::sendMouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event) { emit mouseMoveOnOverlay(overlayID, event); } -void Overlays::sendHoverEnterOverlay(unsigned int id, PointerEvent event) { +void Overlays::sendHoverEnterOverlay(OverlayID id, PointerEvent event) { emit hoverEnterOverlay(id, event); } -void Overlays::sendHoverOverOverlay(unsigned int id, PointerEvent event) { +void Overlays::sendHoverOverOverlay(OverlayID id, PointerEvent event) { emit hoverOverOverlay(id, event); } -void Overlays::sendHoverLeaveOverlay(unsigned int id, PointerEvent event) { +void Overlays::sendHoverLeaveOverlay(OverlayID id, PointerEvent event) { emit hoverLeaveOverlay(id, event); } -unsigned int Overlays::getKeyboardFocusOverlay() const { +OverlayID Overlays::getKeyboardFocusOverlay() const { return qApp->getKeyboardFocusOverlay(); } -void Overlays::setKeyboardFocusOverlay(unsigned int id) { +void Overlays::setKeyboardFocusOverlay(OverlayID id) { qApp->setKeyboardFocusOverlay(id); } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 90644206ee..5c784739cb 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -53,7 +53,7 @@ class RayToOverlayIntersectionResult { public: RayToOverlayIntersectionResult(); bool intersects; - unsigned int overlayID; + OverlayID overlayID; float distance; BoxFace face; glm::vec3 surfaceNormal; @@ -77,12 +77,12 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R * @namespace Overlays */ -const unsigned int UNKNOWN_OVERLAY_ID = 0; +const OverlayID UNKNOWN_OVERLAY_ID = 0; class Overlays : public QObject { Q_OBJECT - Q_PROPERTY(unsigned int keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay) + Q_PROPERTY(OverlayID keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay) public: Overlays(); @@ -93,12 +93,12 @@ public: void disable(); void enable(); - Overlay::Pointer getOverlay(unsigned int id) const; - OverlayPanel::Pointer getPanel(unsigned int id) const { return _panels[id]; } + Overlay::Pointer getOverlay(OverlayID id) const; + OverlayPanel::Pointer getPanel(OverlayID id) const { return _panels[id]; } /// adds an overlay that's already been created - unsigned int addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); } - unsigned int addOverlay(Overlay::Pointer overlay); + OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); } + OverlayID addOverlay(Overlay::Pointer overlay); void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); @@ -116,7 +116,7 @@ public slots: * @param {Overlays.OverlayProperties} The properties of the overlay that you want to add. * @return {Overlays.OverlayID} The ID of the newly created overlay. */ - unsigned int addOverlay(const QString& type, const QVariant& properties); + OverlayID addOverlay(const QString& type, const QVariant& properties); /**jsdoc * Create a clone of an existing overlay. @@ -125,7 +125,7 @@ public slots: * @param {Overlays.OverlayID} overlayID The ID of the overlay to clone. * @return {Overlays.OverlayID} The ID of the new overlay. */ - unsigned int cloneOverlay(unsigned int id); + OverlayID cloneOverlay(OverlayID id); /**jsdoc * Edit an overlay's properties. @@ -134,7 +134,7 @@ public slots: * @param {Overlays.OverlayID} overlayID The ID of the overlay to edit. * @return {bool} `true` if the overlay was found and edited, otherwise false. */ - bool editOverlay(unsigned int id, const QVariant& properties); + bool editOverlay(OverlayID id, const QVariant& properties); /// edits an overlay updating only the included properties, will return the identified OverlayID in case of /// successful edit, if the input id is for an unknown overlay this function will have no effect @@ -146,7 +146,7 @@ public slots: * @function Overlays.deleteOverlay * @param {Overlays.OverlayID} overlayID The ID of the overlay to delete. */ - void deleteOverlay(unsigned int id); + void deleteOverlay(OverlayID id); /**jsdoc * Get the type of an overlay. @@ -155,7 +155,7 @@ public slots: * @param {Overlays.OverlayID} overlayID The ID of the overlay to get the type of. * @return {string} The type of the overlay if found, otherwise the empty string. */ - QString getOverlayType(unsigned int overlayId) const; + QString getOverlayType(OverlayID overlayId) const; /**jsdoc * Get the overlay Script object. @@ -164,7 +164,7 @@ public slots: * @param {Overlays.OverlayID} overlayID The ID of the overlay to get the script object of. * @return {Object} The script object for the overlay if found. */ - QObject* getOverlayObject(unsigned int id); + QObject* getOverlayObject(OverlayID id); /**jsdoc * Get the ID of the overlay at a particular point on the HUD/screen. @@ -174,7 +174,7 @@ public slots: * @return {Overlays.OverlayID} The ID of the overlay at the point specified. * If no overlay is found, `0` will be returned. */ - unsigned int getOverlayAtPoint(const glm::vec2& point); + OverlayID getOverlayAtPoint(const glm::vec2& point); /**jsdoc * Get the value of a an overlay's property. @@ -185,16 +185,26 @@ public slots: * @return {Object} The value of the property. If the overlay or the property could * not be found, `undefined` will be returned. */ - OverlayPropertyResult getProperty(unsigned int id, const QString& property); + OverlayPropertyResult getProperty(OverlayID id, const QString& property); /*jsdoc * Find the closest 3D overlay hit by a pick ray. * * @function Overlays.findRayIntersection * @param {PickRay} The PickRay to use for finding overlays. + * @param {bool} Unused; Exists to match Entity interface + * @param {List of Overlays.OverlayID} Whitelist for intersection test. + * @param {List of Overlays.OverlayID} Blacklist for intersection test. + * @param {bool} Unused; Exists to match Entity interface + * @param {bool} Unused; Exists to match Entity interface * @return {Overlays.RayToOverlayIntersectionResult} The result of the ray cast. */ - RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray); + RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray, + bool precisionPicking = false, + const QScriptValue& overlayIDsToInclude = QScriptValue(), + const QScriptValue& overlayIDsToDiscard = QScriptValue(), + bool visibleOnly = false, + bool collidableOnly = false); /**jsdoc * Check whether an overlay's assets have been loaded. For example, if the @@ -204,7 +214,7 @@ public slots: * @param {Overlays.OverlayID} The ID of the overlay to check. * @return {bool} `true` if the overlay's assets have been loaded, otherwise `false`. */ - bool isLoaded(unsigned int id); + bool isLoaded(OverlayID id); /**jsdoc * Calculates the size of the given text in the specified overlay if it is a text overlay. @@ -216,7 +226,7 @@ public slots: * @param {string} The string to measure. * @return {Vec2} The size of the text. */ - QSizeF textSize(unsigned int id, const QString& text) const; + QSizeF textSize(OverlayID id, const QString& text) const; /**jsdoc * Get the width of the virtual 2D HUD. @@ -235,39 +245,39 @@ public slots: float height() const; /// return true if there is an overlay with that id else false - bool isAddedOverlay(unsigned int id); + bool isAddedOverlay(OverlayID id); - unsigned int getParentPanel(unsigned int childId) const; - void setParentPanel(unsigned int childId, unsigned int panelId); + OverlayID getParentPanel(OverlayID childId) const; + void setParentPanel(OverlayID childId, OverlayID panelId); /// adds a panel that has already been created - unsigned int addPanel(OverlayPanel::Pointer panel); + OverlayID addPanel(OverlayPanel::Pointer panel); /// creates and adds a panel based on a set of properties - unsigned int addPanel(const QVariant& properties); + OverlayID addPanel(const QVariant& properties); /// edit the properties of a panel - void editPanel(unsigned int panelId, const QVariant& properties); + void editPanel(OverlayID panelId, const QVariant& properties); /// get a property of a panel - OverlayPropertyResult getPanelProperty(unsigned int panelId, const QString& property); + OverlayPropertyResult getPanelProperty(OverlayID panelId, const QString& property); /// deletes a panel and all child overlays - void deletePanel(unsigned int panelId); + void deletePanel(OverlayID panelId); /// return true if there is a panel with that id else false - bool isAddedPanel(unsigned int id) { return _panels.contains(id); } + bool isAddedPanel(OverlayID id) { return _panels.contains(id); } - void sendMousePressOnOverlay(unsigned int overlayID, const PointerEvent& event); - void sendMouseReleaseOnOverlay(unsigned int overlayID, const PointerEvent& event); - void sendMouseMoveOnOverlay(unsigned int overlayID, const PointerEvent& event); + void sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event); + void sendMouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event); + void sendMouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event); - void sendHoverEnterOverlay(unsigned int id, PointerEvent event); - void sendHoverOverOverlay(unsigned int id, PointerEvent event); - void sendHoverLeaveOverlay(unsigned int id, PointerEvent event); + void sendHoverEnterOverlay(OverlayID id, PointerEvent event); + void sendHoverOverOverlay(OverlayID id, PointerEvent event); + void sendHoverLeaveOverlay(OverlayID id, PointerEvent event); - unsigned int getKeyboardFocusOverlay() const; - void setKeyboardFocusOverlay(unsigned int id); + OverlayID getKeyboardFocusOverlay() const; + void setKeyboardFocusOverlay(OverlayID id); signals: /**jsdoc @@ -276,26 +286,26 @@ signals: * @function Overlays.overlayDeleted * @param {OverlayID} The ID of the overlay that was deleted. */ - void overlayDeleted(unsigned int id); - void panelDeleted(unsigned int id); + void overlayDeleted(OverlayID id); + void panelDeleted(OverlayID id); - void mousePressOnOverlay(unsigned int overlayID, const PointerEvent& event); - void mouseReleaseOnOverlay(unsigned int overlayID, const PointerEvent& event); - void mouseMoveOnOverlay(unsigned int overlayID, const PointerEvent& event); + void mousePressOnOverlay(OverlayID overlayID, const PointerEvent& event); + void mouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event); + void mouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event); void mousePressOffOverlay(); - void hoverEnterOverlay(unsigned int overlayID, const PointerEvent& event); - void hoverOverOverlay(unsigned int overlayID, const PointerEvent& event); - void hoverLeaveOverlay(unsigned int overlayID, const PointerEvent& event); + void hoverEnterOverlay(OverlayID overlayID, const PointerEvent& event); + void hoverOverOverlay(OverlayID overlayID, const PointerEvent& event); + void hoverLeaveOverlay(OverlayID overlayID, const PointerEvent& event); private: void cleanupOverlaysToDelete(); - QMap _overlaysHUD; - QMap _overlaysWorld; - QMap _panels; + QMap _overlaysHUD; + QMap _overlaysWorld; + QMap _panels; QList _overlaysToDelete; - unsigned int _nextOverlayID; + OverlayID _nextOverlayID; QReadWriteLock _lock; QReadWriteLock _deleteLock; @@ -305,8 +315,8 @@ private: PointerEvent calculatePointerEvent(Overlay::Pointer overlay, PickRay ray, RayToOverlayIntersectionResult rayPickResult, QMouseEvent* event, PointerEvent::EventType eventType); - unsigned int _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID }; - unsigned int _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID }; + OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID }; + OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID }; }; #endif // hifi_Overlays_h diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index cb649e8766..bfc37ccf60 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -198,7 +198,7 @@ void Web3DOverlay::render(RenderArgs* args) { _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); currentContext->makeCurrent(currentSurface); - auto forwardPointerEvent = [=](unsigned int overlayID, const PointerEvent& event) { + auto forwardPointerEvent = [=](OverlayID overlayID, const PointerEvent& event) { if (overlayID == getOverlayID()) { handlePointerEvent(event); } @@ -208,7 +208,7 @@ void Web3DOverlay::render(RenderArgs* args) { _mouseReleaseConnection = connect(&(qApp->getOverlays()), &Overlays::mouseReleaseOnOverlay, forwardPointerEvent); _mouseMoveConnection = connect(&(qApp->getOverlays()), &Overlays::mouseMoveOnOverlay, forwardPointerEvent); _hoverLeaveConnection = connect(&(qApp->getOverlays()), &Overlays::hoverLeaveOverlay, - [=](unsigned int overlayID, const PointerEvent& event) { + [=](OverlayID overlayID, const PointerEvent& event) { if (this->_pressed && this->getOverlayID() == overlayID) { // If the user mouses off the overlay while the button is down, simulate a touch end. QTouchEvent::TouchPoint point; From 05c135b9d8d86df89511ecb596b1ccbc189c7496 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Feb 2017 21:22:23 -0800 Subject: [PATCH 02/25] uuid keys for overlays appears to work --- interface/src/Application.cpp | 10 ++--- interface/src/devices/DdeFaceTracker.cpp | 2 +- interface/src/ui/overlays/Base3DOverlay.h | 3 ++ interface/src/ui/overlays/Overlay.cpp | 10 ++--- interface/src/ui/overlays/Overlay.h | 32 ++++++---------- interface/src/ui/overlays/OverlayPanel.cpp | 2 +- interface/src/ui/overlays/Overlays.cpp | 43 ++++++++-------------- interface/src/ui/overlays/Overlays.h | 5 +-- 8 files changed, 43 insertions(+), 64 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a00cfb37d2..5f26fda674 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -529,7 +529,7 @@ bool setupEssentials(int& argc, char** argv) { // to take care of highlighting keyboard focused items, rather than // continuing to overburden Application.cpp std::shared_ptr _keyboardFocusHighlight{ nullptr }; -OverlayID _keyboardFocusHighlightID{ -1 }; +OverlayID _keyboardFocusHighlightID{ UNKNOWN_OVERLAY_ID }; // FIXME hack access to the internal share context for the Chromium helper @@ -1683,9 +1683,9 @@ void Application::cleanupBeforeQuit() { _applicationStateDevice.reset(); { - if (_keyboardFocusHighlightID) { + if (_keyboardFocusHighlightID != UNKNOWN_OVERLAY_ID) { getOverlays().deleteOverlay(_keyboardFocusHighlightID); - _keyboardFocusHighlightID = UNKNOWN_OVERLAY_ID; + _keyboardFocusHighlightID = UNKNOWN_OVERLAY_ID; } _keyboardFocusHighlight = nullptr; } @@ -3072,7 +3072,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { buttons, event->modifiers()); if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() || - getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y()))) { + getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_OVERLAY_ID) { getOverlays().mouseMoveEvent(&mappedEvent); getEntities()->mouseMoveEvent(&mappedEvent); } @@ -4091,7 +4091,7 @@ void Application::rotationModeChanged() const { void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions) { // Create focus - if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { + if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { _keyboardFocusHighlight = std::make_shared(); _keyboardFocusHighlight->setAlpha(1.0f); _keyboardFocusHighlight->setBorderSize(1.0f); diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 2ddd8d9d04..fa7b2c173e 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -193,7 +193,7 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui _calibrationCount(0), _calibrationValues(), _calibrationBillboard(NULL), - _calibrationBillboardID(0), + _calibrationBillboardID(UNKNOWN_OVERLAY_ID), _calibrationMessage(QString()), _isCalibrated(false) { diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 18936df504..7906b9d6c0 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -23,6 +23,9 @@ public: Base3DOverlay(); Base3DOverlay(const Base3DOverlay* base3DOverlay); + virtual OverlayID getOverlayID() const override { return OverlayID(getID().toString()); } + void setOverlayID(OverlayID overlayID) override { setID(overlayID); } + // getters virtual bool is3D() const override { return true; } diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 8ce4b7e97a..0ad2c94241 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -189,7 +189,7 @@ float Overlay::updatePulse() { _pulseDirection *= -1.0f; } _pulse += pulseDelta; - + return _pulse; } @@ -205,11 +205,11 @@ void Overlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr qVectorOverlayIDFromScriptValue(const QScriptValue& array) { @@ -220,9 +220,7 @@ QVector qVectorOverlayIDFromScriptValue(const QScriptValue& array) { int length = array.property("length").toInteger(); newVector.reserve(length); for (int i = 0; i < length; i++) { - OverlayID id; - OverlayIDfromScriptValue(array.property(i), id); - newVector << id; + newVector << OverlayID(array.property(i).toString()); } return newVector; } diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index d55b72a189..320cd532c4 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -15,22 +15,11 @@ #include // for xColor #include -class OverlayID { +class OverlayID : public QUuid { public: - OverlayID() {} - OverlayID(int value) { id = value; } - - OverlayID& operator=(const OverlayID& other) { id = other.id; return *this; } - OverlayID& operator++() { id++; return *this; } - - // OverlayID& operator=(unsigned int value) { id = value; return *this; } - bool operator==(const OverlayID& other) const { return id == other.id; } - bool operator!=(const OverlayID& other) const { return id != other.id; } - // bool operator<(const OverlayID& other) const { return id < other.id; } - // bool operator>(const OverlayID& other) const { return id > other.id; } - operator bool() const { return id != 0; } - - unsigned int id; + OverlayID() : QUuid() {} + OverlayID(QString v) : QUuid(v) {} + OverlayID(QUuid v) : QUuid(v) {} }; class Overlay : public QObject { @@ -50,8 +39,8 @@ public: Overlay(const Overlay* overlay); ~Overlay(); - OverlayID getOverlayID() { return _overlayID; } - void setOverlayID(OverlayID overlayID) { _overlayID = overlayID; } + virtual OverlayID getOverlayID() const { return _overlayID; } + virtual void setOverlayID(OverlayID overlayID) { _overlayID = overlayID; } virtual void update(float deltatime) {} virtual void render(RenderArgs* args) = 0; @@ -107,8 +96,6 @@ protected: render::ItemID _renderItemID{ render::Item::INVALID_ITEM_ID }; - OverlayID _overlayID; // what Overlays.cpp knows this instance as - bool _isLoaded; float _alpha; @@ -125,10 +112,13 @@ protected: xColor _color; bool _visible; // should the overlay be drawn at all Anchor _anchor; + +private: + OverlayID _overlayID; // only used for non-3d overlays }; namespace render { - template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay); + template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay); template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay); template <> int payloadGetLayer(const Overlay::Pointer& overlay); template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args); @@ -141,5 +131,5 @@ QScriptValue OverlayIDtoScriptValue(QScriptEngine* engine, const OverlayID& id); void OverlayIDfromScriptValue(const QScriptValue &object, OverlayID& id); QVector qVectorOverlayIDFromScriptValue(const QScriptValue& array); - + #endif // hifi_Overlay_h diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index 484e1da216..df2b91c4ef 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -89,7 +89,7 @@ QVariant OverlayPanel::getProperty(const QString &property) { if (property == "children") { QVariantList array; for (int i = 0; i < _children.length(); i++) { - array.append(OverlayIDtoScriptValue(nullptr, _children[i])); + array.append(OverlayIDtoScriptValue(nullptr, _children[i]).toVariant()); } return array; } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 42e6d2c679..98590e2166 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -39,9 +39,6 @@ Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") -Overlays::Overlays() : - _nextOverlayID(1) {} - void Overlays::cleanupAllOverlays() { { QWriteLocker lock(&_lock); @@ -188,14 +185,13 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) thisOverlay->setProperties(properties.toMap()); return addOverlay(thisOverlay); } - return 0; + return UNKNOWN_OVERLAY_ID; } OverlayID Overlays::addOverlay(Overlay::Pointer overlay) { QWriteLocker lock(&_lock); - OverlayID thisID = _nextOverlayID; + OverlayID thisID = OverlayID(QUuid::createUuid()); overlay->setOverlayID(thisID); - ++_nextOverlayID; if (overlay->is3D()) { _overlaysWorld[thisID] = overlay; @@ -220,9 +216,9 @@ OverlayID Overlays::cloneOverlay(OverlayID id) { attachable->getParentPanel()->addChild(cloneId); } return cloneId; - } - - return 0; // Not found + } + + return UNKNOWN_OVERLAY_ID; // Not found } bool Overlays::editOverlay(OverlayID id, const QVariant& properties) { @@ -242,13 +238,7 @@ bool Overlays::editOverlays(const QVariant& propertiesById) { bool success = true; QWriteLocker lock(&_lock); for (const auto& key : map.keys()) { - bool convertSuccess; - OverlayID id = key.toUInt(&convertSuccess); - if (!convertSuccess) { - success = false; - continue; - } - + OverlayID id = OverlayID(key); Overlay::Pointer thisOverlay = getOverlay(id); if (!thisOverlay) { success = false; @@ -310,7 +300,7 @@ OverlayID Overlays::getParentPanel(OverlayID childId) const { } else if (_panels.contains(childId)) { return _panels.key(getPanel(childId)->getParentPanel()); } - return 0; + return UNKNOWN_OVERLAY_ID; } void Overlays::setParentPanel(OverlayID childId, OverlayID panelId) { @@ -347,7 +337,7 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { glm::vec2 pointCopy = point; QReadLocker lock(&_lock); if (!_enabled) { - return 0; + return UNKNOWN_OVERLAY_ID; } QMapIterator i(_overlaysHUD); i.toBack(); @@ -378,7 +368,7 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { } } - return 0; // not found + return UNKNOWN_OVERLAY_ID; // not found } OverlayPropertyResult Overlays::getProperty(OverlayID id, const QString& property) { @@ -447,14 +437,14 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, return result; } -RayToOverlayIntersectionResult::RayToOverlayIntersectionResult() : - intersects(false), - overlayID(-1), +RayToOverlayIntersectionResult::RayToOverlayIntersectionResult() : + intersects(false), + overlayID(UNKNOWN_OVERLAY_ID), distance(0), face(), intersection(), extraInfo() -{ +{ } QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) { @@ -463,7 +453,7 @@ QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, obj.setProperty("overlayID", OverlayIDtoScriptValue(engine, value.overlayID)); obj.setProperty("distance", value.distance); - QString faceName = ""; + QString faceName = ""; // handle BoxFace switch (value.face) { case MIN_X_FACE: @@ -499,7 +489,7 @@ QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& objectVar, RayToOverlayIntersectionResult& value) { QVariantMap object = objectVar.toVariant().toMap(); value.intersects = object["intersects"].toBool(); - value.overlayID = object["overlayID"].toInt(); + value.overlayID = OverlayID(QUuid(object["overlayID"].toString())); value.distance = object["distance"].toFloat(); QString faceName = object["face"].toString(); @@ -556,8 +546,7 @@ QSizeF Overlays::textSize(OverlayID id, const QString& text) const { OverlayID Overlays::addPanel(OverlayPanel::Pointer panel) { QWriteLocker lock(&_lock); - OverlayID thisID = _nextOverlayID; - ++_nextOverlayID; + OverlayID thisID = QUuid::createUuid(); _panels[thisID] = panel; return thisID; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 5c784739cb..4a4d6f9466 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -77,7 +77,7 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R * @namespace Overlays */ -const OverlayID UNKNOWN_OVERLAY_ID = 0; +const OverlayID UNKNOWN_OVERLAY_ID = OverlayID(); class Overlays : public QObject { Q_OBJECT @@ -85,7 +85,7 @@ class Overlays : public QObject { Q_PROPERTY(OverlayID keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay) public: - Overlays(); + Overlays() {}; void init(); void update(float deltatime); @@ -305,7 +305,6 @@ private: QMap _overlaysWorld; QMap _panels; QList _overlaysToDelete; - OverlayID _nextOverlayID; QReadWriteLock _lock; QReadWriteLock _deleteLock; From 585691f71ca974b17ce455b62e6a3908aea58289 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Feb 2017 19:29:11 +1300 Subject: [PATCH 03/25] Add finger painting button to tablet --- .../icons/tablet-icons/finger-paint-a.svg | 96 +++++++++++++++++++ .../icons/tablet-icons/finger-paint-i.svg | 46 +++++++++ scripts/system/fingerPaint.js | 44 +++++++++ 3 files changed, 186 insertions(+) create mode 100644 interface/resources/icons/tablet-icons/finger-paint-a.svg create mode 100644 interface/resources/icons/tablet-icons/finger-paint-i.svg create mode 100644 scripts/system/fingerPaint.js diff --git a/interface/resources/icons/tablet-icons/finger-paint-a.svg b/interface/resources/icons/tablet-icons/finger-paint-a.svg new file mode 100644 index 0000000000..553636bfbb --- /dev/null +++ b/interface/resources/icons/tablet-icons/finger-paint-a.svg @@ -0,0 +1,96 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/icons/tablet-icons/finger-paint-i.svg b/interface/resources/icons/tablet-icons/finger-paint-i.svg new file mode 100644 index 0000000000..d7c8948e01 --- /dev/null +++ b/interface/resources/icons/tablet-icons/finger-paint-i.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js new file mode 100644 index 0000000000..c154f2d81d --- /dev/null +++ b/scripts/system/fingerPaint.js @@ -0,0 +1,44 @@ +// +// fingerPaint.js +// +// Created by David Rowe on 15 Feb 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 +// + +(function () { + var tablet, + button, + BUTTON_NAME = "PAINT", + isFingerPainting = false; + + function onButtonClicked() { + isFingerPainting = !isFingerPainting; + button.editProperties({ isActive: isFingerPainting }); + } + + function setUp() { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + if (tablet) { + button = tablet.addButton({ + icon: "icons/tablet-icons/bubble-i.svg", + activeIcon: "icons/tablet-icons/bubble-a.svg", + text: BUTTON_NAME, + isActive: isFingerPainting + }); + button.clicked.connect(onButtonClicked); + } + } + + function tearDown() { + if (tablet) { + button.clicked.disconnect(onButtonClicked); + tablet.removeButton(button); + } + } + + setUp(); + Script.scriptEnding.connect(tearDown); +}()); \ No newline at end of file From bad57fa03f4f6e792ca9f2bbde9f0d6155a08a27 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Feb 2017 08:50:55 +1300 Subject: [PATCH 04/25] Controller and painting code framework --- scripts/system/fingerPaint.js | 153 +++++++++++++++++++++++++++++++--- 1 file changed, 141 insertions(+), 12 deletions(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index c154f2d81d..7f1f90c640 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -12,31 +12,160 @@ var tablet, button, BUTTON_NAME = "PAINT", - isFingerPainting = false; + isFingerPainting = false, + leftHand, + rightHand, + leftBrush, + rightBrush, + CONTROLLER_MAPPING_NAME = "com.highfidelity.fingerPaint"; + + function paintBrush(name) { + // Paints in 3D. + + var brushName = name, + BRUSH_COLOR = { red: 250, green: 0, blue: 0 }, + ERASE_SEARCH_DISTANCE = 0.1; // m + + function startLine(position, width) { + } + + function drawLine(position, width) { + } + + function finishLine(position, width) { + } + + function cancelLine() { + } + + function eraseClosestLine(position) { + } + + function tearDown() { + } + + return { + startLine: startLine, + drawLine: drawLine, + finishLine: finishLine, + cancelLine: cancelLine, + eraseClosestLine: eraseClosestLine, + tearDown: tearDown + }; + } + + function handController(name) { + // Translates controller data into application events. + var handName = name, + triggerPressed, // Callback. + triggerPressing, // "" + triggerReleased, // "" + gripPressed, // "" + isEnabled = false; + + function setEnabled(enabled) { + isEnabled = enabled; + } + + function onTriggerPress(value) { + if (!isEnabled) { + return; + } + } + + function onGripPress(value) { + if (!isEnabled) { + return; + } + } + + function tearDown() { + } + + return { + setEnabled: setEnabled, + onTriggerPress: onTriggerPress, + onGripPress: onGripPress, + triggerPressed: triggerPressed, + triggerPressing: triggerPressing, + triggerReleased: triggerReleased, + gripPressed: gripPressed, + tearDown: tearDown + }; + } function onButtonClicked() { + var wasFingerPainting = isFingerPainting; + isFingerPainting = !isFingerPainting; button.editProperties({ isActive: isFingerPainting }); + + leftHand.setEnabled(isFingerPainting); + rightHand.setEnabled(isFingerPainting); + + if (wasFingerPainting) { + leftBrush.cancelLine(); + rightBrush.cancelLine(); + } } function setUp() { tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - if (tablet) { - button = tablet.addButton({ - icon: "icons/tablet-icons/bubble-i.svg", - activeIcon: "icons/tablet-icons/bubble-a.svg", - text: BUTTON_NAME, - isActive: isFingerPainting - }); - button.clicked.connect(onButtonClicked); + if (!tablet) { + return; } + + // Tablet button. + button = tablet.addButton({ + icon: "icons/tablet-icons/bubble-i.svg", + activeIcon: "icons/tablet-icons/bubble-a.svg", + text: BUTTON_NAME, + isActive: isFingerPainting + }); + button.clicked.connect(onButtonClicked); + + // Connect controller API to handController objects. + leftHand = handController("left"); + rightHand = handController("right"); + var controllerMapping = Controller.newMapping(CONTROLLER_MAPPING_NAME); + controllerMapping.from(Controller.Standard.LT).to(leftHand.onTriggerPress); + controllerMapping.from(Controller.Standard.LeftGrip).to(leftHand.onGripPress); + controllerMapping.from(Controller.Standard.RT).to(rightHand.onTriggerPress); + controllerMapping.from(Controller.Standard.RightGrip).to(rightHand.onGripPress); + Controller.enableMapping(CONTROLLER_MAPPING_NAME); + + // Connect handController outputs to paintBrush objects. + leftBrush = paintBrush("left"); + leftHand.triggerPressed = leftBrush.startLine; + leftHand.triggerPressing = leftBrush.drawLine; + leftHand.trigerRelease = leftBrush.finishLine; + leftHand.gripPressed = leftBrush.eraseLine; + rightBrush = paintBrush("right"); + rightHand.triggerPressed = rightBrush.startLine; + rightHand.triggerPressing = rightBrush.drawLine; + rightHand.trigerRelease = rightBrush.finishLine; + rightHand.gripPressed = rightBrush.eraseLine; } function tearDown() { - if (tablet) { - button.clicked.disconnect(onButtonClicked); - tablet.removeButton(button); + if (!tablet) { + return; } + + button.clicked.disconnect(onButtonClicked); + tablet.removeButton(button); + + Controller.disableMapping(CONTROLLER_MAPPING_NAME); + + leftBrush.tearDown(); + leftBrush = null; + leftHand.tearDown(); + leftHand = null; + + rightBrush.tearDown(); + rightBrush = null; + rightHand.tearDown(); + rightHand = null; } setUp(); From 867e24762b713182be2515b86a8a09922461a83e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Feb 2017 09:23:07 +1300 Subject: [PATCH 05/25] Disable lasers and grabbing while painting if tablet not displayed --- scripts/system/fingerPaint.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 7f1f90c640..d35e053d6b 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -17,7 +17,9 @@ rightHand, leftBrush, rightBrush, - CONTROLLER_MAPPING_NAME = "com.highfidelity.fingerPaint"; + CONTROLLER_MAPPING_NAME = "com.highfidelity.fingerPaint", + isTabletDisplayed = false, + HIFI_GRAB_DISABLE_MESSAGE_CHANNEL = "Hifi-Grab-Disable"; function paintBrush(name) { // Paints in 3D. @@ -94,6 +96,17 @@ }; } + function updateHandControllerGrab() { + // Send message to handControllerGrab.js to handle. + var enabled = !isFingerPainting || isTabletDisplayed; + + Messages.sendMessage(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL, JSON.stringify({ + holdEnabled: enabled, + nearGrabEnabled: enabled, + farGrabEnabled: enabled + })); + } + function onButtonClicked() { var wasFingerPainting = isFingerPainting; @@ -107,6 +120,15 @@ leftBrush.cancelLine(); rightBrush.cancelLine(); } + + updateHandControllerGrab(); + } + + function onTabletScreenChanged(type, url) { + var TABLET_SCREEN_CLOSED = "Closed"; + + isTabletDisplayed = type !== TABLET_SCREEN_CLOSED; + updateHandControllerGrab(); } function setUp() { @@ -124,6 +146,9 @@ }); button.clicked.connect(onButtonClicked); + // Track whether tablet is displayed or not. + tablet.screenChanged.connect(onTabletScreenChanged); + // Connect controller API to handController objects. leftHand = handController("left"); rightHand = handController("right"); @@ -145,6 +170,9 @@ rightHand.triggerPressing = rightBrush.drawLine; rightHand.trigerRelease = rightBrush.finishLine; rightHand.gripPressed = rightBrush.eraseLine; + + // Messages channel for disabling/enabling laser pointers and grabbing. + Messages.subscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); } function tearDown() { @@ -155,6 +183,8 @@ button.clicked.disconnect(onButtonClicked); tablet.removeButton(button); + tablet.screenChanged.disconnect(onTabletScreenChanged); + Controller.disableMapping(CONTROLLER_MAPPING_NAME); leftBrush.tearDown(); @@ -166,6 +196,8 @@ rightBrush = null; rightHand.tearDown(); rightHand = null; + + Messages.unsubscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); } setUp(); From 7b36669d8026ebbd9befb52c8ad2194a0171102a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Feb 2017 10:20:13 +1300 Subject: [PATCH 06/25] Point index finger while painting if tablet not displayed --- scripts/system/controllers/squeezeHands.js | 33 ++++++++++++++++++++++ scripts/system/fingerPaint.js | 16 +++++++---- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/squeezeHands.js b/scripts/system/controllers/squeezeHands.js index 1e94c29521..3f1d21b46c 100644 --- a/scripts/system/controllers/squeezeHands.js +++ b/scripts/system/controllers/squeezeHands.js @@ -25,6 +25,11 @@ var OVERLAY_RAMP_RATE = 8.0; var animStateHandlerID; +var isPointingIndex = false; +var HIFI_POINT_INDEX_MESSAGE_CHANNEL = "Hifi-Point-Index"; + +var indexfingerJointNames = ["LeftHandIndex1", "LeftHandIndex2", "LeftHandIndex3", "RightHandIndex1", "RightHandIndex2", "RightHandIndex3"]; + function clamp(val, min, max) { return Math.min(Math.max(val, min), max); } @@ -43,6 +48,8 @@ function init() { animStateHandler, ["leftHandOverlayAlpha", "rightHandOverlayAlpha", "leftHandGraspAlpha", "rightHandGraspAlpha"] ); + Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); + Messages.messageReceived.connect(handleMessages); } function animStateHandler(props) { @@ -76,11 +83,37 @@ function update(dt) { } else { rightHandOverlayAlpha = clamp(rightHandOverlayAlpha - OVERLAY_RAMP_RATE * dt, 0, 1); } + + // Point index finger. + if (isPointingIndex) { + var zeroRotation = { x: 0, y: 0, z: 0, w: 1 }; + for (var i = 0; i < indexfingerJointNames.length; i++) { + MyAvatar.setJointRotation(indexfingerJointNames[i], zeroRotation); + } + } +} + +function handleMessages(channel, message, sender) { + if (sender === MyAvatar.sessionUUID && channel === HIFI_POINT_INDEX_MESSAGE_CHANNEL) { + var data = JSON.parse(message); + if (data.pointIndex !== undefined) { + print("pointIndex: " + data.pointIndex); + isPointingIndex = data.pointIndex; + + if (!isPointingIndex) { + for (var i = 0; i < indexfingerJointNames.length; i++) { + MyAvatar.clearJointData(indexfingerJointNames[i]); + } + } + } + } } function shutdown() { Script.update.disconnect(update); MyAvatar.removeAnimationStateHandler(animStateHandlerID); + Messages.unsubscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); + Messages.messageReceived.disconnect(handleMessages); } Script.scriptEnding.connect(shutdown); diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index d35e053d6b..7dbcc4c370 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -19,6 +19,7 @@ rightBrush, CONTROLLER_MAPPING_NAME = "com.highfidelity.fingerPaint", isTabletDisplayed = false, + HIFI_POINT_INDEX_MESSAGE_CHANNEL = "Hifi-Point-Index", HIFI_GRAB_DISABLE_MESSAGE_CHANNEL = "Hifi-Grab-Disable"; function paintBrush(name) { @@ -96,8 +97,8 @@ }; } - function updateHandControllerGrab() { - // Send message to handControllerGrab.js to handle. + function updateHandFunctions() { + // Update other scripts' hand functions. var enabled = !isFingerPainting || isTabletDisplayed; Messages.sendMessage(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL, JSON.stringify({ @@ -105,6 +106,9 @@ nearGrabEnabled: enabled, farGrabEnabled: enabled })); + Messages.sendMessage(HIFI_POINT_INDEX_MESSAGE_CHANNEL, JSON.stringify({ + pointIndex: !enabled + })); } function onButtonClicked() { @@ -121,14 +125,14 @@ rightBrush.cancelLine(); } - updateHandControllerGrab(); + updateHandFunctions(); } function onTabletScreenChanged(type, url) { var TABLET_SCREEN_CLOSED = "Closed"; isTabletDisplayed = type !== TABLET_SCREEN_CLOSED; - updateHandControllerGrab(); + updateHandFunctions(); } function setUp() { @@ -171,7 +175,8 @@ rightHand.trigerRelease = rightBrush.finishLine; rightHand.gripPressed = rightBrush.eraseLine; - // Messages channel for disabling/enabling laser pointers and grabbing. + // Messages channels for enabling/disabling other scripts' functions. + Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); Messages.subscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); } @@ -197,6 +202,7 @@ rightHand.tearDown(); rightHand = null; + Messages.unsubscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); Messages.unsubscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); } From 5236f123c1d349dfeb713288aaa3ac05fb0c7bea Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Feb 2017 12:42:10 +1300 Subject: [PATCH 07/25] Interpret trigger and grip values --- scripts/system/fingerPaint.js | 97 +++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 7dbcc4c370..4f21419a87 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -60,39 +60,108 @@ function handController(name) { // Translates controller data into application events. var handName = name, - triggerPressed, // Callback. - triggerPressing, // "" - triggerReleased, // "" - gripPressed, // "" - isEnabled = false; + isEnabled = false, + + triggerPressedCallback, + triggerPressingCallback, + triggerReleasedCallback, + gripPressedCallback, + + triggerValue = 0.0, + isTriggerPressed = false, + TRIGGER_SMOOTH_RATIO = 0.1, + TRIGGER_OFF = 0.05, + TRIGGER_ON = 0.1, + TRIGGER_START_WIDTH = 0.15, + TRIGGER_FINISH_WIDTH = 1.0, + TRIGGER_RANGE_WIDTH = TRIGGER_FINISH_WIDTH - TRIGGER_START_WIDTH, + START_LINE_WIDTH = 0.005, + FINISH_LINE_WIDTH = 0.010, + RANGE_LINE_WIDTH = FINISH_LINE_WIDTH - START_LINE_WIDTH, + + gripValue = 0.0, + isGripPressed = false, + GRIP_SMOOTH_RATIO = 0.1, + GRIP_OFF = 0.05, + GRIP_ON = 0.1; function setEnabled(enabled) { isEnabled = enabled; } function onTriggerPress(value) { + var wasTriggerPressed, + fingerTipPosition, + lineWidth; + if (!isEnabled) { return; } + + triggerValue = triggerValue * TRIGGER_SMOOTH_RATIO + value * (1.0 - TRIGGER_SMOOTH_RATIO); + + wasTriggerPressed = isTriggerPressed; + if (isTriggerPressed) { + isTriggerPressed = triggerValue > TRIGGER_OFF; + } else { + isTriggerPressed = triggerValue > TRIGGER_ON; + } + + if (wasTriggerPressed || isTriggerPressed) { + fingerTipPosition = MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex3" : "RightHandIndex3"); + if (triggerValue < TRIGGER_START_WIDTH) { + lineWidth = START_LINE_WIDTH; + } else { + lineWidth = START_LINE_WIDTH + + (triggerValue - TRIGGER_START_WIDTH) / TRIGGER_RANGE_WIDTH * RANGE_LINE_WIDTH; + } + + if (!wasTriggerPressed && isTriggerPressed) { + triggerPressedCallback(fingerTipPosition, lineWidth); + } else if (wasTriggerPressed && isTriggerPressed) { + triggerPressingCallback(fingerTipPosition, lineWidth); + } else { + triggerReleasedCallback(fingerTipPosition, lineWidth); + } + } } function onGripPress(value) { + var fingerTipPosition; + if (!isEnabled) { return; } + + gripValue = gripValue * GRIP_SMOOTH_RATIO + value * (1.0 - GRIP_SMOOTH_RATIO); + + if (isGripPressed) { + isGripPressed = gripValue > GRIP_OFF; + } else { + isGripPressed = gripValue > GRIP_ON; + if (isGripPressed) { + fingerTipPosition = MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex3" : "RightHandIndex3"); + gripPressedCallback(fingerTipPosition); + } + } + } + + function setUp(onTriggerPressed, onTriggerPressing, onTriggerReleased, onGripPressed) { + triggerPressedCallback = onTriggerPressed; + triggerPressingCallback = onTriggerPressing; + triggerReleasedCallback = onTriggerReleased; + gripPressedCallback = onGripPressed; } function tearDown() { + // Nothing to do. } return { setEnabled: setEnabled, onTriggerPress: onTriggerPress, onGripPress: onGripPress, - triggerPressed: triggerPressed, - triggerPressing: triggerPressing, - triggerReleased: triggerReleased, - gripPressed: gripPressed, + setUp: setUp, tearDown: tearDown }; } @@ -165,15 +234,9 @@ // Connect handController outputs to paintBrush objects. leftBrush = paintBrush("left"); - leftHand.triggerPressed = leftBrush.startLine; - leftHand.triggerPressing = leftBrush.drawLine; - leftHand.trigerRelease = leftBrush.finishLine; - leftHand.gripPressed = leftBrush.eraseLine; + leftHand.setUp(leftBrush.startLine, leftBrush.drawLine, leftBrush.finishLine, leftBrush.eraseClosestLine); rightBrush = paintBrush("right"); - rightHand.triggerPressed = rightBrush.startLine; - rightHand.triggerPressing = rightBrush.drawLine; - rightHand.trigerRelease = rightBrush.finishLine; - rightHand.gripPressed = rightBrush.eraseLine; + rightHand.setUp(rightBrush.startLine, rightBrush.drawLine, rightBrush.finishLine, rightBrush.eraseClosestLine); // Messages channels for enabling/disabling other scripts' functions. Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); From 9c1bb37a349f073f078379aa01ef295b4deddbea Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Feb 2017 14:45:44 +1300 Subject: [PATCH 08/25] Paint lines --- scripts/system/fingerPaint.js | 87 +++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 4f21419a87..10b84b66fa 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -24,27 +24,104 @@ function paintBrush(name) { // Paints in 3D. - var brushName = name, - BRUSH_COLOR = { red: 250, green: 0, blue: 0 }, - ERASE_SEARCH_DISTANCE = 0.1; // m + STROKE_COLOR = { red: 250, green: 0, blue: 0 }, + ERASE_SEARCH_DISTANCE = 0.1, // m + isDrawingLine = false, + entityID, + basePosition, + strokePoints, + strokeNormals, + strokeWidths, + MIN_STROKE_LENGTH = 0.02, + MAX_POINTS_PER_LINE = 100; + + function strokeNormal() { + return Vec3.multiplyQbyV(Camera.getOrientation(), Vec3.UNIT_NEG_Z); + } function startLine(position, width) { + // Start drawing a polyline. + + if (isDrawingLine) { + print("ERROR: startLine() called when already drawing line"); + // Nevertheless, continue on and start a new line. + } + + basePosition = position; + + strokePoints = [Vec3.ZERO]; + strokeNormals = [strokeNormal()]; + strokeWidths = [width]; + + entityID = Entities.addEntity({ + type: "PolyLine", + name: "fingerPainting", + color: STROKE_COLOR, + position: position, + linePoints: strokePoints, + normals: strokeNormals, + strokeWidths: strokeWidths, + dimensions: { x: 10, y: 10, z: 10 } + }); + + isDrawingLine = true; } function drawLine(position, width) { + // Add a stroke to the polyline if stroke is a sufficient length. + var localPosition; + + if (!isDrawingLine) { + print("ERROR: drawLine() called when not drawing line"); + return; + } + + localPosition = Vec3.subtract(position, basePosition); + + if (Vec3.distance(localPosition, strokePoints[strokePoints.length - 1]) >= MIN_STROKE_LENGTH + && strokePoints.length < MAX_POINTS_PER_LINE) { + strokePoints.push(localPosition); + strokeNormals.push(strokeNormal()); + strokeWidths.push(width); + + Entities.editEntity(entityID, { + linePoints: strokePoints, + normals: strokeNormals, + strokeWidths: strokeWidths + }); + } } function finishLine(position, width) { + // Finish drawing polyline; delete if it has only 1 point. + + if (!isDrawingLine) { + print("ERROR: finishLine() called when not drawing line"); + return; + } + + if (strokePoints.length === 1) { + // Delete "empty" line. + Entities.deleteEntity(entityID); + } + + isDrawingLine = false; } function cancelLine() { + // Cancel any line being drawn. + if (isDrawingLine) { + Entities.deleteEntity(entityID); + isDrawingLine = false; + } } function eraseClosestLine(position) { } function tearDown() { + cancelLine(); } return { @@ -108,7 +185,7 @@ } if (wasTriggerPressed || isTriggerPressed) { - fingerTipPosition = MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex3" : "RightHandIndex3"); + fingerTipPosition = MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex4" : "RightHandIndex4"); if (triggerValue < TRIGGER_START_WIDTH) { lineWidth = START_LINE_WIDTH; } else { @@ -140,7 +217,7 @@ } else { isGripPressed = gripValue > GRIP_ON; if (isGripPressed) { - fingerTipPosition = MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex3" : "RightHandIndex3"); + fingerTipPosition = MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex4" : "RightHandIndex4"); gripPressedCallback(fingerTipPosition); } } From 25761adf6c58065f36ef8705f2c926ef1b33ab43 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Feb 2017 15:21:59 +1300 Subject: [PATCH 09/25] Erase closest line --- scripts/system/fingerPaint.js | 39 ++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 10b84b66fa..ce9428b246 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -26,7 +26,7 @@ // Paints in 3D. var brushName = name, STROKE_COLOR = { red: 250, green: 0, blue: 0 }, - ERASE_SEARCH_DISTANCE = 0.1, // m + ERASE_SEARCH_RADIUS = 0.1, // m isDrawingLine = false, entityID, basePosition, @@ -118,6 +118,43 @@ } function eraseClosestLine(position) { + // Erase closest line that is within search radius of finger tip. + var entities, + entitiesLength, + properties, + entityID, + entityDistance, + i, + pointsLength, + j, + distance, + found = false, + foundID, + foundDistance = ERASE_SEARCH_RADIUS; + + // Find entities with bounding box within search radius. + entities = Entities.findEntities(position, ERASE_SEARCH_RADIUS); + + // Fine polyline entity with closest point within search radius. + for (i = 0, entitiesLength = entities.length; i < entitiesLength; i += 1) { + properties = Entities.getEntityProperties(entities[i], ["type", "position", "linePoints"]); + if (properties.type === "PolyLine") { + basePosition = properties.position; + for (j = 0, pointsLength = properties.linePoints.length; j < pointsLength; j += 1) { + distance = Vec3.distance(position, Vec3.sum(basePosition, properties.linePoints[j])); + if (distance <= foundDistance) { + found = true; + foundID = entities[i]; + foundDistance = distance; + } + } + } + } + + // Delete found entity. + if (found) { + Entities.deleteEntity(foundID); + } } function tearDown() { From bdfc9fd418b5db5d82564bf52c975d89f53635e6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Feb 2017 16:39:10 +1300 Subject: [PATCH 10/25] Tidying --- scripts/system/fingerPaint.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index ce9428b246..4742e20410 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -122,8 +122,6 @@ var entities, entitiesLength, properties, - entityID, - entityDistance, i, pointsLength, j, @@ -186,12 +184,12 @@ TRIGGER_SMOOTH_RATIO = 0.1, TRIGGER_OFF = 0.05, TRIGGER_ON = 0.1, - TRIGGER_START_WIDTH = 0.15, - TRIGGER_FINISH_WIDTH = 1.0, - TRIGGER_RANGE_WIDTH = TRIGGER_FINISH_WIDTH - TRIGGER_START_WIDTH, - START_LINE_WIDTH = 0.005, - FINISH_LINE_WIDTH = 0.010, - RANGE_LINE_WIDTH = FINISH_LINE_WIDTH - START_LINE_WIDTH, + TRIGGER_START_WIDTH_RAMP = 0.15, + TRIGGER_FINISH_WIDTH_RAMP = 1.0, + TRIGGER_RAMP_WIDTH = TRIGGER_FINISH_WIDTH_RAMP - TRIGGER_START_WIDTH_RAMP, + MIN_LINE_WIDTH = 0.005, + MAX_LINE_WIDTH = 0.03, + RAMP_LINE_WIDTH = MAX_LINE_WIDTH - MIN_LINE_WIDTH, gripValue = 0.0, isGripPressed = false, @@ -223,11 +221,11 @@ if (wasTriggerPressed || isTriggerPressed) { fingerTipPosition = MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex4" : "RightHandIndex4"); - if (triggerValue < TRIGGER_START_WIDTH) { - lineWidth = START_LINE_WIDTH; + if (triggerValue < TRIGGER_START_WIDTH_RAMP) { + lineWidth = MIN_LINE_WIDTH; } else { - lineWidth = START_LINE_WIDTH - + (triggerValue - TRIGGER_START_WIDTH) / TRIGGER_RANGE_WIDTH * RANGE_LINE_WIDTH; + lineWidth = MIN_LINE_WIDTH + + (triggerValue - TRIGGER_START_WIDTH_RAMP) / TRIGGER_RAMP_WIDTH * RAMP_LINE_WIDTH; } if (!wasTriggerPressed && isTriggerPressed) { @@ -362,6 +360,9 @@ return; } + isFingerPainting = false; + updateHandFunctions(); + button.clicked.disconnect(onButtonClicked); tablet.removeButton(button); From 3712aea8613435fa1a04483d1f3c77836f93a249 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Feb 2017 19:21:20 +1300 Subject: [PATCH 11/25] Handle trigger values of 1.0 not repeating --- scripts/system/fingerPaint.js | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 4742e20410..1c4527b6ad 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -179,6 +179,7 @@ triggerReleasedCallback, gripPressedCallback, + rawTriggerValue = 0.0, triggerValue = 0.0, isTriggerPressed = false, TRIGGER_SMOOTH_RATIO = 0.1, @@ -191,6 +192,7 @@ MAX_LINE_WIDTH = 0.03, RAMP_LINE_WIDTH = MAX_LINE_WIDTH - MIN_LINE_WIDTH, + rawGripValue = 0.0, gripValue = 0.0, isGripPressed = false, GRIP_SMOOTH_RATIO = 0.1, @@ -202,6 +204,11 @@ } function onTriggerPress(value) { + // Controller values are only updated when they change so store latest for use in update. + rawTriggerValue = value; + } + + function updateTriggerPress(value) { var wasTriggerPressed, fingerTipPosition, lineWidth; @@ -210,7 +217,7 @@ return; } - triggerValue = triggerValue * TRIGGER_SMOOTH_RATIO + value * (1.0 - TRIGGER_SMOOTH_RATIO); + triggerValue = triggerValue * TRIGGER_SMOOTH_RATIO + rawTriggerValue * (1.0 - TRIGGER_SMOOTH_RATIO); wasTriggerPressed = isTriggerPressed; if (isTriggerPressed) { @@ -239,13 +246,18 @@ } function onGripPress(value) { + // Controller values are only updated when they change so store latest for use in update. + rawGripValue = value; + } + + function updateGripPress() { var fingerTipPosition; if (!isEnabled) { return; } - gripValue = gripValue * GRIP_SMOOTH_RATIO + value * (1.0 - GRIP_SMOOTH_RATIO); + gripValue = gripValue * GRIP_SMOOTH_RATIO + rawGripValue * (1.0 - GRIP_SMOOTH_RATIO); if (isGripPressed) { isGripPressed = gripValue > GRIP_OFF; @@ -258,6 +270,11 @@ } } + function onUpdate() { + updateTriggerPress(); + updateGripPress(); + } + function setUp(onTriggerPressed, onTriggerPressing, onTriggerReleased, onGripPressed) { triggerPressedCallback = onTriggerPressed; triggerPressingCallback = onTriggerPressing; @@ -273,6 +290,7 @@ setEnabled: setEnabled, onTriggerPress: onTriggerPress, onGripPress: onGripPress, + onUpdate: onUpdate, setUp: setUp, tearDown: tearDown }; @@ -343,6 +361,8 @@ controllerMapping.from(Controller.Standard.RT).to(rightHand.onTriggerPress); controllerMapping.from(Controller.Standard.RightGrip).to(rightHand.onGripPress); Controller.enableMapping(CONTROLLER_MAPPING_NAME); + Script.update.connect(leftHand.onUpdate); + Script.update.connect(rightHand.onUpdate); // Connect handController outputs to paintBrush objects. leftBrush = paintBrush("left"); @@ -360,6 +380,9 @@ return; } + Script.update.disconnect(leftHand.onUpdate); + Script.update.disconnect(rightHand.onUpdate); + isFingerPainting = false; updateHandFunctions(); From 81f63440236169d882002fcc74c10023cec56e16 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Feb 2017 09:36:00 -0800 Subject: [PATCH 12/25] allow overlays to be parents --- interface/src/InterfaceParentFinder.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/interface/src/InterfaceParentFinder.cpp b/interface/src/InterfaceParentFinder.cpp index 824e81b6d8..14088bc716 100644 --- a/interface/src/InterfaceParentFinder.cpp +++ b/interface/src/InterfaceParentFinder.cpp @@ -45,12 +45,20 @@ SpatiallyNestableWeakPointer InterfaceParentFinder::find(QUuid parentID, bool& s success = true; return parent; } - if (parentID == AVATAR_SELF_ID) { success = true; return avatarManager->getMyAvatar(); } + // search overlays + auto& overlays = qApp->getOverlays(); + auto overlay = overlays.getOverlay(parentID); + parent = std::dynamic_pointer_cast(overlay); // this will return nullptr for non-3d overlays + if (!parent.expired()) { + success = true; + return parent; + } + success = false; return parent; } From 2b02998fae4cb9ecfb05128c5a4962698d9b05dd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Feb 2017 09:47:40 -0800 Subject: [PATCH 13/25] hook up overlaysToDiscard and overlaysToInclude in Overlays::findRayIntersection --- interface/src/ui/overlays/Overlays.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 98590e2166..6b120cab56 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -412,13 +412,19 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, i.previous(); OverlayID thisID = i.key(); auto thisOverlay = std::dynamic_pointer_cast(i.value()); + + if ((overlaysToDiscard.size() > 0 && overlaysToDiscard.contains(thisID)) || + (overlaysToInclude.size() > 0 && !overlaysToInclude.contains(thisID))) { + continue; + } + if (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { float thisDistance; BoxFace thisFace; glm::vec3 thisSurfaceNormal; QString thisExtraInfo; - if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, - thisFace, thisSurfaceNormal, thisExtraInfo)) { + if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, + thisFace, thisSurfaceNormal, thisExtraInfo)) { bool isDrawInFront = thisOverlay->getDrawInFront(); if (thisDistance < bestDistance && (!bestIsFront || isDrawInFront)) { bestIsFront = isDrawInFront; From 47cdade1e9a3ba3d123678a46c3a9552beb386f1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Feb 2017 11:47:37 -0800 Subject: [PATCH 14/25] fix home-button on tablet --- interface/src/scripting/HMDScriptingInterface.h | 8 ++++---- scripts/system/libraries/WebTablet.js | 7 +------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index f5744bb8d1..643fac02fc 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -30,7 +30,7 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen Q_PROPERTY(bool mounted READ isMounted) Q_PROPERTY(bool showTablet READ getShouldShowTablet) Q_PROPERTY(QUuid tabletID READ getCurrentTableUIID WRITE setCurrentTabletUIID) - Q_PROPERTY(unsigned int homeButtonID READ getCurrentHomeButtonUUID WRITE setCurrentHomeButtonUUID) + Q_PROPERTY(QUuid homeButtonID READ getCurrentHomeButtonUUID WRITE setCurrentHomeButtonUUID) public: @@ -93,13 +93,13 @@ public: void setCurrentTabletUIID(QUuid tabletID) { _tabletUIID = tabletID; } QUuid getCurrentTableUIID() const { return _tabletUIID; } - void setCurrentHomeButtonUUID(unsigned int homeButtonID) { _homeButtonID = homeButtonID; } - unsigned int getCurrentHomeButtonUUID() const { return _homeButtonID; } + void setCurrentHomeButtonUUID(QUuid homeButtonID) { _homeButtonID = homeButtonID; } + QUuid getCurrentHomeButtonUUID() const { return _homeButtonID; } private: bool _showTablet { false }; QUuid _tabletUIID; // this is the entityID of the WebEntity which is part of (a child of) the tablet-ui. - unsigned int _homeButtonID; + QUuid _homeButtonID; QUuid _tabletEntityID; // Get the position of the HMD diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 74bbd788be..0990440801 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -159,7 +159,7 @@ WebTablet = function (url, width, dpi, hand, clientOnly) { }); this.receive = function (channel, senderID, senderUUID, localOnly) { - if (_this.homeButtonEntity === parseInt(senderID)) { + if (_this.homeButtonEntity == senderID) { var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var onHomeScreen = tablet.onHomeScreen(); if (onHomeScreen) { @@ -219,7 +219,6 @@ WebTablet = function (url, width, dpi, hand, clientOnly) { }; WebTablet.prototype.setHomeButtonTexture = function() { - print(this.homeButtonEntity); Entities.editEntity(this.tabletEntityID, {textures: JSON.stringify({"tex.close": HOME_BUTTON_TEXTURE})}); }; @@ -385,14 +384,10 @@ WebTablet.prototype.register = function() { WebTablet.prototype.cleanUpOldTabletsOnJoint = function(jointIndex) { var children = Entities.getChildrenIDsOfJoint(MyAvatar.sessionUUID, jointIndex); children = children.concat(Entities.getChildrenIDsOfJoint(AVATAR_SELF_ID, jointIndex)); - print("cleanup " + children); children.forEach(function(childID) { var props = Entities.getEntityProperties(childID, ["name"]); if (props.name === "WebTablet Tablet") { - print("cleaning up " + props.name); Entities.deleteEntity(childID); - } else { - print("not cleaning up " + props.name); } }); }; From 5ddcbae9345a6fd885600462bfb373c87234a5c1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Feb 2017 11:51:23 -0800 Subject: [PATCH 15/25] save tablet web-overlay ID in HMD interface. don't trigger edit affordances if the click was intented for the tablet --- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/scripting/HMDScriptingInterface.h | 11 ++++++++--- scripts/system/libraries/entitySelectionTool.js | 11 ++++++++--- scripts/system/tablet-ui/tabletUI.js | 2 ++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 29f41c89fd..e39b7e1e50 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -808,7 +808,7 @@ void MyAvatar::saveData() { auto hmdInterface = DependencyManager::get(); _avatarEntitiesLock.withReadLock([&] { for (auto entityID : _avatarEntityData.keys()) { - if (hmdInterface->getCurrentTableUIID() == entityID) { + if (hmdInterface->getCurrentTabletUIID() == entityID) { // don't persist the tablet between domains / sessions continue; } diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index f5744bb8d1..9a618695d6 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -29,8 +29,9 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen Q_PROPERTY(glm::quat orientation READ getOrientation) Q_PROPERTY(bool mounted READ isMounted) Q_PROPERTY(bool showTablet READ getShouldShowTablet) - Q_PROPERTY(QUuid tabletID READ getCurrentTableUIID WRITE setCurrentTabletUIID) + Q_PROPERTY(QUuid tabletID READ getCurrentTabletUIID WRITE setCurrentTabletUIID) Q_PROPERTY(unsigned int homeButtonID READ getCurrentHomeButtonUUID WRITE setCurrentHomeButtonUUID) + Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID) public: @@ -91,14 +92,18 @@ public: bool getShouldShowTablet() const { return _showTablet; } void setCurrentTabletUIID(QUuid tabletID) { _tabletUIID = tabletID; } - QUuid getCurrentTableUIID() const { return _tabletUIID; } + QUuid getCurrentTabletUIID() const { return _tabletUIID; } void setCurrentHomeButtonUUID(unsigned int homeButtonID) { _homeButtonID = homeButtonID; } unsigned int getCurrentHomeButtonUUID() const { return _homeButtonID; } + void setCurrentTabletScreenID(QUuid tabletID) { _tabletScreenID = tabletID; } + QUuid getCurrentTabletScreenID() const { return _tabletScreenID; } + private: bool _showTablet { false }; - QUuid _tabletUIID; // this is the entityID of the WebEntity which is part of (a child of) the tablet-ui. + QUuid _tabletUIID; // this is the entityID of the tablet frame + QUuid _tabletScreenID; // this is the overlayID which is part of (a child of) the tablet-ui. unsigned int _homeButtonID; QUuid _tabletEntityID; diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index ffce0774b5..b46b1267cc 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -2048,7 +2048,7 @@ SelectionDisplay = (function() { Overlays.editOverlay(grabberPointLightL, { visible: false }); - Overlays.editOverlay(grabberPointLightR, { + Overlays.editOverlay(grabberPointLightR, { visible: false }); Overlays.editOverlay(grabberPointLightF, { @@ -3866,6 +3866,12 @@ SelectionDisplay = (function() { var somethingClicked = false; var pickRay = generalComputePickRay(event.x, event.y); + var result = Overlays.findRayIntersection(pickRay, true, [HMD.tabletScreenID]); + if (result.intersects) { + // mouse clicks on the tablet should override the edit affordances + return false; + } + // before we do a ray test for grabbers, disable the ray intersection for our selection box Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true @@ -3879,10 +3885,9 @@ SelectionDisplay = (function() { Overlays.editOverlay(rollHandle, { ignoreRayIntersection: true }); - var result = Overlays.findRayIntersection(pickRay); + result = Overlays.findRayIntersection(pickRay); if (result.intersects) { - if (wantDebug) { print("something intersects... "); diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 1dc6b7fef8..43eebf15e1 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -32,6 +32,7 @@ UIWebTablet.register(); HMD.tabletID = UIWebTablet.tabletEntityID; HMD.homeButtonID = UIWebTablet.homeButtonEntity; + HMD.tabletScreenID = UIWebTablet.webOverlayID; } function hideTabletUI() { @@ -48,6 +49,7 @@ UIWebTablet = null; HMD.tabletID = null; HMD.homeButtonID = null; + HMD.tabletScreenID = null; } } From b8b5927351f0fc8a930ca734142e78d5d8cb5d38 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 17 Feb 2017 13:21:01 -0800 Subject: [PATCH 16/25] Logging display mode changes --- interface/src/Application.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 488e97b5e6..ea01b13c0f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6679,6 +6679,12 @@ void Application::updateDisplayMode() { } emit activeDisplayPluginChanged(); + + if (_displayPlugin->isHmd()) { + qCDebug(interfaceapp) << "Entering into HMD Mode"; + } else { + qCDebug(interfaceapp) << "Entering into Desktop Mode"; + } // reset the avatar, to set head and hand palms back to a reasonable default pose. getMyAvatar()->reset(false); From d7bb6f105bcee1df7e21a9f29d7b3905fa26073e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Feb 2017 15:43:20 -0800 Subject: [PATCH 17/25] make tablet part IDs available through qApp --- interface/src/Application.cpp | 10 ++++++++++ interface/src/Application.h | 3 +++ interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/scripting/HMDScriptingInterface.h | 12 ++++++++---- interface/src/ui/overlays/Overlay.h | 3 +-- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5f26fda674..40431737a2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6861,3 +6861,13 @@ void Application::toggleMuteAudio() { auto menu = Menu::getInstance(); menu->setIsOptionChecked(MenuOption::MuteAudio, !menu->isOptionChecked(MenuOption::MuteAudio)); } + +OverlayID Application::getTabletScreenID() { + auto HMD = DependencyManager::get(); + return HMD->getCurrentTabletScreenID(); +} + +OverlayID Application::getTabletHomeButtonID() { + auto HMD = DependencyManager::get(); + return HMD->getCurrentHomeButtonUUID(); +} diff --git a/interface/src/Application.h b/interface/src/Application.h index 7dcb35babc..cc3e603a82 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -293,6 +293,9 @@ public: Q_INVOKABLE void sendHoverOverEntity(QUuid id, PointerEvent event); Q_INVOKABLE void sendHoverLeaveEntity(QUuid id, PointerEvent event); + OverlayID getTabletScreenID(); + OverlayID getTabletHomeButtonID(); + signals: void svoImportRequested(const QString& url); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 29f41c89fd..e39b7e1e50 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -808,7 +808,7 @@ void MyAvatar::saveData() { auto hmdInterface = DependencyManager::get(); _avatarEntitiesLock.withReadLock([&] { for (auto entityID : _avatarEntityData.keys()) { - if (hmdInterface->getCurrentTableUIID() == entityID) { + if (hmdInterface->getCurrentTabletUIID() == entityID) { // don't persist the tablet between domains / sessions continue; } diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 643fac02fc..463a21ded8 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -29,9 +29,9 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen Q_PROPERTY(glm::quat orientation READ getOrientation) Q_PROPERTY(bool mounted READ isMounted) Q_PROPERTY(bool showTablet READ getShouldShowTablet) - Q_PROPERTY(QUuid tabletID READ getCurrentTableUIID WRITE setCurrentTabletUIID) + Q_PROPERTY(QUuid tabletID READ getCurrentTabletUIID WRITE setCurrentTabletUIID) Q_PROPERTY(QUuid homeButtonID READ getCurrentHomeButtonUUID WRITE setCurrentHomeButtonUUID) - + Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID) public: Q_INVOKABLE glm::vec3 calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction) const; @@ -91,14 +91,18 @@ public: bool getShouldShowTablet() const { return _showTablet; } void setCurrentTabletUIID(QUuid tabletID) { _tabletUIID = tabletID; } - QUuid getCurrentTableUIID() const { return _tabletUIID; } + QUuid getCurrentTabletUIID() const { return _tabletUIID; } void setCurrentHomeButtonUUID(QUuid homeButtonID) { _homeButtonID = homeButtonID; } QUuid getCurrentHomeButtonUUID() const { return _homeButtonID; } + void setCurrentTabletScreenID(QUuid tabletID) { _tabletScreenID = tabletID; } + QUuid getCurrentTabletScreenID() const { return _tabletScreenID; } + private: bool _showTablet { false }; - QUuid _tabletUIID; // this is the entityID of the WebEntity which is part of (a child of) the tablet-ui. + QUuid _tabletUIID; // this is the entityID of the tablet frame + QUuid _tabletScreenID; // this is the overlayID which is part of (a child of) the tablet-ui. QUuid _homeButtonID; QUuid _tabletEntityID; diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 320cd532c4..0c96af1a99 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -128,8 +128,7 @@ namespace render { Q_DECLARE_METATYPE(OverlayID); Q_DECLARE_METATYPE(QVector); QScriptValue OverlayIDtoScriptValue(QScriptEngine* engine, const OverlayID& id); -void OverlayIDfromScriptValue(const QScriptValue &object, OverlayID& id); +void OverlayIDfromScriptValue(const QScriptValue& object, OverlayID& id); QVector qVectorOverlayIDFromScriptValue(const QScriptValue& array); - #endif // hifi_Overlay_h From 777a0b51c11775615dd7fbdc6ac9a201679650e8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 18 Feb 2017 13:35:16 +1300 Subject: [PATCH 18/25] Ignore spurious finger tip position values --- scripts/system/fingerPaint.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 1c4527b6ad..416b0dede1 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -70,7 +70,9 @@ function drawLine(position, width) { // Add a stroke to the polyline if stroke is a sufficient length. - var localPosition; + var localPosition, + distanceToPrevious, + MAX_DISTANCE_TO_PREVIOUS = 1.0; if (!isDrawingLine) { print("ERROR: drawLine() called when not drawing line"); @@ -78,8 +80,14 @@ } localPosition = Vec3.subtract(position, basePosition); + distanceToPrevious = Vec3.distance(localPosition, strokePoints[strokePoints.length - 1]); - if (Vec3.distance(localPosition, strokePoints[strokePoints.length - 1]) >= MIN_STROKE_LENGTH + if (distanceToPrevious > MAX_DISTANCE_TO_PREVIOUS) { + // Ignore occasional spurious finger tip positions. + return; + } + + if (distanceToPrevious >= MIN_STROKE_LENGTH && strokePoints.length < MAX_POINTS_PER_LINE) { strokePoints.push(localPosition); strokeNormals.push(strokeNormal()); From 0689557ba57d64516522dc8f4a1c2464c005d6aa Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 18 Feb 2017 13:39:59 +1300 Subject: [PATCH 19/25] Draw smoother lines --- scripts/system/fingerPaint.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 416b0dede1..ebcdca44b5 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -33,8 +33,10 @@ strokePoints, strokeNormals, strokeWidths, - MIN_STROKE_LENGTH = 0.02, - MAX_POINTS_PER_LINE = 100; + timeOfLastPoint, + MIN_STROKE_LENGTH = 0.005, // m + MIN_STROKE_INTERVAL = 66, // ms + MAX_POINTS_PER_LINE = 70; // Hard-coded limit in PolyLineEntityItem.h. function strokeNormal() { return Vec3.multiplyQbyV(Camera.getOrientation(), Vec3.UNIT_NEG_Z); @@ -53,6 +55,7 @@ strokePoints = [Vec3.ZERO]; strokeNormals = [strokeNormal()]; strokeWidths = [width]; + timeOfLastPoint = Date.now(); entityID = Entities.addEntity({ type: "PolyLine", @@ -88,10 +91,12 @@ } if (distanceToPrevious >= MIN_STROKE_LENGTH + && (Date.now() - timeOfLastPoint) >= MIN_STROKE_INTERVAL && strokePoints.length < MAX_POINTS_PER_LINE) { strokePoints.push(localPosition); strokeNormals.push(strokeNormal()); strokeWidths.push(width); + timeOfLastPoint = Date.now(); Entities.editEntity(entityID, { linePoints: strokePoints, From 2c02b42c967354be7dd559c67e8a0a05768a7d5b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 18 Feb 2017 14:21:54 +1300 Subject: [PATCH 20/25] Finger paint button icon files --- .../icons/tablet-icons/finger-paint-a.svg | 94 +++++++------------ .../icons/tablet-icons/finger-paint-i.svg | 56 ++++------- scripts/system/fingerPaint.js | 4 +- 3 files changed, 54 insertions(+), 100 deletions(-) diff --git a/interface/resources/icons/tablet-icons/finger-paint-a.svg b/interface/resources/icons/tablet-icons/finger-paint-a.svg index 553636bfbb..acc93608d9 100644 --- a/interface/resources/icons/tablet-icons/finger-paint-a.svg +++ b/interface/resources/icons/tablet-icons/finger-paint-a.svg @@ -10,19 +10,19 @@ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" + id="Layer_1" x="0px" y="0px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve" - id="svg2" - inkscape:version="0.91 r13725" - sodipodi:docname="bubble-a.svg">image/svg+xml \ No newline at end of file + d="M18.3,19.6c0.7,0.1,1.2,0.5,1.4,1.1c0.4,1.3,2,5.6,2.4,6.9c2.2,0,7.9,0.1,9.9,0.1c0.2,0,0.6,0,0.8,0.1 c0.5,0.1,0.8,0.4,1.1,0.9c0.1,0.2,0.2,0.4,0.2,0.6c0.8,2.9,0.7,2,1.5,4.9c0.8,3,0.1,5.7-2.3,7.7c-1.9,1.6-3.6,2.3-5.7,1.9 c-0.6-0.1-1.2-0.3-1.8-0.5c-3.6-1.5-7.3-2.9-10.9-4.3c-0.9-0.4-1.4-1.2-1.3-2c0.1-0.9,0.9-1.5,1.8-1.6c0.1,0,0.3,0,0.4,0 c0.2,0,0.4,0.1,0.7,0.2c1.6,0.6,2.6,1.4,4.2,2c0,0,0,0,0,0c0,0,0.1,0,0.2,0c-0.1-0.2-0.1-0.4-0.2-0.6c-1.4-4.9-2.9-9.8-4.3-14.7 c-0.2-0.7-0.3-1.4,0.2-2c0.4-0.6,1-0.8,1.7-0.8C18.2,19.5,18.2,19.5,18.3,19.6 M18.9,16.3c-0.1,0-0.3,0-0.4-0.1 c-1.9-0.2-3.6,0.6-4.7,2.1c-1.5,2-0.9,4.1-0.7,4.8c0.9,3,1.8,6,2.6,9c-0.1,0-0.3,0-0.4,0c-2.5,0-4.6,1.9-5,4.3 c-0.2,1.2,0.1,2.4,0.7,3.4c0.6,1,1.5,1.7,2.7,2.2c1.2,0.5,2.4,0.9,3.6,1.4c2.4,0.9,4.9,1.9,7.3,2.9c0.9,0.4,1.7,0.6,2.5,0.7 c3.9,0.7,6.7-1.2,8.5-2.7c3.4-2.8,4.6-6.7,3.4-11.1c-0.5-1.7-0.6-2.1-0.8-2.7c-0.1-0.4-0.3-1-0.7-2.2c-0.1-0.4-0.2-0.7-0.4-1.1 c-0.7-1.5-1.8-2.5-3.4-2.7c-0.6-0.1-1.2-0.1-1.8-0.1c-1.2,0-3.4,0-5.4,0c-0.6,0-1.3-0.1-1.9-0.1c-0.2-0.6-0.5-1.3-0.7-2 c-0.4-1.1-0.7-2.1-0.9-2.6C22.3,17.9,20.8,16.7,18.9,16.3L18.9,16.3z" + id="path13" + style="fill:#000000;fill-opacity:1" /> \ No newline at end of file diff --git a/interface/resources/icons/tablet-icons/finger-paint-i.svg b/interface/resources/icons/tablet-icons/finger-paint-i.svg index d7c8948e01..b295727d8a 100644 --- a/interface/resources/icons/tablet-icons/finger-paint-i.svg +++ b/interface/resources/icons/tablet-icons/finger-paint-i.svg @@ -1,46 +1,30 @@ - - - - - - - - - - - - - - - + + + + + diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index ebcdca44b5..725c04f876 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -355,8 +355,8 @@ // Tablet button. button = tablet.addButton({ - icon: "icons/tablet-icons/bubble-i.svg", - activeIcon: "icons/tablet-icons/bubble-a.svg", + icon: "icons/tablet-icons/finger-paint-i.svg", + activeIcon: "icons/tablet-icons/finger-paint-a.svg", text: BUTTON_NAME, isActive: isFingerPainting }); From 692fa52acaa3a8d1debeefa6932bd86907675613 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 18 Feb 2017 15:21:48 +1300 Subject: [PATCH 21/25] Disable drawing pointer lasers while painting --- .../controllers/handControllerPointer.js | 23 +++++++++++++++++-- scripts/system/fingerPaint.js | 8 ++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index 6bebbf0498..f8a336a017 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -480,6 +480,10 @@ var LASER_SEARCH_COLOR_XYZW = {x: 10 / 255, y: 10 / 255, z: 255 / 255, w: LASER_ var LASER_TRIGGER_COLOR_XYZW = {x: 250 / 255, y: 10 / 255, z: 10 / 255, w: LASER_ALPHA}; var SYSTEM_LASER_DIRECTION = {x: 0, y: 0, z: -1}; var systemLaserOn = false; + +var HIFI_POINTER_DISABLE_MESSAGE_CHANNEL = "Hifi-Pointer-Disable"; +var isPointerEnabled = true; + function clearSystemLaser() { if (!systemLaserOn) { return; @@ -542,9 +546,8 @@ function update() { return off(); } - // If there's a HUD element at the (newly moved) reticle, just make it visible and bail. - if (isPointingAtOverlay(hudPoint2d)) { + if (isPointingAtOverlay(hudPoint2d) && isPointerEnabled) { if (HMD.active) { Reticle.depth = hudReticleDistance(); @@ -579,9 +582,25 @@ function checkSettings() { } checkSettings(); +// Enable/disable pointer. +function handleMessages(channel, message, sender) { + if (sender === MyAvatar.sessionUUID && channel === HIFI_POINTER_DISABLE_MESSAGE_CHANNEL) { + var data = JSON.parse(message); + if (data.pointerEnabled !== undefined) { + print("pointerEnabled: " + data.pointerEnabled); + isPointerEnabled = data.pointerEnabled; + } + } +} + +Messages.subscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); +Messages.messageReceived.connect(handleMessages); + var settingsChecker = Script.setInterval(checkSettings, SETTINGS_CHANGE_RECHECK_INTERVAL); Script.update.connect(update); Script.scriptEnding.connect(function () { + Messages.unsubscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); + Messages.messageReceived.disconnect(handleMessages); Script.clearInterval(settingsChecker); Script.update.disconnect(update); OffscreenFlags.navigationFocusDisabled = false; diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 725c04f876..4824f777aa 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -20,7 +20,8 @@ CONTROLLER_MAPPING_NAME = "com.highfidelity.fingerPaint", isTabletDisplayed = false, HIFI_POINT_INDEX_MESSAGE_CHANNEL = "Hifi-Point-Index", - HIFI_GRAB_DISABLE_MESSAGE_CHANNEL = "Hifi-Grab-Disable"; + HIFI_GRAB_DISABLE_MESSAGE_CHANNEL = "Hifi-Grab-Disable", + HIFI_POINTER_DISABLE_MESSAGE_CHANNEL = "Hifi-Pointer-Disable"; function paintBrush(name) { // Paints in 3D. @@ -318,6 +319,9 @@ nearGrabEnabled: enabled, farGrabEnabled: enabled })); + Messages.sendMessage(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL, JSON.stringify({ + pointerEnabled: enabled + })); Messages.sendMessage(HIFI_POINT_INDEX_MESSAGE_CHANNEL, JSON.stringify({ pointIndex: !enabled })); @@ -386,6 +390,7 @@ // Messages channels for enabling/disabling other scripts' functions. Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); Messages.subscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); + Messages.subscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); } function tearDown() { @@ -418,6 +423,7 @@ Messages.unsubscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); Messages.unsubscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); + Messages.unssubscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); } setUp(); From 05c63e16cacd8d601bcb30b038550ee118e81dea Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 18 Feb 2017 20:40:27 +1300 Subject: [PATCH 22/25] Send messages local only --- scripts/system/fingerPaint.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index 4824f777aa..c5547b40ee 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -318,13 +318,13 @@ holdEnabled: enabled, nearGrabEnabled: enabled, farGrabEnabled: enabled - })); + }), true); Messages.sendMessage(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL, JSON.stringify({ pointerEnabled: enabled - })); + }), true); Messages.sendMessage(HIFI_POINT_INDEX_MESSAGE_CHANNEL, JSON.stringify({ pointIndex: !enabled - })); + }), true); } function onButtonClicked() { From 71ba38afb05c3712b3fc34a52b7851b41ec21fbc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 18 Feb 2017 21:28:30 +1300 Subject: [PATCH 23/25] Process controller and script updates only when finger painting is on --- scripts/system/fingerPaint.js | 134 +++++++++++++++++----------------- 1 file changed, 68 insertions(+), 66 deletions(-) diff --git a/scripts/system/fingerPaint.js b/scripts/system/fingerPaint.js index c5547b40ee..959f594212 100644 --- a/scripts/system/fingerPaint.js +++ b/scripts/system/fingerPaint.js @@ -13,10 +13,10 @@ button, BUTTON_NAME = "PAINT", isFingerPainting = false, - leftHand, - rightHand, - leftBrush, - rightBrush, + leftHand = null, + rightHand = null, + leftBrush = null, + rightBrush = null, CONTROLLER_MAPPING_NAME = "com.highfidelity.fingerPaint", isTabletDisplayed = false, HIFI_POINT_INDEX_MESSAGE_CHANNEL = "Hifi-Point-Index", @@ -186,7 +186,6 @@ function handController(name) { // Translates controller data into application events. var handName = name, - isEnabled = false, triggerPressedCallback, triggerPressingCallback, @@ -213,10 +212,6 @@ GRIP_OFF = 0.05, GRIP_ON = 0.1; - function setEnabled(enabled) { - isEnabled = enabled; - } - function onTriggerPress(value) { // Controller values are only updated when they change so store latest for use in update. rawTriggerValue = value; @@ -227,10 +222,6 @@ fingerTipPosition, lineWidth; - if (!isEnabled) { - return; - } - triggerValue = triggerValue * TRIGGER_SMOOTH_RATIO + rawTriggerValue * (1.0 - TRIGGER_SMOOTH_RATIO); wasTriggerPressed = isTriggerPressed; @@ -267,10 +258,6 @@ function updateGripPress() { var fingerTipPosition; - if (!isEnabled) { - return; - } - gripValue = gripValue * GRIP_SMOOTH_RATIO + rawGripValue * (1.0 - GRIP_SMOOTH_RATIO); if (isGripPressed) { @@ -301,7 +288,6 @@ } return { - setEnabled: setEnabled, onTriggerPress: onTriggerPress, onGripPress: onGripPress, onUpdate: onUpdate, @@ -327,21 +313,76 @@ }), true); } + function enableProcessing() { + // Connect controller API to handController objects. + leftHand = handController("left"); + rightHand = handController("right"); + var controllerMapping = Controller.newMapping(CONTROLLER_MAPPING_NAME); + controllerMapping.from(Controller.Standard.LT).to(leftHand.onTriggerPress); + controllerMapping.from(Controller.Standard.LeftGrip).to(leftHand.onGripPress); + controllerMapping.from(Controller.Standard.RT).to(rightHand.onTriggerPress); + controllerMapping.from(Controller.Standard.RightGrip).to(rightHand.onGripPress); + Controller.enableMapping(CONTROLLER_MAPPING_NAME); + + // Connect handController outputs to paintBrush objects. + leftBrush = paintBrush("left"); + leftHand.setUp(leftBrush.startLine, leftBrush.drawLine, leftBrush.finishLine, leftBrush.eraseClosestLine); + rightBrush = paintBrush("right"); + rightHand.setUp(rightBrush.startLine, rightBrush.drawLine, rightBrush.finishLine, rightBrush.eraseClosestLine); + + // Messages channels for enabling/disabling other scripts' functions. + Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); + Messages.subscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); + Messages.subscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); + + // Update hand controls. + Script.update.connect(leftHand.onUpdate); + Script.update.connect(rightHand.onUpdate); + } + + function disableProcessing() { + Script.update.disconnect(leftHand.onUpdate); + Script.update.disconnect(rightHand.onUpdate); + + Controller.disableMapping(CONTROLLER_MAPPING_NAME); + + leftBrush.tearDown(); + leftBrush = null; + leftHand.tearDown(); + leftHand = null; + + rightBrush.tearDown(); + rightBrush = null; + rightHand.tearDown(); + rightHand = null; + + Messages.unsubscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); + Messages.unsubscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); + Messages.unsubscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); + } + function onButtonClicked() { var wasFingerPainting = isFingerPainting; isFingerPainting = !isFingerPainting; button.editProperties({ isActive: isFingerPainting }); - leftHand.setEnabled(isFingerPainting); - rightHand.setEnabled(isFingerPainting); + print("Finger painting: " + isFingerPainting ? "on" : "off"); if (wasFingerPainting) { leftBrush.cancelLine(); rightBrush.cancelLine(); } + if (isFingerPainting) { + enableProcessing(); + } + updateHandFunctions(); + + if (!isFingerPainting) { + disableProcessing(); + } } function onTabletScreenChanged(type, url) { @@ -368,29 +409,6 @@ // Track whether tablet is displayed or not. tablet.screenChanged.connect(onTabletScreenChanged); - - // Connect controller API to handController objects. - leftHand = handController("left"); - rightHand = handController("right"); - var controllerMapping = Controller.newMapping(CONTROLLER_MAPPING_NAME); - controllerMapping.from(Controller.Standard.LT).to(leftHand.onTriggerPress); - controllerMapping.from(Controller.Standard.LeftGrip).to(leftHand.onGripPress); - controllerMapping.from(Controller.Standard.RT).to(rightHand.onTriggerPress); - controllerMapping.from(Controller.Standard.RightGrip).to(rightHand.onGripPress); - Controller.enableMapping(CONTROLLER_MAPPING_NAME); - Script.update.connect(leftHand.onUpdate); - Script.update.connect(rightHand.onUpdate); - - // Connect handController outputs to paintBrush objects. - leftBrush = paintBrush("left"); - leftHand.setUp(leftBrush.startLine, leftBrush.drawLine, leftBrush.finishLine, leftBrush.eraseClosestLine); - rightBrush = paintBrush("right"); - rightHand.setUp(rightBrush.startLine, rightBrush.drawLine, rightBrush.finishLine, rightBrush.eraseClosestLine); - - // Messages channels for enabling/disabling other scripts' functions. - Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); - Messages.subscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); - Messages.subscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); } function tearDown() { @@ -398,32 +416,16 @@ return; } - Script.update.disconnect(leftHand.onUpdate); - Script.update.disconnect(rightHand.onUpdate); - - isFingerPainting = false; - updateHandFunctions(); - - button.clicked.disconnect(onButtonClicked); - tablet.removeButton(button); + if (isFingerPainting) { + isFingerPainting = false; + updateHandFunctions(); + disableProcessing(); + } tablet.screenChanged.disconnect(onTabletScreenChanged); - Controller.disableMapping(CONTROLLER_MAPPING_NAME); - - leftBrush.tearDown(); - leftBrush = null; - leftHand.tearDown(); - leftHand = null; - - rightBrush.tearDown(); - rightBrush = null; - rightHand.tearDown(); - rightHand = null; - - Messages.unsubscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); - Messages.unsubscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); - Messages.unssubscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); + button.clicked.disconnect(onButtonClicked); + tablet.removeButton(button); } setUp(); From 4a650ff2bb81efcdea2c8ff33a19396085266816 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 19 Feb 2017 18:37:35 -0800 Subject: [PATCH 24/25] Overlays::getOverlayAtPoint was depending on the order in which the overlays were added --- interface/src/ui/overlays/Overlay.h | 5 +++++ interface/src/ui/overlays/Overlays.cpp | 10 ++++++++-- interface/src/ui/overlays/Overlays.h | 1 + .../script-engine/src/TabletScriptingInterface.cpp | 2 +- scripts/tutorials/createDice.js | 4 ++-- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 0c96af1a99..9ad4f0ba70 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -91,6 +91,9 @@ public: render::ItemID getRenderItemID() const { return _renderItemID; } void setRenderItemID(render::ItemID renderItemID) { _renderItemID = renderItemID; } + unsigned int getStackOrder() const { return _stackOrder; } + void setStackOrder(unsigned int stackOrder) { _stackOrder = stackOrder; } + protected: float updatePulse(); @@ -113,6 +116,8 @@ protected: bool _visible; // should the overlay be drawn at all Anchor _anchor; + unsigned int _stackOrder { 0 }; + private: OverlayID _overlayID; // only used for non-3d overlays }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 6b120cab56..f3a78c9350 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -192,6 +192,7 @@ OverlayID Overlays::addOverlay(Overlay::Pointer overlay) { QWriteLocker lock(&_lock); OverlayID thisID = OverlayID(QUuid::createUuid()); overlay->setOverlayID(thisID); + overlay->setStackOrder(_stackOrder++); if (overlay->is3D()) { _overlaysWorld[thisID] = overlay; @@ -348,6 +349,8 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { BoxFace thisFace; glm::vec3 thisSurfaceNormal; float distance; + unsigned int bestStackOrder = 0; + OverlayID bestOverlayID = UNKNOWN_OVERLAY_ID; while (i.hasPrevious()) { i.previous(); @@ -363,12 +366,15 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { auto thisOverlay = std::dynamic_pointer_cast(i.value()); if (thisOverlay && thisOverlay->getVisible() && thisOverlay->isLoaded() && thisOverlay->getBoundingRect().contains(pointCopy.x, pointCopy.y, false)) { - return thisID; + if (thisOverlay->getStackOrder() > bestStackOrder) { + bestOverlayID = thisID; + bestStackOrder = thisOverlay->getStackOrder(); + } } } } - return UNKNOWN_OVERLAY_ID; // not found + return bestOverlayID; } OverlayPropertyResult Overlays::getProperty(OverlayID id, const QString& property) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 4a4d6f9466..7c6ba34f58 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -305,6 +305,7 @@ private: QMap _overlaysWorld; QMap _panels; QList _overlaysToDelete; + unsigned int _stackOrder { 1 }; QReadWriteLock _lock; QReadWriteLock _deleteLock; diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index c78ce251c8..d66bb4d2f6 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -172,7 +172,7 @@ static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml"; static const char* VRMENU_SOURCE_URL = "TabletMenu.qml"; class TabletRootWindow : public QmlWindowClass { - virtual QString qmlSource() const { return "hifi/tablet/WindowRoot.qml"; } + virtual QString qmlSource() const override { return "hifi/tablet/WindowRoot.qml"; } }; TabletProxy::TabletProxy(QString name) : _name(name) { diff --git a/scripts/tutorials/createDice.js b/scripts/tutorials/createDice.js index 8975578c66..0d39d11d48 100644 --- a/scripts/tutorials/createDice.js +++ b/scripts/tutorials/createDice.js @@ -33,7 +33,7 @@ var BUTTON_SIZE = 32; var PADDING = 3; var BOTTOM_PADDING = 50; //a helper library for creating toolbars -Script.include("http://hifi-production.s3.amazonaws.com/tutorials/dice/toolBars.js"); +Script.include("/~/system/libraries/toolBars.js"); var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.toolbars-dice", function(screenSize) { return { @@ -139,4 +139,4 @@ function scriptEnding() { } Controller.mousePressEvent.connect(mousePressEvent); -Script.scriptEnding.connect(scriptEnding); \ No newline at end of file +Script.scriptEnding.connect(scriptEnding); From 2db8517303776b11b0c59ac7d7f21213cb6e5931 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Feb 2017 12:42:57 -0800 Subject: [PATCH 25/25] remove ctrl-M from file --- scripts/system/libraries/entitySelectionTool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 596620b59a..0fd0b01d25 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -2048,7 +2048,7 @@ SelectionDisplay = (function() { Overlays.editOverlay(grabberPointLightL, { visible: false }); - Overlays.editOverlay(grabberPointLightR, { + Overlays.editOverlay(grabberPointLightR, { visible: false }); Overlays.editOverlay(grabberPointLightF, {