diff --git a/examples/example/ui/overlayPanelExample.js b/examples/example/ui/overlayPanelExample.js index 481db282fd..3a735c3e15 100644 --- a/examples/example/ui/overlayPanelExample.js +++ b/examples/example/ui/overlayPanelExample.js @@ -25,8 +25,12 @@ var mainPanel = new OverlayPanel({ offsetRotation: { w: 0, x: 0, y: 1, z: 0 } }); +print(JSON.stringify(mainPanel.offsetPosition)); +print(JSON.stringify(mainPanel.offsetRotation)); + var bluePanel = mainPanel.addChild(new OverlayPanel ({ - offsetPosition: { x: 0.1, y: 0.1, z: 0.2 } + offsetPosition: { x: 0.1, y: 0.1, z: 0.2 }, + offsetScale: 0.5 })); var mainPanelBackground = new Image3DOverlay({ @@ -46,10 +50,6 @@ var mainPanelBackground = new Image3DOverlay({ }); var bluePanelBackground = mainPanelBackground.clone(); -bluePanelBackground.dimensions = { - x: 0.3, - y: 0.3 -}; mainPanel.addChild(mainPanelBackground); bluePanel.addChild(bluePanelBackground); @@ -117,15 +117,15 @@ var redDot2 = mainPanel.addChild(new Image3DOverlay({ var blueSquare = bluePanel.addChild(new Image3DOverlay({ url: BLUE_SQUARE_IMAGE_URL, dimensions: { - x: 0.1, - y: 0.1, + x: 0.15, + y: 0.15, }, isFacingAvatar: false, alpha: 1.0, ignoreRayIntersection: false, offsetPosition: { - x: 0.055, - y: -0.055, + x: 0.09, + y: -0.09, z: 0 } })); @@ -133,23 +133,23 @@ var blueSquare = bluePanel.addChild(new Image3DOverlay({ var blueSquare2 = bluePanel.addChild(new Image3DOverlay({ url: BLUE_SQUARE_IMAGE_URL, dimensions: { - x: 0.1, - y: 0.1, + x: 0.15, + y: 0.15, }, isFacingAvatar: false, alpha: 1.0, ignoreRayIntersection: false, offsetPosition: { - x: 0.055, - y: 0.055, + x: 0.09, + y: 0.09, z: 0 } })); var blueSquare3 = blueSquare2.clone(); blueSquare3.offsetPosition = { - x: -0.055, - y: 0.055, + x: -0.09, + y: 0.09, z: 0 }; diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index 3e409f5e0f..aee4472491 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -234,7 +234,7 @@ // Supports multiple inheritance of properties. Just `concat` them onto the end of the // properties list. - var PANEL_ATTACHABLE_FIELDS = ["offsetPosition", "offsetRotation"]; + var PANEL_ATTACHABLE_FIELDS = ["offsetPosition", "offsetRotation", "offsetScale"]; Overlay = (function() { var that = function(type, params) { @@ -383,8 +383,8 @@ that.prototype.constructor = that; [ - "position", "positionBinding", "rotation", "rotationBinding", - "offsetPosition", "offsetRotation", "visible" + "position", "positionBinding", "rotation", "rotationBinding", "scale", + "offsetPosition", "offsetRotation", "offsetScale", "visible" ].forEach(function(prop) { Object.defineProperty(that.prototype, prop, { get: function() { diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp index 7b195ad466..282289af92 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.cpp +++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp @@ -46,11 +46,13 @@ QScriptValue Billboard3DOverlay::getProperty(const QString &property) { return Planar3DOverlay::getProperty(property); } -void Billboard3DOverlay::applyTransformTo(Transform& transform) { - PanelAttachable::applyTransformTo(transform); - if (_isFacingAvatar) { - glm::quat rotation = Application::getInstance()->getCamera()->getOrientation(); +void Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) { + if (force || usecTimestampNow() > _transformExpiry) { + PanelAttachable::applyTransformTo(transform, true); + if (_isFacingAvatar) { + glm::quat rotation = Application::getInstance()->getCamera()->getOrientation(); - transform.setRotation(rotation); + transform.setRotation(rotation); + } } } diff --git a/interface/src/ui/overlays/Billboard3DOverlay.h b/interface/src/ui/overlays/Billboard3DOverlay.h index 0a15718414..f9a5081123 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.h +++ b/interface/src/ui/overlays/Billboard3DOverlay.h @@ -29,7 +29,7 @@ public: virtual QScriptValue getProperty(const QString& property); protected: - virtual void applyTransformTo(Transform& transform); + virtual void applyTransformTo(Transform& transform, bool force = false); private: bool _isFacingAvatar; diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index cf681fafa1..efa51ca899 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -87,7 +87,7 @@ void Image3DOverlay::render(RenderArgs* args) { xColor color = getColor(); float alpha = getAlpha(); - applyTransformTo(_transform); + applyTransformTo(_transform, true); Transform transform = _transform; transform.postScale(glm::vec3(getDimensions(), 1.0f)); transform.postRotate(glm::angleAxis(glm::pi(), IDENTITY_UP)); @@ -170,7 +170,7 @@ bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec float& distance, BoxFace& face) { if (_texture && _texture->isLoaded()) { // Make sure position and rotation is updated. - applyTransformTo(_transform); + applyTransformTo(_transform, true); // Produce the dimensions of the overlay based on the image's aspect ratio and the overlay's scale. bool isNull = _fromImage.isNull(); diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index c1ef9fcdb4..df14e2f448 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -80,6 +80,9 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { "MyAvatar" : "", _rotationBindEntity)); } + if (property == "scale") { + return vec3toScriptValue(_scriptEngine, getScale()); + } if (property == "visible") { return getVisible(); } @@ -102,7 +105,9 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { position.property("x").isValid() && position.property("y").isValid() && position.property("z").isValid()) { - vec3FromScriptValue(position, _position); + glm::vec3 newPosition; + vec3FromScriptValue(position, newPosition); + setPosition(newPosition); } QScriptValue positionBinding = properties.property("positionBinding"); @@ -119,7 +124,9 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { rotation.property("y").isValid() && rotation.property("z").isValid() && rotation.property("w").isValid()) { - quatFromScriptValue(rotation, _rotation); + glm::quat newRotation; + quatFromScriptValue(rotation, newRotation); + setRotation(newRotation); } QScriptValue rotationBinding = properties.property("rotationBinding"); @@ -134,38 +141,49 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { if (visible.isValid()) { setVisible(visible.toVariant().toBool()); } -} -void OverlayPanel::applyTransformTo(Transform& transform) { - if (getParentPanel()) { - getParentPanel()->applyTransformTo(transform); - } else { - transform.setTranslation(getComputedPosition()); - transform.setRotation(getComputedRotation()); + QScriptValue scale = properties.property("scale"); + if (scale.isValid()) { + if (scale.property("x").isValid() && + scale.property("y").isValid() && + scale.property("z").isValid()) { + glm::vec3 newScale; + vec3FromScriptValue(scale, newScale); + setScale(newScale); + } else { + setScale(scale.toVariant().toFloat()); + } } - _position = transform.getTranslation(); - _rotation = transform.getRotation(); - transform.postTranslate(getOffsetPosition()); - transform.postRotate(getOffsetRotation()); } -glm::vec3 OverlayPanel::getComputedPosition() const { +void OverlayPanel::applyTransformTo(Transform& transform, bool force) { + if (force || usecTimestampNow() > _transformExpiry) { + PanelAttachable::applyTransformTo(transform, true); + if (!getParentPanel()) { + updateTransform(); + transform.setTranslation(getPosition()); + transform.setRotation(getRotation()); + transform.setScale(getScale()); + transform.postTranslate(getOffsetPosition()); + transform.postRotate(getOffsetRotation()); + transform.postScale(getOffsetScale()); + } + } +} + +void OverlayPanel::updateTransform() { if (_positionBindMyAvatar) { - return DependencyManager::get()->getMyAvatar()->getPosition(); + setPosition(DependencyManager::get()->getMyAvatar()->getPosition()); } else if (!_positionBindEntity.isNull()) { - return DependencyManager::get()->getEntityTree()-> - findEntityByID(_positionBindEntity)->getPosition(); + setPosition(DependencyManager::get()->getEntityTree()-> + findEntityByID(_positionBindEntity)->getPosition()); } - return getPosition(); -} -glm::quat OverlayPanel::getComputedRotation() const { if (_rotationBindMyAvatar) { - return DependencyManager::get()->getMyAvatar()->getOrientation() * - glm::angleAxis(glm::pi(), IDENTITY_UP); + setRotation(DependencyManager::get()->getMyAvatar()->getOrientation() * + glm::angleAxis(glm::pi(), IDENTITY_UP)); } else if (!_rotationBindEntity.isNull()) { - return DependencyManager::get()->getEntityTree()-> - findEntityByID(_rotationBindEntity)->getRotation(); + setRotation(DependencyManager::get()->getEntityTree()-> + findEntityByID(_rotationBindEntity)->getRotation()); } - return getRotation(); } diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index f398abb4f8..6e0c6c5a6a 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -42,13 +42,16 @@ public: void init(QScriptEngine* scriptEngine) { _scriptEngine = scriptEngine; } // getters - glm::vec3 getPosition() const { return _position; } - glm::quat getRotation() const { return _rotation; } + glm::vec3 getPosition() const { return _transform.getTranslation(); } + glm::quat getRotation() const { return _transform.getRotation(); } + glm::vec3 getScale() const { return _transform.getScale(); } bool getVisible() const { return _visible; } // setters - void setPosition(const glm::vec3& position) { _position = position; } - void setRotation(const glm::quat& rotation) { _rotation = rotation; } + void setPosition(const glm::vec3& position) { _transform.setTranslation(position); } + void setRotation(const glm::quat& rotation) { _transform.setRotation(rotation); } + void setScale(float scale) { _transform.setScale(scale); } + void setScale(const glm::vec3& scale) { _transform.setScale(scale); } void setVisible(bool visible) { _visible = visible; } const QList& getChildren() { return _children; } @@ -59,14 +62,12 @@ public: QScriptValue getProperty(const QString& property); void setProperties(const QScriptValue& properties); - virtual void applyTransformTo(Transform& transform); + virtual void applyTransformTo(Transform& transform, bool force = false); private: - glm::vec3 getComputedPosition() const; - glm::quat getComputedRotation() const; + void updateTransform(); - glm::vec3 _position = {0, 0, 0}; - glm::quat _rotation = {1, 0, 0, 0}; + Transform _transform; bool _positionBindMyAvatar = false; QUuid _positionBindEntity; diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 90b8112de2..20b06c55b2 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -23,11 +23,16 @@ bool PanelAttachable::getParentVisible() const { } } -void PanelAttachable::applyTransformTo(Transform& transform) { - if (getParentPanel()) { - getParentPanel()->applyTransformTo(transform); - transform.postTranslate(getOffsetPosition()); - transform.postRotate(getOffsetRotation()); +void PanelAttachable::applyTransformTo(Transform& transform, bool force) { + if (force || usecTimestampNow() > _transformExpiry) { + const quint64 TRANSFORM_UPDATE_PERIOD = 50000; + _transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD; + if (getParentPanel()) { + getParentPanel()->applyTransformTo(transform, true); + transform.postTranslate(getOffsetPosition()); + transform.postRotate(getOffsetRotation()); + transform.postScale(getOffsetScale()); + } } } @@ -38,39 +43,44 @@ QScriptValue PanelAttachable::getProperty(QScriptEngine* scriptEngine, const QSt if (property == "offsetRotation") { return quatToScriptValue(scriptEngine, getOffsetRotation()); } + if (property == "offsetScale") { + return vec3toScriptValue(scriptEngine, getOffsetScale()); + } return QScriptValue(); } void PanelAttachable::setProperties(const QScriptValue &properties) { QScriptValue offsetPosition = properties.property("offsetPosition"); - if (offsetPosition.isValid()) { - QScriptValue x = offsetPosition.property("x"); - QScriptValue y = offsetPosition.property("y"); - QScriptValue z = offsetPosition.property("z"); - - if (x.isValid() && y.isValid() && z.isValid()) { - glm::vec3 newPosition; - newPosition.x = x.toVariant().toFloat(); - newPosition.y = y.toVariant().toFloat(); - newPosition.z = z.toVariant().toFloat(); - setOffsetPosition(newPosition); - } + if (offsetPosition.isValid() && + offsetPosition.property("x").isValid() && + offsetPosition.property("y").isValid() && + offsetPosition.property("z").isValid()) { + glm::vec3 newPosition; + vec3FromScriptValue(offsetPosition, newPosition); + setOffsetPosition(newPosition); } QScriptValue offsetRotation = properties.property("offsetRotation"); - if (offsetRotation.isValid()) { - QScriptValue x = offsetRotation.property("x"); - QScriptValue y = offsetRotation.property("y"); - QScriptValue z = offsetRotation.property("z"); - QScriptValue w = offsetRotation.property("w"); + if (offsetRotation.isValid() && + offsetRotation.property("x").isValid() && + offsetRotation.property("y").isValid() && + offsetRotation.property("z").isValid() && + offsetRotation.property("w").isValid()) { + glm::quat newRotation; + quatFromScriptValue(offsetRotation, newRotation); + setOffsetRotation(newRotation); + } - if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { - glm::quat newRotation; - newRotation.x = x.toVariant().toFloat(); - newRotation.y = y.toVariant().toFloat(); - newRotation.z = z.toVariant().toFloat(); - newRotation.w = w.toVariant().toFloat(); - setOffsetRotation(newRotation); + QScriptValue offsetScale = properties.property("offsetScale"); + if (offsetScale.isValid()) { + if (offsetScale.property("x").isValid() && + offsetScale.property("y").isValid() && + offsetScale.property("z").isValid()) { + glm::vec3 newScale; + vec3FromScriptValue(offsetScale, newScale); + setOffsetScale(newScale); + } else { + setOffsetScale(offsetScale.toVariant().toFloat()); } } } diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index a41f20152e..700bc2c5f1 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -24,25 +24,30 @@ class OverlayPanel; class PanelAttachable { public: + // getters std::shared_ptr getParentPanel() const { return _parentPanel; } - virtual glm::vec3 getOffsetPosition() const { return _offsetPosition; } - virtual glm::quat getOffsetRotation() const { return _offsetRotation; } + glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); } + glm::quat getOffsetRotation() const { return _offset.getRotation(); } + glm::vec3 getOffsetScale() const { return _offset.getScale(); } bool getParentVisible() const; + // setters void setParentPanel(std::shared_ptr panel) { _parentPanel = panel; } - virtual void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } - virtual void setOffsetRotation(const glm::quat& rotation) { _offsetRotation = rotation; } + void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); } + void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); } + void setOffsetScale(float scale) { _offset.setScale(scale); } + void setOffsetScale(const glm::vec3& scale) { _offset.setScale(scale); } QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); void setProperties(const QScriptValue& properties); protected: - virtual void applyTransformTo(Transform& transform); + virtual void applyTransformTo(Transform& transform, bool force = false); + quint64 _transformExpiry = 0; private: std::shared_ptr _parentPanel = nullptr; - glm::vec3 _offsetPosition = {0, 0, 0}; - glm::quat _offsetRotation = {1, 0, 0, 0}; + Transform _offset; }; #endif // hifi_PanelAttachable_h diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 5a60ad6029..d4df8553c8 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -86,7 +86,7 @@ void Text3DOverlay::render(RenderArgs* args) { Q_ASSERT(args->_batch); auto& batch = *args->_batch; - applyTransformTo(_transform); + applyTransformTo(_transform, true); batch.setModelTransform(_transform); const float MAX_COLOR = 255.0f; @@ -212,6 +212,6 @@ QSizeF Text3DOverlay::textSize(const QString& text) const { } bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance, BoxFace &face) { - applyTransformTo(_transform); + applyTransformTo(_transform, true); return Billboard3DOverlay::findRayIntersection(origin, direction, distance, face); }