From 22453aa3ce5c2e5b24de713b13faaaf02be52916 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 4 Aug 2015 14:04:13 -0700 Subject: [PATCH] Improve inner workings of overlay API. More stuff is known to the C++, and a panel object in JavaScript can be gotten by ID from another thread. --- examples/libraries/overlayManager.js | 87 +++++++++++-------- interface/src/ui/overlays/FloatingUIPanel.cpp | 34 +++++--- interface/src/ui/overlays/FloatingUIPanel.h | 6 ++ interface/src/ui/overlays/Overlays.cpp | 27 +++++- interface/src/ui/overlays/Overlays.h | 6 ++ 5 files changed, 110 insertions(+), 50 deletions(-) diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index 1b5031d143..d857efd0be 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -60,9 +60,9 @@ } var overlay = new overlayTypes[type](); overlay._id = id; - var panelID = Overlays.getAttachedPanel(id) - if (panelID && panelID in panels) { - panels[panelID].addChild(overlay); + var attachedPanel = findPanel(Overlays.getAttachedPanel(id)) + if (attachedPanel) { + attachedPanel.addChild(overlay); } overlays[id] = overlay; return overlay; @@ -79,7 +79,7 @@ // function findOverlay(id, knownOverlaysOnly, searchList) { if (id > 0) { - knownOverlaysOnly = Boolean(knownOverlaysOnly) || Boolean(searchList); + knownOverlaysOnly = Boolean(knownOverlaysOnly); searchList = searchList || overlays; var foundOverlay = searchList[id]; if (foundOverlay) { @@ -92,6 +92,47 @@ return null; } + // + // Create a new JavaScript object for a panel of given ID. + // + function makePanelFromId(id) { + if (!Overlays.isAddedPanel(id)) { + return null; + } + var panel = new FloatingUIPanel(); + panel._id = id; + var attachedPanel = findPanel(Overlays.getAttachedPanel(id)) + if (attachedPanel) { + attachedPanel.addChild(panel); + } + overlays[id] = overlay; + return overlay; + } + + // + // Get or create an overlay object from the id. + // + // @param knownOverlaysOnly (Optional: Boolean) + // If true, a new object will not be created. + // @param searchList (Optional: Object) + // Map of overlay id's and overlay objects. Can be generated with + // `OverlayManager.makeSearchList`. + // + function findPanel(id, knownPanelsOnly, searchList) { + if (id > 0) { + knownPanelsOnly = Boolean(knownPanelsOnly); + searchList = searchList || panels; + var foundPanel = searchList[id]; + if (foundPanel) { + return foundPanel; + } + if (!knownPanelsOnly) { + return makePanelFromId(id); + } + } + return null; + } + // // Perform global scoped operations on overlays, such as finding by ray intersection. @@ -206,7 +247,6 @@ } else { this._id = 0; } - this._attachedPanelPointer = null; }; that.prototype.constructor = that; @@ -219,7 +259,7 @@ Object.defineProperty(that.prototype, "attachedPanel", { get: function() { - return this._attachedPanelPointer; + return findPanel(Overlays.getAttachedPanel(this._id)); } }); @@ -343,7 +383,6 @@ this._children = []; this._visible = Boolean(params.visible); panels[this._id] = this; - this._attachedPanelPointer = null; }; that.prototype.constructor = that; @@ -384,7 +423,7 @@ Object.defineProperty(that.prototype, "attachedPanel", { get: function() { - return this._attachedPanelPointer; + return findPanel(Overlays.getAttachedPanel(this._id)); } }); @@ -395,23 +434,12 @@ }); that.prototype.addChild = function(child) { - if (child instanceof Overlay && child.isPanelAttachable()) { + if (child instanceof Overlay && child.isPanelAttachable() || + child instanceof FloatingUIPanel) { Overlays.setAttachedPanel(child._id, this._id); - } else if (child instanceof FloatingUIPanel) { - child.setProperties({ - anchorPosition: { - bind: "panel", - value: this._id - }, - offsetRotation: { - bind: "panel", - value: this._id - } - }); } else { throw new that.AddChildException("Given child is not panel attachable."); } - child._attachedPanelPointer = this; child.visible = this.visible; this._children.push(child); return child; @@ -420,19 +448,9 @@ that.prototype.removeChild = function(child) { var i = this._children.indexOf(child); if (i >= 0) { - if (child instanceof Overlay) { + if (child instanceof Overlay || child instanceof FloatingUIPanel) { Overlays.setAttachedPanel(child._id, 0); - } else if (child instanceof FloatingUIPanel) { - child.setProperties({ - anchorPosition: { - bind: "myAvatar" - }, - offsetRotation: { - bind: "myAvatar" - } - }); } - child._attachedPanelPointer = null; this._children.splice(i, 1); } }; @@ -465,11 +483,6 @@ function onPanelDeleted(id) { if (id in panels) { - // Overlays will automatically delete all child overlays, but not all child panels. We - // have to do that ourselves. - panels[id]._children.forEach(function(child) { - child.destroy(); - }); if (panels[id].attachedPanel) { panels[id].attachedPanel.removeChild(panels[id]); } diff --git a/interface/src/ui/overlays/FloatingUIPanel.cpp b/interface/src/ui/overlays/FloatingUIPanel.cpp index eedb4bffd1..496218d7ed 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.cpp +++ b/interface/src/ui/overlays/FloatingUIPanel.cpp @@ -49,6 +49,14 @@ void FloatingUIPanel::setOffsetRotation(const glm::quat& rotation) { }); } +void FloatingUIPanel::setAttachedPanel(unsigned int panelID) { + if (panelID) { + attachAnchorToPanel(panelID); + attachRotationToPanel(panelID); + } + _attachedPanel = panelID; +} + void FloatingUIPanel::addChild(unsigned int childId) { if (!_children.contains(childId)) { _children.append(childId); @@ -99,11 +107,7 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) { }); } } else if (bindTypeString == "panel") { - FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays() - .getPanel(value.toVariant().toUInt()); - setAnchorPosition([panel]() -> glm::vec3 { - return panel->getPosition(); - }); + attachAnchorToPanel(value.toVariant().toUInt()); } else if (bindTypeString == "vec3") { QScriptValue x = value.property("x"); QScriptValue y = value.property("y"); @@ -140,11 +144,7 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) { }); } } else if (bindTypeString == "panel") { - FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays() - .getPanel(value.toVariant().toUInt()); - setOffsetRotation([panel]() -> glm::quat { - return panel->getRotation(); - }); + attachRotationToPanel(value.toVariant().toUInt()); } else if (bindTypeString == "quat") { QScriptValue x = value.property("x"); QScriptValue y = value.property("y"); @@ -195,3 +195,17 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) { } } } + +void FloatingUIPanel::attachAnchorToPanel(unsigned int panelID) { + FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays().getPanel(panelID); + setAnchorPosition([panel]() -> glm::vec3 { + return panel->getPosition(); + }); +} + +void FloatingUIPanel::attachRotationToPanel(unsigned int panelID) { + FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays().getPanel(panelID); + setOffsetRotation([panel]() -> glm::quat { + return panel->getRotation(); + }); +} diff --git a/interface/src/ui/overlays/FloatingUIPanel.h b/interface/src/ui/overlays/FloatingUIPanel.h index f84ac32fac..1b9c732b47 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.h +++ b/interface/src/ui/overlays/FloatingUIPanel.h @@ -32,6 +32,7 @@ public: glm::quat getFacingRotation() const { return _facingRotation; } glm::vec3 getPosition() const; glm::quat getRotation() const; + unsigned int getAttachedPanel() const { return _attachedPanel; } void setAnchorPosition(const std::function& func) { _anchorPosition = func; } void setAnchorPosition(const glm::vec3& position); @@ -39,6 +40,7 @@ public: void setOffsetRotation(const glm::quat& rotation); void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; } + void setAttachedPanel(unsigned int panelID); const QList& getChildren() { return _children; } void addChild(unsigned int childId); @@ -52,10 +54,14 @@ private: static std::function const AVATAR_POSITION; static std::function const AVATAR_ORIENTATION; + void attachAnchorToPanel(unsigned int panelID); + void attachRotationToPanel(unsigned int panelID); + std::function _anchorPosition{AVATAR_POSITION}; std::function _offsetRotation{AVATAR_ORIENTATION}; glm::vec3 _offsetPosition{0, 0, 0}; glm::quat _facingRotation{1, 0, 0, 0}; + unsigned int _attachedPanel{0}; QScriptEngine* _scriptEngine; QList _children; }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 9bc50146d1..a7762b3f81 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -277,6 +277,8 @@ unsigned int Overlays::getAttachedPanel(unsigned int childId) const { auto attachable = std::dynamic_pointer_cast(overlay); if (attachable) { return _panels.key(attachable->getAttachedPanel()); + } else if (_panels.contains(childId)) { + return getPanel(childId)->getAttachedPanel(); } return 0; } @@ -286,7 +288,7 @@ void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) { auto attachable = std::dynamic_pointer_cast(overlay); if (attachable) { if (_panels.contains(panelId)) { - auto panel = _panels[panelId]; + auto panel = getPanel(panelId); panel->addChild(childId); attachable->setAttachedPanel(panel); } else { @@ -296,6 +298,19 @@ void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) { attachable->setAttachedPanel(nullptr); } } + } else if (_panels.contains(childId)) { + auto child = getPanel(childId); + if (_panels.contains(panelId)) { + auto panel = getPanel(panelId); + panel->addChild(childId); + child->setAttachedPanel(panelId); + } else { + auto panel = getPanel(child->getAttachedPanel()); + if (panel) { + panel->removeChild(childId); + child->setAttachedPanel(0); + } + } } } @@ -538,7 +553,7 @@ void Overlays::editPanel(unsigned int panelId, const QScriptValue& properties) { OverlayPropertyResult Overlays::getPanelProperty(unsigned int panelId, const QString& property) { OverlayPropertyResult result; if (_panels.contains(panelId)) { - FloatingUIPanel::Pointer thisPanel = _panels[panelId]; + FloatingUIPanel::Pointer thisPanel = getPanel(panelId); QReadLocker lock(&_lock); result.value = thisPanel->getProperty(property); } @@ -559,8 +574,14 @@ void Overlays::deletePanel(unsigned int panelId) { } while (!panelToDelete->getChildren().isEmpty()) { - deleteOverlay(panelToDelete->popLastChild()); + unsigned int childId = panelToDelete->popLastChild(); + deleteOverlay(childId); + deletePanel(childId); } emit panelDeleted(panelId); } + +bool Overlays::isAddedOverlay(unsigned int id) { + return _overlaysHUD.contains(id) || _overlaysWorld.contains(id); +} diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index ce2c3efeae..a2850b3356 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -125,6 +125,12 @@ public slots: /// deletes a panel and all child overlays void deletePanel(unsigned int panelId); + /// return true if there is an overlay with that id else false + bool isAddedOverlay(unsigned int id); + + /// return true if there is a panel with that id else false + bool isAddedPanel(unsigned int id) { return _panels.contains(id); } + signals: void overlayDeleted(unsigned int id); void panelDeleted(unsigned int id);