From be558eb62e206650079ceee73551c75140e1e1ae Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 3 Aug 2015 16:56:23 -0700 Subject: [PATCH 01/42] Make Text3DOverlay a PanelAttachable. --- interface/src/ui/overlays/Text3DOverlay.cpp | 60 ++++++++++++--------- interface/src/ui/overlays/Text3DOverlay.h | 10 +++- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 00a7d75090..39c8b44902 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -40,6 +40,7 @@ Text3DOverlay::Text3DOverlay() : Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : Planar3DOverlay(text3DOverlay), + PanelAttachable(text3DOverlay), _text(text3DOverlay->_text), _backgroundColor(text3DOverlay->_backgroundColor), _backgroundAlpha(text3DOverlay->_backgroundAlpha), @@ -76,36 +77,33 @@ xColor Text3DOverlay::getBackgroundColor() { return result; } +void Text3DOverlay::setTransforms(Transform &transform) { + PanelAttachable::setTransforms(transform); + if (_isFacingAvatar) { + glm::quat rotation = Application::getInstance()->getCamera()->getOrientation(); + transform.setRotation(rotation); + } +} + +void Text3DOverlay::update(float deltatime) { + setTransforms(_transform); +} void Text3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } - Q_ASSERT(args->_batch); auto& batch = *args->_batch; - glm::quat rotation; - - if (_isFacingAvatar) { - // rotate about vertical to face the camera - rotation = args->_viewFrustum->getOrientation(); - } else { - rotation = getRotation(); - } - - Transform transform; - transform.setTranslation(getPosition()); - transform.setRotation(rotation); - transform.setScale(getScale()); - - batch.setModelTransform(transform); - + setTransforms(_transform); + batch.setModelTransform(_transform); + const float MAX_COLOR = 255.0f; xColor backgroundColor = getBackgroundColor(); - glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, - getBackgroundAlpha()); + glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, + backgroundColor.blue / MAX_COLOR, getBackgroundAlpha()); glm::vec2 dimensions = getDimensions(); glm::vec2 halfDimensions = dimensions * 0.5f; @@ -125,20 +123,21 @@ void Text3DOverlay::render(RenderArgs* args) { glm::vec2 clipMinimum(0.0f, 0.0f); glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); - - transform.setTranslation(getPosition()); - transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin) , halfDimensions.y - _topMargin, 0.01f)); + + Transform transform = _transform; + transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin), + halfDimensions.y - _topMargin, 0.01f)); transform.setScale(scaleFactor); batch.setModelTransform(transform); - - glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() }; + + glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, + _color.blue / MAX_COLOR, getAlpha() }; _textRenderer->draw(batch, 0, 0, _text, textColor); - - batch.setPipeline(DrawOverlay3D::getOpaquePipeline()); } void Text3DOverlay::setProperties(const QScriptValue& properties) { Planar3DOverlay::setProperties(properties); + PanelAttachable::setProperties(properties); QScriptValue text = properties.property("text"); if (text.isValid()) { @@ -216,6 +215,11 @@ QScriptValue Text3DOverlay::getProperty(const QString& property) { if (property == "isFacingAvatar") { return _isFacingAvatar; } + + QScriptValue value = PanelAttachable::getProperty(_scriptEngine, property); + if (value.isValid()) { + return value; + } return Planar3DOverlay::getProperty(property); } @@ -232,3 +236,7 @@ QSizeF Text3DOverlay::textSize(const QString& text) const { return QSizeF(extents.x, extents.y) * pointToWorldScale; } +bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance, BoxFace &face) { + setTransforms(_transform); + return Planar3DOverlay::findRayIntersection(origin, direction, distance, face); +} diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index abd5ef54bd..0893a7cd73 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -14,10 +14,11 @@ #include #include "Planar3DOverlay.h" +#include "PanelAttachable.h" class TextRenderer3D; -class Text3DOverlay : public Planar3DOverlay { +class Text3DOverlay : public Planar3DOverlay, public PanelAttachable { Q_OBJECT public: @@ -29,6 +30,8 @@ public: ~Text3DOverlay(); virtual void render(RenderArgs* args); + virtual void update(float deltatime); + // getters const QString& getText() const { return _text; } float getLineHeight() const { return _lineHeight; } @@ -54,8 +57,13 @@ public: QSizeF textSize(const QString& test) const; // Meters + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); + virtual Text3DOverlay* createClone() const; +protected: + virtual void setTransforms(Transform& transform); + private: TextRenderer3D* _textRenderer = nullptr; From 28050a2ac9a936a8d8f4e9beef88dffeb70375d2 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 3 Aug 2015 16:56:56 -0700 Subject: [PATCH 02/42] Fix PanelAttachable transformations. Apply the offsetPosition of the PanelAttachable after the facingRotation of the FloatingUIPanel, not before. --- examples/controlPanel.js | 19 +++++----- examples/example/ui/floatingUIExample.js | 37 +++++++++++++++++-- examples/libraries/overlayManager.js | 5 +-- .../src/ui/overlays/BillboardOverlay.cpp | 4 +- interface/src/ui/overlays/PanelAttachable.cpp | 4 +- interface/src/ui/overlays/PanelAttachable.h | 8 ++-- 6 files changed, 53 insertions(+), 24 deletions(-) diff --git a/examples/controlPanel.js b/examples/controlPanel.js index 59d66fdaf9..26497beee8 100644 --- a/examples/controlPanel.js +++ b/examples/controlPanel.js @@ -26,7 +26,8 @@ var panel = new FloatingUIPanel({ anchorPosition: { bind: "myAvatar" }, - offsetPosition: { x: 0, y: 0.4, z: 1 } + offsetPosition: { x: 0, y: 0.4, z: 1 }, + facingRotation: { w: 0, x: 0, y: 1, z: 0 } }); var background = new BillboardOverlay({ @@ -51,9 +52,9 @@ var closeButton = new BillboardOverlay({ alpha: 1.0, ignoreRayIntersection: false, offsetPosition: { - x: -0.1, + x: 0.1, y: 0.1, - z: -0.001 + z: 0.001 } }); closeButton.onClick = function(event) { @@ -77,9 +78,9 @@ var micMuteButton = new BillboardOverlay({ alpha: 1.0, ignoreRayIntersection: false, offsetPosition: { - x: 0.1, + x: -0.1, y: 0.1, - z: -0.001 + z: 0.001 } }); micMuteButton.onClick = function(event) { @@ -103,9 +104,9 @@ var faceMuteButton = new BillboardOverlay({ alpha: 1.0, ignoreRayIntersection: false, offsetPosition: { - x: 0.1, + x: -0.1, y: -0.1, - z: -0.001 + z: 0.001 } }); faceMuteButton.onClick = function(event) { @@ -129,9 +130,9 @@ var addressBarButton = new BillboardOverlay({ alpha: 1.0, ignoreRayIntersection: false, offsetPosition: { - x: -0.1, + x: 0.1, y: -0.1, - z: -0.001 + z: 0.001 } }); addressBarButton.onClick = function(event) { diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/floatingUIExample.js index 1e957fe6b3..a2b5d5757f 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/floatingUIExample.js @@ -23,11 +23,12 @@ var mainPanel = new FloatingUIPanel({ bind: "quat", value: { w: 1, x: 0, y: 0, z: 0 } }, - offsetPosition: { x: 0, y: 0.4, z: 1 } + offsetPosition: { x: 0, y: 0.4, z: 1 }, + facingRotation: { w: 0, x: 0, y: 1, z: 0 } }); var bluePanel = mainPanel.addChild(new FloatingUIPanel ({ - offsetPosition: { x: 0.1, y: 0.1, z: -0.2 } + offsetPosition: { x: 0.1, y: 0.1, z: 0.2 } })); var mainPanelBackground = new BillboardOverlay({ @@ -42,7 +43,7 @@ var mainPanelBackground = new BillboardOverlay({ offsetPosition: { x: 0, y: 0, - z: 0.001 + z: -0.001 } }); @@ -55,6 +56,34 @@ bluePanelBackground.dimensions = { mainPanel.addChild(mainPanelBackground); bluePanel.addChild(bluePanelBackground); +var textWidth = .5; +var textHeight = .1; +var numberOfLines = 2; +var textMargin = 0.00625; +var lineHeight = (textHeight - (2 * textMargin)) / numberOfLines; + +var text = mainPanel.addChild(new Text3DOverlay({ + text: "TEXT", + isFacingAvatar: true, + alpha: 1.0, + ignoreRayIntersection: false, + offsetPosition: { + x: -0.15, + y: -0.15, + z: 0 + }, + dimensions: { x: textWidth, y: textHeight }, + backgroundColor: { red: 0, green: 0, blue: 0 }, + color: { red: 255, green: 255, blue: 255 }, + topMargin: textMargin, + leftMargin: textMargin, + bottomMargin: textMargin, + rightMargin: textMargin, + lineHeight: lineHeight, + alpha: 0.9, + backgroundAlpha: 0.9 +})); + var redDot = mainPanel.addChild(new BillboardOverlay({ url: RED_DOT_IMAGE_URL, dimensions: { @@ -149,7 +178,7 @@ function onMouseUp(event) { var newPos = { x: Number(oldPos.x), y: Number(oldPos.y), - z: Number(oldPos.z) + 0.1 + z: Number(oldPos.z) - 0.1 }; overlay.offsetPosition = newPos; } diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index cd05cd2a52..fdb9800116 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -94,7 +94,6 @@ OverlayManager = { findOnRay: function(pickRay, knownOverlaysOnly, searchList) { var rayPickResult = Overlays.findRayIntersection(pickRay); - print("raypick " + rayPickResult.overlayID); if (rayPickResult.intersects) { return findOverlay(rayPickResult.overlayID, knownOverlaysOnly, searchList); } @@ -102,7 +101,6 @@ }, findAtPoint: function(point, knownOverlaysOnly, searchList) { var foundID = Overlays.getOverlayAtPoint(point); - print("at point " + foundID); if (foundID) { return findOverlay(foundID, knownOverlaysOnly, searchList); } else { @@ -270,7 +268,7 @@ generateOverlayClass(Planar3DOverlay, "text3d", [ "text", "backgroundColor", "backgroundAlpha", "lineHeight", "leftMargin", "topMargin", "rightMargin", "bottomMargin", "isFacingAvatar" - ]); + ].concat(PANEL_ATTACHABLE_FIELDS)); generateOverlayClass(Volume3DOverlay, "cube", [ "borderSize" @@ -443,7 +441,6 @@ function onPanelDeleted(id) { if (id in panels) { panels[id]._children.forEach(function(child) { - print(JSON.stringify(child.destroy)); child.destroy(); }); delete panels[id]; diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 3bd1f56ba3..2cde21227c 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -43,8 +43,7 @@ void BillboardOverlay::setTransforms(Transform& transform) { PanelAttachable::setTransforms(transform); if (_isFacingAvatar) { glm::quat rotation = Application::getInstance()->getCamera()->getOrientation(); - rotation *= glm::angleAxis(glm::pi(), IDENTITY_UP); - setRotation(rotation); + transform.setRotation(rotation); } } @@ -101,6 +100,7 @@ void BillboardOverlay::render(RenderArgs* args) { setTransforms(_transform); Transform transform = _transform; transform.postScale(glm::vec3(getDimensions(), 1.0f)); + transform.postRotate(glm::angleAxis(glm::pi(), IDENTITY_UP)); batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index ac4730cfe8..6b453bddc7 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -15,6 +15,7 @@ PanelAttachable::PanelAttachable() : _attachedPanel(nullptr), + _offsetPosition(0, 0, 0), _facingRotation(1, 0, 0, 0) { } @@ -30,8 +31,9 @@ void PanelAttachable::setTransforms(Transform& transform) { if (getAttachedPanel()) { transform.setTranslation(getAttachedPanel()->getAnchorPosition()); transform.setRotation(getAttachedPanel()->getOffsetRotation()); - transform.postTranslate(getOffsetPosition() + getAttachedPanel()->getOffsetPosition()); + transform.postTranslate(getAttachedPanel()->getOffsetPosition()); transform.postRotate(getFacingRotation() * getAttachedPanel()->getFacingRotation()); + transform.postTranslate(getOffsetPosition()); } } diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index 9776ac5ecb..f22d4cc698 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -23,12 +23,12 @@ public: PanelAttachable(const PanelAttachable* panelAttachable); FloatingUIPanel::Pointer getAttachedPanel() const { return _attachedPanel; } - glm::vec3 getOffsetPosition() const { return _offsetPosition; } - glm::quat getFacingRotation() const { return _facingRotation; } + virtual glm::vec3 getOffsetPosition() const { return _offsetPosition; } + virtual glm::quat getFacingRotation() const { return _facingRotation; } void setAttachedPanel(FloatingUIPanel::Pointer panel) { _attachedPanel = panel; } - void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } - void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; } + virtual void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } + virtual void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; } QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); void setProperties(const QScriptValue& properties); From c0838f4e583f0d869b144a6218f9dec1950f07d4 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 3 Aug 2015 17:06:38 -0700 Subject: [PATCH 03/42] Bring text closer to it's background. --- interface/src/ui/overlays/Text3DOverlay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 39c8b44902..04545c59c9 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -108,7 +108,7 @@ void Text3DOverlay::render(RenderArgs* args) { glm::vec2 dimensions = getDimensions(); glm::vec2 halfDimensions = dimensions * 0.5f; - const float SLIGHTLY_BEHIND = -0.005f; + const float SLIGHTLY_BEHIND = -0.001f; glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); @@ -126,7 +126,7 @@ void Text3DOverlay::render(RenderArgs* args) { Transform transform = _transform; transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin), - halfDimensions.y - _topMargin, 0.01f)); + halfDimensions.y - _topMargin, 0.001f)); transform.setScale(scaleFactor); batch.setModelTransform(transform); From e5a429e8a611337e9f0695c1541e36eb123c8131 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 3 Aug 2015 17:07:11 -0700 Subject: [PATCH 04/42] Add a Text3DOverlay in floatingUIExample.js. --- examples/example/ui/floatingUIExample.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/floatingUIExample.js index a2b5d5757f..f489159440 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/floatingUIExample.js @@ -56,21 +56,21 @@ bluePanelBackground.dimensions = { mainPanel.addChild(mainPanelBackground); bluePanel.addChild(bluePanelBackground); -var textWidth = .5; +var textWidth = .25; var textHeight = .1; -var numberOfLines = 2; +var numberOfLines = 1; var textMargin = 0.00625; var lineHeight = (textHeight - (2 * textMargin)) / numberOfLines; var text = mainPanel.addChild(new Text3DOverlay({ text: "TEXT", - isFacingAvatar: true, + isFacingAvatar: false, alpha: 1.0, ignoreRayIntersection: false, offsetPosition: { - x: -0.15, + x: 0.1, y: -0.15, - z: 0 + z: 0.001 }, dimensions: { x: textWidth, y: textHeight }, backgroundColor: { red: 0, green: 0, blue: 0 }, From 055133b82e4ef7d7d7791608fbb396dfaef57130 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 4 Aug 2015 12:04:13 -0700 Subject: [PATCH 05/42] Refactor inheritance for billboard overlays. BillboardOverlays is now Image3DOverlay. Billboard3DOverlay is the base class for both Image3DOverlay and Text3DOverlay, and it is PanelAttachable. --- examples/controlPanel.js | 10 +-- examples/entityScripts/sitOnEntity.js | 2 +- .../example/games/clonedOverlaysExample.js | 4 +- examples/example/ui/floatingUIExample.js | 10 +-- examples/libraries/entitySelectionTool.js | 8 +- examples/libraries/lightOverlayManager.js | 2 +- examples/libraries/overlayManager.js | 76 +++++++++++++------ examples/libraries/virtualKeyboard.js | 4 +- examples/notifications.js | 2 +- examples/progress.js | 2 +- examples/sit.js | 2 +- .../src/ui/overlays/Billboard3DOverlay.cpp | 55 ++++++++++++++ .../src/ui/overlays/Billboard3DOverlay.h | 38 ++++++++++ ...illboardOverlay.cpp => Image3DOverlay.cpp} | 75 ++++++------------ .../{BillboardOverlay.h => Image3DOverlay.h} | 33 ++++---- interface/src/ui/overlays/Overlays.cpp | 6 +- interface/src/ui/overlays/OverlaysPayload.cpp | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 37 ++------- interface/src/ui/overlays/Text3DOverlay.h | 11 +-- 19 files changed, 218 insertions(+), 161 deletions(-) create mode 100644 interface/src/ui/overlays/Billboard3DOverlay.cpp create mode 100644 interface/src/ui/overlays/Billboard3DOverlay.h rename interface/src/ui/overlays/{BillboardOverlay.cpp => Image3DOverlay.cpp} (71%) rename interface/src/ui/overlays/{BillboardOverlay.h => Image3DOverlay.h} (60%) diff --git a/examples/controlPanel.js b/examples/controlPanel.js index 26497beee8..53e9dbc05a 100644 --- a/examples/controlPanel.js +++ b/examples/controlPanel.js @@ -30,7 +30,7 @@ var panel = new FloatingUIPanel({ facingRotation: { w: 0, x: 0, y: 1, z: 0 } }); -var background = new BillboardOverlay({ +var background = new Image3DOverlay({ url: BG_IMAGE_URL, dimensions: { x: 0.5, @@ -42,7 +42,7 @@ var background = new BillboardOverlay({ }); panel.addChild(background); -var closeButton = new BillboardOverlay({ +var closeButton = new Image3DOverlay({ url: CLOSE_IMAGE_URL, dimensions: { x: 0.15, @@ -62,7 +62,7 @@ closeButton.onClick = function(event) { }; panel.addChild(closeButton); -var micMuteButton = new BillboardOverlay({ +var micMuteButton = new Image3DOverlay({ url: MIC_IMAGE_URL, subImage: { x: 0, @@ -88,7 +88,7 @@ micMuteButton.onClick = function(event) { }; panel.addChild(micMuteButton); -var faceMuteButton = new BillboardOverlay({ +var faceMuteButton = new Image3DOverlay({ url: FACE_IMAGE_URL, subImage: { x: 0, @@ -114,7 +114,7 @@ faceMuteButton.onClick = function(event) { }; panel.addChild(faceMuteButton); -var addressBarButton = new BillboardOverlay({ +var addressBarButton = new Image3DOverlay({ url: ADDRESS_BAR_IMAGE_URL, subImage: { x: 0, diff --git a/examples/entityScripts/sitOnEntity.js b/examples/entityScripts/sitOnEntity.js index 8338761c41..0732b14486 100644 --- a/examples/entityScripts/sitOnEntity.js +++ b/examples/entityScripts/sitOnEntity.js @@ -178,7 +178,7 @@ modelProperties.sittingPoints[seatIndex].rotation); this.scale = MyAvatar.scale / 3; - this.sphere = Overlays.addOverlay("billboard", { + this.sphere = Overlays.addOverlay("image3d", { subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, url: buttonImageUrl, position: this.position, diff --git a/examples/example/games/clonedOverlaysExample.js b/examples/example/games/clonedOverlaysExample.js index aa475ee518..51281aa841 100644 --- a/examples/example/games/clonedOverlaysExample.js +++ b/examples/example/games/clonedOverlaysExample.js @@ -252,7 +252,7 @@ function SpriteBillboard(sprite_properties, overlay) { } var christmastree_loader = null; -christmastree_loader = new OverlayPreloader("billboard", +christmastree_loader = new OverlayPreloader("image3d", {url: CHRISTMAS_TREE_SPRITES_URL, alpha: 0}, function() { for (var i = 0; i < NUM_OF_TREES; i++) { var clonedOverlay = Overlays.cloneOverlay(christmastree_loader.overlay); @@ -269,7 +269,7 @@ christmastree_loader = new OverlayPreloader("billboard", ); var santa_loader = null; -santa_loader = new OverlayPreloader("billboard", +santa_loader = new OverlayPreloader("image3d", {url: SANTA_SPRITES_URL, alpha: 0}, function() { for (var i = 0; i < NUM_OF_SANTAS; i++) { var clonedOverlay = Overlays.cloneOverlay(santa_loader.overlay); diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/floatingUIExample.js index f489159440..d661890254 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/floatingUIExample.js @@ -31,7 +31,7 @@ var bluePanel = mainPanel.addChild(new FloatingUIPanel ({ offsetPosition: { x: 0.1, y: 0.1, z: 0.2 } })); -var mainPanelBackground = new BillboardOverlay({ +var mainPanelBackground = new Image3DOverlay({ url: BG_IMAGE_URL, dimensions: { x: 0.5, @@ -84,7 +84,7 @@ var text = mainPanel.addChild(new Text3DOverlay({ backgroundAlpha: 0.9 })); -var redDot = mainPanel.addChild(new BillboardOverlay({ +var redDot = mainPanel.addChild(new Image3DOverlay({ url: RED_DOT_IMAGE_URL, dimensions: { x: 0.1, @@ -100,7 +100,7 @@ var redDot = mainPanel.addChild(new BillboardOverlay({ } })); -var redDot2 = mainPanel.addChild(new BillboardOverlay({ +var redDot2 = mainPanel.addChild(new Image3DOverlay({ url: RED_DOT_IMAGE_URL, dimensions: { x: 0.1, @@ -116,7 +116,7 @@ var redDot2 = mainPanel.addChild(new BillboardOverlay({ } })); -var blueSquare = bluePanel.addChild(new BillboardOverlay({ +var blueSquare = bluePanel.addChild(new Image3DOverlay({ url: BLUE_SQUARE_IMAGE_URL, dimensions: { x: 0.1, @@ -132,7 +132,7 @@ var blueSquare = bluePanel.addChild(new BillboardOverlay({ } })); -var blueSquare2 = bluePanel.addChild(new BillboardOverlay({ +var blueSquare2 = bluePanel.addChild(new Image3DOverlay({ url: BLUE_SQUARE_IMAGE_URL, dimensions: { x: 0.1, diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 98a71e3b12..b2f6474089 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -340,7 +340,7 @@ SelectionDisplay = (function () { leftMargin: 0, }); - var grabberMoveUp = Overlays.addOverlay("billboard", { + var grabberMoveUp = Overlays.addOverlay("image3d", { url: HIFI_PUBLIC_BUCKET + "images/up-arrow.svg", position: { x:0, y: 0, z: 0}, color: handleColor, @@ -609,7 +609,7 @@ SelectionDisplay = (function () { minorTickMarksColor: { red: 0, green: 0, blue: 0 }, }); - var yawHandle = Overlays.addOverlay("billboard", { + var yawHandle = Overlays.addOverlay("image3d", { url: ROTATE_ARROW_WEST_NORTH_URL, position: { x:0, y: 0, z: 0}, color: handleColor, @@ -622,7 +622,7 @@ SelectionDisplay = (function () { }); - var pitchHandle = Overlays.addOverlay("billboard", { + var pitchHandle = Overlays.addOverlay("image3d", { url: ROTATE_ARROW_WEST_NORTH_URL, position: { x:0, y: 0, z: 0}, color: handleColor, @@ -635,7 +635,7 @@ SelectionDisplay = (function () { }); - var rollHandle = Overlays.addOverlay("billboard", { + var rollHandle = Overlays.addOverlay("image3d", { url: ROTATE_ARROW_WEST_NORTH_URL, position: { x:0, y: 0, z: 0}, color: handleColor, diff --git a/examples/libraries/lightOverlayManager.js b/examples/libraries/lightOverlayManager.js index 9b26cae837..0942fae723 100644 --- a/examples/libraries/lightOverlayManager.js +++ b/examples/libraries/lightOverlayManager.js @@ -61,7 +61,7 @@ LightOverlayManager = function() { // Allocate or get an unused overlay function getOverlay() { if (unusedOverlays.length == 0) { - var overlay = Overlays.addOverlay("billboard", { + var overlay = Overlays.addOverlay("image3d", { }); allOverlays.push(overlay); } else { diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index fdb9800116..1b5031d143 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -8,7 +8,7 @@ // Manage overlays with object oriented goodness, instead of ugly `Overlays.h` methods. // Instead of: // -// var billboard = Overlays.addOverlay("billboard", { visible: false }); +// var billboard = Overlays.addOverlay("image3d", { visible: false }); // ... // Overlays.editOverlay(billboard, { visible: true }); // ... @@ -16,7 +16,7 @@ // // You can now do: // -// var billboard = new BillboardOverlay({ visible: false }); +// var billboard = new Image3DOverlay({ visible: false }); // ... // billboard.visible = true; // ... @@ -41,8 +41,13 @@ var overlays = {}; var panels = {}; - var overlayTypes; - var Overlay, Overlay2D, Base3DOverlay, Planar3DOverlay, Volume3DOverlay; + var overlayTypes, + Overlay, + Overlay2D, + Base3DOverlay, + Planar3DOverlay, + Billboard3DOverlay, + Volume3DOverlay; // @@ -123,7 +128,7 @@ // // Usage: // // Create an overlay - // var billboard = new BillboardOverlay({ + // var billboard = new Image3DOverlay({ // visible: true, // isFacingAvatar: true, // ignoreRayIntersections: false @@ -234,6 +239,10 @@ Overlays.deleteOverlay(this._id); }; + that.prototype.isPanelAttachable = function() { + return true; + }; + return generateOverlayClass(that, ABSTRACT, [ "alpha", "glowLevel", "pulseMax", "pulseMin", "pulsePeriod", "glowLevelPulse", "alphaPulse", "colorPulse", "visible", "anchor" @@ -253,6 +262,11 @@ "dimensions" ]); + Billboard3DOverlay = generateOverlayClass(Planar3DOverlay, ABSTRACT, [ + "isFacingAvatar" + ].concat(PANEL_ATTACHABLE_FIELDS)); + Billboard3DOverlay.prototype.isPanelAttachable = function() { return true; }; + Volume3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [ "dimensions" ]); @@ -261,14 +275,18 @@ "subImage", "imageURL" ]); + generateOverlayClass(Billboard3DOverlay, "image3d", [ + "url", "subImage" + ]); + generateOverlayClass(Overlay2D, "text", [ "font", "text", "backgroundColor", "backgroundAlpha", "leftMargin", "topMargin" ]); - generateOverlayClass(Planar3DOverlay, "text3d", [ + generateOverlayClass(Billboard3DOverlay, "text3d", [ "text", "backgroundColor", "backgroundAlpha", "lineHeight", "leftMargin", "topMargin", - "rightMargin", "bottomMargin", "isFacingAvatar" - ].concat(PANEL_ATTACHABLE_FIELDS)); + "rightMargin", "bottomMargin" + ]); generateOverlayClass(Volume3DOverlay, "cube", [ "borderSize" @@ -300,13 +318,10 @@ generateOverlayClass(Volume3DOverlay, "model", [ "url", "dimensions", "textures" ]); - - generateOverlayClass(Planar3DOverlay, "billboard", [ - "url", "subImage", "isFacingAvatar" - ].concat(PANEL_ATTACHABLE_FIELDS)); })(); ImageOverlay = overlayTypes["image"]; + Image3DOverlay = overlayTypes["image3d"]; TextOverlay = overlayTypes["text"]; Text3DOverlay = overlayTypes["text3d"]; Cube3DOverlay = overlayTypes["cube"]; @@ -317,7 +332,6 @@ Grid3DOverlay = overlayTypes["grid"]; LocalModelsOverlay = overlayTypes["localmodels"]; ModelOverlay = overlayTypes["model"]; - BillboardOverlay = overlayTypes["billboard"]; // @@ -334,6 +348,10 @@ that.prototype.constructor = that; + that.AddChildException = function(message) { + this.message = message; + }; + var FIELDS = ["offsetPosition", "offsetRotation", "facingRotation"]; FIELDS.forEach(function(prop) { Object.defineProperty(that.prototype, prop, { @@ -351,13 +369,6 @@ var PSEUDO_FIELDS = []; - PSEUDO_FIELDS.push("children"); - Object.defineProperty(that.prototype, "children", { - get: function() { - return this._children.slice(); - } - }); - PSEUDO_FIELDS.push("visible"); Object.defineProperty(that.prototype, "visible", { get: function() { @@ -371,8 +382,20 @@ } }); + Object.defineProperty(that.prototype, "attachedPanel", { + get: function() { + return this._attachedPanelPointer; + } + }); + + Object.defineProperty(that.prototype, "children", { + get: function() { + return this._children.slice(); + } + }); + that.prototype.addChild = function(child) { - if (child instanceof Overlay) { + if (child instanceof Overlay && child.isPanelAttachable()) { Overlays.setAttachedPanel(child._id, this._id); } else if (child instanceof FloatingUIPanel) { child.setProperties({ @@ -385,6 +408,8 @@ value: this._id } }); + } else { + throw new that.AddChildException("Given child is not panel attachable."); } child._attachedPanelPointer = this; child.visible = this.visible; @@ -431,8 +456,8 @@ function onOverlayDeleted(id) { if (id in overlays) { - if (overlays[id]._attachedPanelPointer) { - overlays[id]._attachedPanelPointer.removeChild(overlays[id]); + if (overlays[id].attachedPanel) { + overlays[id].attachedPanel.removeChild(overlays[id]); } delete overlays[id]; } @@ -440,9 +465,14 @@ 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]); + } delete panels[id]; } } diff --git a/examples/libraries/virtualKeyboard.js b/examples/libraries/virtualKeyboard.js index a1f952a5eb..7a0ec80a98 100644 --- a/examples/libraries/virtualKeyboard.js +++ b/examples/libraries/virtualKeyboard.js @@ -148,7 +148,7 @@ KeyboardKey = (function(keyboard, keyProperties) { }; for (var i = 0; i < this.bounds.length; i++) { if (THREE_D_MODE) { - this.overlays.push(Overlays.addOverlay("billboard", { + this.overlays.push(Overlays.addOverlay("image3d", { scale: 1, rotation: MyAvatar.rotation, isFacingAvatar: false, @@ -202,7 +202,7 @@ Keyboard = (function(params) { return windowDimensions.y - this.height(); }; if (THREE_D_MODE) { - this.background = Overlays.addOverlay("billboard", { + this.background = Overlays.addOverlay("image3d", { scale: 1, position: MyAvatar.position, rotation: MyAvatar.rotation, diff --git a/examples/notifications.js b/examples/notifications.js index 5ee6874521..461d28cd2c 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -260,7 +260,7 @@ function notify(notice, button, height) { positions = calculate3DOverlayPositions(noticeWidth, noticeHeight, notice.y); notifications.push((Overlays.addOverlay("text3d", notice))); - buttons.push((Overlays.addOverlay("billboard", button))); + buttons.push((Overlays.addOverlay("image3d", button))); overlay3DDetails.push({ notificationOrientation: positions.notificationOrientation, notificationPosition: positions.notificationPosition, diff --git a/examples/progress.js b/examples/progress.js index 55ea15f218..6dd26a9a11 100644 --- a/examples/progress.js +++ b/examples/progress.js @@ -117,7 +117,7 @@ visible: false, ignoreRayIntersection: true }); - bar3D.overlay = Overlays.addOverlay("billboard", { + bar3D.overlay = Overlays.addOverlay("image3d", { url: BAR_URL, subImage: { x: BAR_WIDTH, y: 0, width: BAR_WIDTH, height: BAR_HEIGHT }, scale: SCALE_3D * BAR_WIDTH, diff --git a/examples/sit.js b/examples/sit.js index da499b3b21..7efad487a7 100644 --- a/examples/sit.js +++ b/examples/sit.js @@ -175,7 +175,7 @@ function SeatIndicator(modelProperties, seatIndex) { modelProperties.sittingPoints[seatIndex].rotation); this.scale = MyAvatar.scale / 12; - this.sphere = Overlays.addOverlay("billboard", { + this.sphere = Overlays.addOverlay("image3d", { subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, url: buttonImageUrl, position: this.position, diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp new file mode 100644 index 0000000000..ffec368a53 --- /dev/null +++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp @@ -0,0 +1,55 @@ +// +// Billboard3DOverlay.cpp +// hifi/interface/src/ui/overlays +// +// Created by Zander Otavka on 8/4/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Billboard3DOverlay.h" +#include "Application.h" + +Billboard3DOverlay::Billboard3DOverlay() : + _isFacingAvatar(false) +{ +} + +Billboard3DOverlay::Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay) : + Planar3DOverlay(billboard3DOverlay), + PanelAttachable(billboard3DOverlay), + _isFacingAvatar(billboard3DOverlay->_isFacingAvatar) +{ +} + +void Billboard3DOverlay::setProperties(const QScriptValue &properties) { + Planar3DOverlay::setProperties(properties); + PanelAttachable::setProperties(properties); + + QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar"); + if (isFacingAvatarValue.isValid()) { + _isFacingAvatar = isFacingAvatarValue.toVariant().toBool(); + } +} + +QScriptValue Billboard3DOverlay::getProperty(const QString &property) { + if (property == "isFacingAvatar") { + return _isFacingAvatar; + } + + QScriptValue value = PanelAttachable::getProperty(_scriptEngine, property); + if (value.isValid()) { + return value; + } + return Planar3DOverlay::getProperty(property); +} + +void Billboard3DOverlay::setTransforms(Transform& transform) { + PanelAttachable::setTransforms(transform); + if (_isFacingAvatar) { + glm::quat rotation = Application::getInstance()->getCamera()->getOrientation(); + transform.setRotation(rotation); + } +} diff --git a/interface/src/ui/overlays/Billboard3DOverlay.h b/interface/src/ui/overlays/Billboard3DOverlay.h new file mode 100644 index 0000000000..1aa973539b --- /dev/null +++ b/interface/src/ui/overlays/Billboard3DOverlay.h @@ -0,0 +1,38 @@ +// +// Billboard3DOverlay.h +// hifi/interface/src/ui/overlays +// +// Created by Zander Otavka on 8/4/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_Billboard3DOverlay_h +#define hifi_Billboard3DOverlay_h + +#include "Planar3DOverlay.h" +#include "PanelAttachable.h" + +class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable { + Q_OBJECT + +public: + Billboard3DOverlay(); + Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay); + + bool getIsFacingAvatar() const { return _isFacingAvatar; } + void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } + + virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); + +protected: + virtual void setTransforms(Transform& transform); + +private: + bool _isFacingAvatar; +}; + +#endif // hifi_Billboard3DOverlay_h diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp similarity index 71% rename from interface/src/ui/overlays/BillboardOverlay.cpp rename to interface/src/ui/overlays/Image3DOverlay.cpp index 2cde21227c..98e6d31486 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -1,15 +1,16 @@ // -// BillboardOverlay.cpp +// Image3DOverlay.cpp // // // Created by Clement on 7/1/14. +// Modified and renamed by Zander Otavka on 8/4/15 // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "BillboardOverlay.h" +#include "Image3DOverlay.h" #include @@ -17,41 +18,30 @@ #include #include #include -#include #include "Application.h" #include "GeometryUtil.h" -QString const BillboardOverlay::TYPE = "billboard"; +QString const Image3DOverlay::TYPE = "image3d"; -BillboardOverlay::BillboardOverlay() { +Image3DOverlay::Image3DOverlay() { _isLoaded = false; } -BillboardOverlay::BillboardOverlay(const BillboardOverlay* billboardOverlay) : - Planar3DOverlay(billboardOverlay), - PanelAttachable(billboardOverlay), - _url(billboardOverlay->_url), - _texture(billboardOverlay->_texture), - _fromImage(billboardOverlay->_fromImage), - _isFacingAvatar(billboardOverlay->_isFacingAvatar) +Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) : + Billboard3DOverlay(image3DOverlay), + _url(image3DOverlay->_url), + _texture(image3DOverlay->_texture), + _fromImage(image3DOverlay->_fromImage) { } -void BillboardOverlay::setTransforms(Transform& transform) { - PanelAttachable::setTransforms(transform); - if (_isFacingAvatar) { - glm::quat rotation = Application::getInstance()->getCamera()->getOrientation(); - transform.setRotation(rotation); - } -} - -void BillboardOverlay::update(float deltatime) { +void Image3DOverlay::update(float deltatime) { setTransforms(_transform); } -void BillboardOverlay::render(RenderArgs* args) { +void Image3DOverlay::render(RenderArgs* args) { if (!_texture) { _isLoaded = true; _texture = DependencyManager::get()->getTexture(_url); @@ -104,7 +94,7 @@ void BillboardOverlay::render(RenderArgs* args) { batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); - + DependencyManager::get()->bindSimpleProgram(*batch, true, true, false, true); DependencyManager::get()->renderQuad( *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, @@ -114,15 +104,14 @@ void BillboardOverlay::render(RenderArgs* args) { batch->setResourceTexture(0, args->_whiteTexture); // restore default white color after me } -void BillboardOverlay::setProperties(const QScriptValue &properties) { - Planar3DOverlay::setProperties(properties); - PanelAttachable::setProperties(properties); +void Image3DOverlay::setProperties(const QScriptValue &properties) { + Billboard3DOverlay::setProperties(properties); QScriptValue urlValue = properties.property("url"); if (urlValue.isValid()) { QString newURL = urlValue.toVariant().toString(); if (newURL != _url) { - setBillboardURL(newURL); + setURL(newURL); } } @@ -156,50 +145,34 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) { setClipFromSource(subImageRect); } } - - QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar"); - if (isFacingAvatarValue.isValid()) { - _isFacingAvatar = isFacingAvatarValue.toVariant().toBool(); - } } -QScriptValue BillboardOverlay::getProperty(const QString& property) { +QScriptValue Image3DOverlay::getProperty(const QString& property) { if (property == "url") { return _url; } if (property == "subImage") { return qRectToScriptValue(_scriptEngine, _fromImage); } - if (property == "isFacingAvatar") { - return _isFacingAvatar; - } if (property == "offsetPosition") { return vec3toScriptValue(_scriptEngine, getOffsetPosition()); } - QScriptValue value = PanelAttachable::getProperty(_scriptEngine, property); - if (value.isValid()) { - return value; - } - return Planar3DOverlay::getProperty(property); + return Billboard3DOverlay::getProperty(property); } -void BillboardOverlay::setURL(const QString& url) { - setBillboardURL(url); -} - -void BillboardOverlay::setBillboardURL(const QString& url) { +void Image3DOverlay::setURL(const QString& url) { _url = url; _isLoaded = false; } -bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) { +bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face) { if (_texture && _texture->isLoaded()) { // Make sure position and rotation is updated. setTransforms(_transform); - // Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale. + // Produce the dimensions of the overlay based on the image's aspect ratio and the overlay's scale. bool isNull = _fromImage.isNull(); float width = isNull ? _texture->getWidth() : _fromImage.width(); float height = isNull ? _texture->getHeight() : _fromImage.height(); @@ -212,6 +185,6 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v return false; } -BillboardOverlay* BillboardOverlay::createClone() const { - return new BillboardOverlay(this); +Image3DOverlay* Image3DOverlay::createClone() const { + return new Image3DOverlay(this); } diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/Image3DOverlay.h similarity index 60% rename from interface/src/ui/overlays/BillboardOverlay.h rename to interface/src/ui/overlays/Image3DOverlay.h index a034612e71..0c71fef173 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/Image3DOverlay.h @@ -1,30 +1,31 @@ // -// BillboardOverlay.h +// Image3DOverlay.h // // // Created by Clement on 7/1/14. +// Modified and renamed by Zander Otavka on 8/4/15 // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_BillboardOverlay_h -#define hifi_BillboardOverlay_h +#ifndef hifi_Image3DOverlay_h +#define hifi_Image3DOverlay_h #include -#include "Planar3DOverlay.h" -#include "PanelAttachable.h" +#include "Billboard3DOverlay.h" -class BillboardOverlay : public Planar3DOverlay, public PanelAttachable { +class Image3DOverlay : public Billboard3DOverlay { Q_OBJECT + public: static QString const TYPE; virtual QString getType() const { return TYPE; } - BillboardOverlay(); - BillboardOverlay(const BillboardOverlay* billboardOverlay); + Image3DOverlay(); + Image3DOverlay(const Image3DOverlay* image3DOverlay); virtual void render(RenderArgs* args); @@ -32,28 +33,20 @@ public: // setters void setURL(const QString& url); - void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } + void setClipFromSource(const QRect& bounds) { _fromImage = bounds; } virtual void setProperties(const QScriptValue& properties); - void setClipFromSource(const QRect& bounds) { _fromImage = bounds; } virtual QScriptValue getProperty(const QString& property); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); - - virtual BillboardOverlay* createClone() const; -protected: - virtual void setTransforms(Transform& transform); + virtual Image3DOverlay* createClone() const; private: - void setBillboardURL(const QString& url); - QString _url; NetworkTexturePointer _texture; - - QRect _fromImage; // where from in the image to sample - bool _isFacingAvatar = true; + QRect _fromImage; // where from in the image to sample }; -#endif // hifi_BillboardOverlay_h +#endif // hifi_Image3DOverlay_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index bce219b4b4..9bc50146d1 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -19,7 +19,7 @@ #include #include "Application.h" -#include "BillboardOverlay.h" +#include "Image3DOverlay.h" #include "Circle3DOverlay.h" #include "Cube3DOverlay.h" #include "ImageOverlay.h" @@ -160,8 +160,8 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay = std::make_shared(Application::getInstance()->getEntityClipboardRenderer()); } else if (type == ModelOverlay::TYPE) { thisOverlay = std::make_shared(); - } else if (type == BillboardOverlay::TYPE) { - thisOverlay = std::make_shared(); + } else if (type == Image3DOverlay::TYPE) { + thisOverlay = std::make_shared(); } if (thisOverlay) { diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index e6b37d693b..5b91ff5b52 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -18,7 +18,7 @@ #include #include -#include "BillboardOverlay.h" +#include "Image3DOverlay.h" #include "Circle3DOverlay.h" #include "Cube3DOverlay.h" #include "ImageOverlay.h" diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 04545c59c9..030043b18c 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -32,15 +32,13 @@ Text3DOverlay::Text3DOverlay() : _leftMargin(DEFAULT_MARGIN), _topMargin(DEFAULT_MARGIN), _rightMargin(DEFAULT_MARGIN), - _bottomMargin(DEFAULT_MARGIN), - _isFacingAvatar(false) + _bottomMargin(DEFAULT_MARGIN) { _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); } Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : - Planar3DOverlay(text3DOverlay), - PanelAttachable(text3DOverlay), + Billboard3DOverlay(text3DOverlay), _text(text3DOverlay->_text), _backgroundColor(text3DOverlay->_backgroundColor), _backgroundAlpha(text3DOverlay->_backgroundAlpha), @@ -48,8 +46,7 @@ Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : _leftMargin(text3DOverlay->_leftMargin), _topMargin(text3DOverlay->_topMargin), _rightMargin(text3DOverlay->_rightMargin), - _bottomMargin(text3DOverlay->_bottomMargin), - _isFacingAvatar(text3DOverlay->_isFacingAvatar) + _bottomMargin(text3DOverlay->_bottomMargin) { _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); } @@ -77,14 +74,6 @@ xColor Text3DOverlay::getBackgroundColor() { return result; } -void Text3DOverlay::setTransforms(Transform &transform) { - PanelAttachable::setTransforms(transform); - if (_isFacingAvatar) { - glm::quat rotation = Application::getInstance()->getCamera()->getOrientation(); - transform.setRotation(rotation); - } -} - void Text3DOverlay::update(float deltatime) { setTransforms(_transform); } @@ -136,8 +125,7 @@ void Text3DOverlay::render(RenderArgs* args) { } void Text3DOverlay::setProperties(const QScriptValue& properties) { - Planar3DOverlay::setProperties(properties); - PanelAttachable::setProperties(properties); + Billboard3DOverlay::setProperties(properties); QScriptValue text = properties.property("text"); if (text.isValid()) { @@ -179,12 +167,6 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) { if (properties.property("bottomMargin").isValid()) { setBottomMargin(properties.property("bottomMargin").toVariant().toFloat()); } - - QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar"); - if (isFacingAvatarValue.isValid()) { - _isFacingAvatar = isFacingAvatarValue.toVariant().toBool(); - } - } QScriptValue Text3DOverlay::getProperty(const QString& property) { @@ -212,15 +194,8 @@ QScriptValue Text3DOverlay::getProperty(const QString& property) { if (property == "bottomMargin") { return _bottomMargin; } - if (property == "isFacingAvatar") { - return _isFacingAvatar; - } - QScriptValue value = PanelAttachable::getProperty(_scriptEngine, property); - if (value.isValid()) { - return value; - } - return Planar3DOverlay::getProperty(property); + return Billboard3DOverlay::getProperty(property); } Text3DOverlay* Text3DOverlay::createClone() const { @@ -238,5 +213,5 @@ QSizeF Text3DOverlay::textSize(const QString& text) const { bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance, BoxFace &face) { setTransforms(_transform); - return Planar3DOverlay::findRayIntersection(origin, direction, distance, face); + return Billboard3DOverlay::findRayIntersection(origin, direction, distance, face); } diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index 0893a7cd73..e5e0ff7b96 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -13,12 +13,11 @@ #include -#include "Planar3DOverlay.h" -#include "PanelAttachable.h" +#include "Billboard3DOverlay.h" class TextRenderer3D; -class Text3DOverlay : public Planar3DOverlay, public PanelAttachable { +class Text3DOverlay : public Billboard3DOverlay { Q_OBJECT public: @@ -39,7 +38,6 @@ public: float getTopMargin() const { return _topMargin; } float getRightMargin() const { return _rightMargin; } float getBottomMargin() const { return _bottomMargin; } - bool getIsFacingAvatar() const { return _isFacingAvatar; } xColor getBackgroundColor(); float getBackgroundAlpha() const { return _backgroundAlpha; } @@ -50,7 +48,6 @@ public: void setTopMargin(float margin) { _topMargin = margin; } void setRightMargin(float margin) { _rightMargin = margin; } void setBottomMargin(float margin) { _bottomMargin = margin; } - void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); @@ -61,9 +58,6 @@ public: virtual Text3DOverlay* createClone() const; -protected: - virtual void setTransforms(Transform& transform); - private: TextRenderer3D* _textRenderer = nullptr; @@ -75,7 +69,6 @@ private: float _topMargin; float _rightMargin; float _bottomMargin; - bool _isFacingAvatar; }; From 22453aa3ce5c2e5b24de713b13faaaf02be52916 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 4 Aug 2015 14:04:13 -0700 Subject: [PATCH 06/42] 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); From a21fa94f1421bf25c9dc83f933a9140441fe0048 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 4 Aug 2015 15:06:12 -0700 Subject: [PATCH 07/42] Fix error in floatingUIExample.js. Script would crash if the user left clicked somewhere not on an overlay. --- examples/example/ui/floatingUIExample.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/floatingUIExample.js index d661890254..7270a5a13f 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/floatingUIExample.js @@ -170,10 +170,10 @@ function onMouseDown(event) { function onMouseUp(event) { if (event.isLeftButton) { var overlay = OverlayManager.findAtPoint({ x: event.x, y: event.y }); - if (overlay === mouseDown.overlay) { + if (overlay && overlay === mouseDown.overlay) { if (overlay.attachedPanel === bluePanel) { overlay.destroy(); - } else if (overlay) { + } else { var oldPos = overlay.offsetPosition; var newPos = { x: Number(oldPos.x), From cb5b5fcfc4367770454ec9a37e90c9071646a6c7 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 4 Aug 2015 17:10:36 -0700 Subject: [PATCH 08/42] Increase right click move threshold. --- examples/controlPanel.js | 2 +- examples/example/ui/floatingUIExample.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/controlPanel.js b/examples/controlPanel.js index 53e9dbc05a..e579eddc63 100644 --- a/examples/controlPanel.js +++ b/examples/controlPanel.js @@ -191,7 +191,7 @@ function onMouseUp(event) { overlay.onClick(event); } } - if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 5) { + if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 10) { panel.setProperties({ visible: !panel.visible, offsetRotation: { diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/floatingUIExample.js index 7270a5a13f..6a8278ac8a 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/floatingUIExample.js @@ -184,7 +184,7 @@ function onMouseUp(event) { } } } - if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 5) { + if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 10) { mainPanel.visible = !mainPanel.visible; } } From 90bfce25e531f5dc9e4525792d8ce61faad7b85c Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 4 Aug 2015 17:10:56 -0700 Subject: [PATCH 09/42] Add anchorPosition as a field for FloatingUIPanel. --- examples/libraries/overlayManager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index d857efd0be..be89b68631 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -110,7 +110,7 @@ } // - // Get or create an overlay object from the id. + // Get or create a panel object from the id. // // @param knownOverlaysOnly (Optional: Boolean) // If true, a new object will not be created. @@ -391,7 +391,7 @@ this.message = message; }; - var FIELDS = ["offsetPosition", "offsetRotation", "facingRotation"]; + var FIELDS = ["anchorPosition", "offsetRotation", "offsetPosition", "facingRotation"]; FIELDS.forEach(function(prop) { Object.defineProperty(that.prototype, prop, { get: function() { From 4965f1adda4fd7a654fa4a2f745d2dbb0f03d1eb Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 5 Aug 2015 09:20:55 -0700 Subject: [PATCH 10/42] Fix a facingRotation issue for PanelAttachable. --- interface/src/ui/overlays/PanelAttachable.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 6b453bddc7..1de1efcf5e 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -32,8 +32,9 @@ void PanelAttachable::setTransforms(Transform& transform) { transform.setTranslation(getAttachedPanel()->getAnchorPosition()); transform.setRotation(getAttachedPanel()->getOffsetRotation()); transform.postTranslate(getAttachedPanel()->getOffsetPosition()); - transform.postRotate(getFacingRotation() * getAttachedPanel()->getFacingRotation()); + transform.postRotate(getAttachedPanel()->getFacingRotation()); transform.postTranslate(getOffsetPosition()); + transform.postRotate(getFacingRotation()); } } From eab35d03d4ac70c413dad4fdd9b5a71e1e4b0176 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 5 Aug 2015 10:24:03 -0700 Subject: [PATCH 11/42] Improve vector operations in floatingUIExample.js. --- examples/example/ui/floatingUIExample.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/floatingUIExample.js index 6a8278ac8a..59d3b67d38 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/floatingUIExample.js @@ -174,13 +174,7 @@ function onMouseUp(event) { if (overlay.attachedPanel === bluePanel) { overlay.destroy(); } else { - var oldPos = overlay.offsetPosition; - var newPos = { - x: Number(oldPos.x), - y: Number(oldPos.y), - z: Number(oldPos.z) - 0.1 - }; - overlay.offsetPosition = newPos; + overlay.offsetPosition = Vec3.sum(overlay.offsetPosition, { x: 0, y: 0, z: -0.1 }); } } } From 5778502c54bef3c0e930e774a32f54de11bb2dcb Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 5 Aug 2015 10:25:33 -0700 Subject: [PATCH 12/42] Improve child removal logic for FloatingUIPanels. --- examples/libraries/overlayManager.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index be89b68631..212e8beab7 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -448,9 +448,7 @@ that.prototype.removeChild = function(child) { var i = this._children.indexOf(child); if (i >= 0) { - if (child instanceof Overlay || child instanceof FloatingUIPanel) { - Overlays.setAttachedPanel(child._id, 0); - } + Overlays.setAttachedPanel(child._id, 0); this._children.splice(i, 1); } }; From 481624b48c0921c5b7f7a4b78a3f8ac1639ca675 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 5 Aug 2015 14:21:23 -0700 Subject: [PATCH 13/42] Re-work panel position and rotation binding. --- examples/controlPanel.js | 9 +- examples/example/ui/floatingUIExample.js | 8 +- examples/libraries/overlayManager.js | 6 +- interface/src/ui/overlays/FloatingUIPanel.cpp | 188 ++++++++---------- interface/src/ui/overlays/FloatingUIPanel.h | 36 ++-- interface/src/ui/overlays/Overlays.cpp | 8 +- interface/src/ui/overlays/PanelAttachable.cpp | 4 +- 7 files changed, 112 insertions(+), 147 deletions(-) diff --git a/examples/controlPanel.js b/examples/controlPanel.js index e579eddc63..3ff054f3c8 100644 --- a/examples/controlPanel.js +++ b/examples/controlPanel.js @@ -23,9 +23,7 @@ var FACE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/face-toggle.svg"; var ADDRESS_BAR_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/address-bar-toggle.svg"; var panel = new FloatingUIPanel({ - anchorPosition: { - bind: "myAvatar" - }, + anchorPositionBinding: { avatar: "MyAvatar" }, offsetPosition: { x: 0, y: 0.4, z: 1 }, facingRotation: { w: 0, x: 0, y: 1, z: 0 } }); @@ -194,10 +192,7 @@ function onMouseUp(event) { if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 10) { panel.setProperties({ visible: !panel.visible, - offsetRotation: { - bind: "quat", - value: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 }) - } + offsetRotation: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 }) }); } diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/floatingUIExample.js index 59d3b67d38..8eaeeff98b 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/floatingUIExample.js @@ -19,10 +19,8 @@ var RED_DOT_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/red-dot.svg"; var BLUE_SQUARE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/blue-square.svg"; var mainPanel = new FloatingUIPanel({ - offsetRotation: { - bind: "quat", - value: { w: 1, x: 0, y: 0, z: 0 } - }, + anchorPositionBinding: null,//{ avatar: "MyAvatar" }, + offsetRotation: { w: 1, x: 0, y: 0, z: 0 }, offsetPosition: { x: 0, y: 0.4, z: 1 }, facingRotation: { w: 0, x: 0, y: 1, z: 0 } }); @@ -189,4 +187,4 @@ function onScriptEnd() { Controller.mousePressEvent.connect(onMouseDown); Controller.mouseReleaseEvent.connect(onMouseUp); -Script.scriptEnding.connect(onScriptEnd); \ No newline at end of file +Script.scriptEnding.connect(onScriptEnd); diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index 212e8beab7..147df87831 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -391,8 +391,10 @@ this.message = message; }; - var FIELDS = ["anchorPosition", "offsetRotation", "offsetPosition", "facingRotation"]; - FIELDS.forEach(function(prop) { + [ + "anchorPosition", "anchorPositionBinding", "offsetRotation", "offsetRotationBinding", + "offsetPosition", "facingRotation" + ].forEach(function(prop) { Object.defineProperty(that.prototype, prop, { get: function() { return Overlays.getPanelProperty(this._id, prop); diff --git a/interface/src/ui/overlays/FloatingUIPanel.cpp b/interface/src/ui/overlays/FloatingUIPanel.cpp index 496218d7ed..99eab0f241 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.cpp +++ b/interface/src/ui/overlays/FloatingUIPanel.cpp @@ -20,41 +20,33 @@ #include "Application.h" #include "Base3DOverlay.h" -std::function const FloatingUIPanel::AVATAR_POSITION = []() -> glm::vec3 { - return DependencyManager::get()->getMyAvatar()->getPosition(); -}; +glm::vec3 FloatingUIPanel::getComputedAnchorPosition() const { + glm::vec3 pos = {}; + if (getAttachedPanel()) { + pos = getAttachedPanel()->getPosition(); + } else if (_anchorPositionBindMyAvatar) { + pos = DependencyManager::get()->getMyAvatar()->getPosition(); + } + return pos + getAnchorPosition(); +} -std::function const FloatingUIPanel::AVATAR_ORIENTATION = []() -> glm::quat { - return DependencyManager::get()->getMyAvatar()->getOrientation() * - glm::angleAxis(glm::pi(), IDENTITY_UP); -}; +glm::quat FloatingUIPanel::getComputedOffsetRotation() const { + glm::quat rot = {1, 0, 0, 0}; + if (getAttachedPanel()) { + rot = getAttachedPanel()->getRotation(); + } else if (_offsetRotationBindMyAvatar) { + rot = DependencyManager::get()->getMyAvatar()->getOrientation() * + glm::angleAxis(glm::pi(), IDENTITY_UP); + } + return rot * getOffsetRotation(); +} glm::vec3 FloatingUIPanel::getPosition() const { - return getOffsetRotation() * getOffsetPosition() + getAnchorPosition(); + return getComputedOffsetRotation() * getOffsetPosition() + getComputedAnchorPosition(); } glm::quat FloatingUIPanel::getRotation() const { - return getOffsetRotation() * getFacingRotation(); -} - -void FloatingUIPanel::setAnchorPosition(const glm::vec3& position) { - setAnchorPosition([position]() -> glm::vec3 { - return position; - }); -} - -void FloatingUIPanel::setOffsetRotation(const glm::quat& rotation) { - setOffsetRotation([rotation]() -> glm::quat { - return rotation; - }); -} - -void FloatingUIPanel::setAttachedPanel(unsigned int panelID) { - if (panelID) { - attachAnchorToPanel(panelID); - attachRotationToPanel(panelID); - } - _attachedPanel = panelID; + return getComputedOffsetRotation() * getFacingRotation(); } void FloatingUIPanel::addChild(unsigned int childId) { @@ -73,9 +65,25 @@ QScriptValue FloatingUIPanel::getProperty(const QString &property) { if (property == "anchorPosition") { return vec3toScriptValue(_scriptEngine, getAnchorPosition()); } + if (property == "anchorPositionBinding") { + QScriptValue obj = _scriptEngine->newObject(); + if (_anchorPositionBindMyAvatar) { + obj.setProperty("avatar", "MyAvatar"); + } + obj.setProperty("computed", vec3toScriptValue(_scriptEngine, getComputedAnchorPosition())); + return obj; + } if (property == "offsetRotation") { return quatToScriptValue(_scriptEngine, getOffsetRotation()); } + if (property == "offsetRotationBinding") { + QScriptValue obj = _scriptEngine->newObject(); + if (_offsetRotationBindMyAvatar) { + obj.setProperty("avatar", "MyAvatar"); + } + obj.setProperty("computed", quatToScriptValue(_scriptEngine, getComputedOffsetRotation())); + return obj; + } if (property == "offsetPosition") { return vec3toScriptValue(_scriptEngine, getOffsetPosition()); } @@ -87,80 +95,56 @@ QScriptValue FloatingUIPanel::getProperty(const QString &property) { } void FloatingUIPanel::setProperties(const QScriptValue &properties) { - QScriptValue anchor = properties.property("anchorPosition"); - if (anchor.isValid()) { - QScriptValue bindType = anchor.property("bind"); - QScriptValue value = anchor.property("value"); + QScriptValue anchorPosition = properties.property("anchorPosition"); + if (anchorPosition.isValid()) { + QScriptValue x = anchorPosition.property("x"); + QScriptValue y = anchorPosition.property("y"); + QScriptValue z = anchorPosition.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(); + setAnchorPosition(newPosition); + } + } - if (bindType.isValid()) { - QString bindTypeString = bindType.toVariant().toString(); - if (bindTypeString == "myAvatar") { - setAnchorPosition(AVATAR_POSITION); - } else if (value.isValid()) { - if (bindTypeString == "overlay") { - Overlay::Pointer overlay = Application::getInstance()->getOverlays() - .getOverlay(value.toVariant().toUInt()); - if (overlay->is3D()) { - auto overlay3D = std::static_pointer_cast(overlay); - setAnchorPosition([&overlay3D]() -> glm::vec3 { - return overlay3D->getPosition(); - }); - } - } else if (bindTypeString == "panel") { - attachAnchorToPanel(value.toVariant().toUInt()); - } else if (bindTypeString == "vec3") { - QScriptValue x = value.property("x"); - QScriptValue y = value.property("y"); - QScriptValue z = value.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(); - setAnchorPosition(newPosition); - } - } - } + QScriptValue anchorPositionBinding = properties.property("anchorPositionBinding"); + if (anchorPositionBinding.isValid()) { + _anchorPositionBindMyAvatar = false; + + QScriptValue avatar = anchorPositionBinding.property("avatar"); + + if (avatar.isValid()) { + _anchorPositionBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); } } QScriptValue offsetRotation = properties.property("offsetRotation"); if (offsetRotation.isValid()) { - QScriptValue bindType = offsetRotation.property("bind"); - QScriptValue value = offsetRotation.property("value"); + QScriptValue x = offsetRotation.property("x"); + QScriptValue y = offsetRotation.property("y"); + QScriptValue z = offsetRotation.property("z"); + QScriptValue w = offsetRotation.property("w"); - if (bindType.isValid()) { - QString bindTypeString = bindType.toVariant().toString(); - if (bindTypeString == "myAvatar") { - setOffsetRotation(AVATAR_ORIENTATION); - } else if (value.isValid()) { - if (bindTypeString == "overlay") { - Overlay::Pointer overlay = Application::getInstance()->getOverlays() - .getOverlay(value.toVariant().toUInt()); - if (overlay->is3D()) { - auto overlay3D = std::static_pointer_cast(overlay); - setOffsetRotation([&overlay3D]() -> glm::quat { - return overlay3D->getRotation(); - }); - } - } else if (bindTypeString == "panel") { - attachRotationToPanel(value.toVariant().toUInt()); - } else if (bindTypeString == "quat") { - QScriptValue x = value.property("x"); - QScriptValue y = value.property("y"); - QScriptValue z = value.property("z"); - QScriptValue w = value.property("w"); + 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); + } + } - 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 offsetRotationBinding = properties.property("offsetRotationBinding"); + if (offsetRotationBinding.isValid()) { + _offsetRotationBindMyAvatar = false; + + QScriptValue avatar = offsetRotationBinding.property("avatar"); + + if (avatar.isValid()) { + _offsetRotationBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); } } @@ -195,17 +179,3 @@ 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 1b9c732b47..a45f57fe4d 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.h +++ b/interface/src/ui/overlays/FloatingUIPanel.h @@ -12,7 +12,6 @@ #ifndef hifi_FloatingUIPanel_h #define hifi_FloatingUIPanel_h -#include #include #include @@ -21,26 +20,29 @@ class FloatingUIPanel : public QObject { Q_OBJECT + public: typedef std::shared_ptr Pointer; void init(QScriptEngine* scriptEngine) { _scriptEngine = scriptEngine; } - glm::vec3 getAnchorPosition() const { return _anchorPosition(); } - glm::quat getOffsetRotation() const { return _offsetRotation(); } + // getters + glm::vec3 getAnchorPosition() const { return _anchorPosition; } + glm::vec3 getComputedAnchorPosition() const; + glm::quat getOffsetRotation() const { return _offsetRotation; } + glm::quat getComputedOffsetRotation() const; glm::vec3 getOffsetPosition() const { return _offsetPosition; } glm::quat getFacingRotation() const { return _facingRotation; } glm::vec3 getPosition() const; glm::quat getRotation() const; - unsigned int getAttachedPanel() const { return _attachedPanel; } + Pointer getAttachedPanel() const { return _attachedPanel; } - void setAnchorPosition(const std::function& func) { _anchorPosition = func; } - void setAnchorPosition(const glm::vec3& position); - void setOffsetRotation(const std::function& func) { _offsetRotation = func; } - void setOffsetRotation(const glm::quat& rotation); + // setters + void setAnchorPosition(const glm::vec3& position) { _anchorPosition = position; } + void setOffsetRotation(const glm::quat& rotation) { _offsetRotation = rotation; } void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; } - void setAttachedPanel(unsigned int panelID); + void setAttachedPanel(Pointer panel) { _attachedPanel = panel; } const QList& getChildren() { return _children; } void addChild(unsigned int childId); @@ -51,17 +53,15 @@ public: void setProperties(const QScriptValue& properties); private: - static std::function const AVATAR_POSITION; - static std::function const AVATAR_ORIENTATION; + glm::vec3 _anchorPosition = {0, 0, 0}; + glm::quat _offsetRotation = {1, 0, 0, 0}; + glm::vec3 _offsetPosition = {0, 0, 0}; + glm::quat _facingRotation = {1, 0, 0, 0}; - void attachAnchorToPanel(unsigned int panelID); - void attachRotationToPanel(unsigned int panelID); + bool _anchorPositionBindMyAvatar = false; + bool _offsetRotationBindMyAvatar = false; - 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}; + Pointer _attachedPanel = nullptr; QScriptEngine* _scriptEngine; QList _children; }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index a7762b3f81..a715001040 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -278,7 +278,7 @@ unsigned int Overlays::getAttachedPanel(unsigned int childId) const { if (attachable) { return _panels.key(attachable->getAttachedPanel()); } else if (_panels.contains(childId)) { - return getPanel(childId)->getAttachedPanel(); + return _panels.key(getPanel(childId)->getAttachedPanel()); } return 0; } @@ -299,13 +299,13 @@ void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) { } } } else if (_panels.contains(childId)) { - auto child = getPanel(childId); + FloatingUIPanel::Pointer child = getPanel(childId); if (_panels.contains(panelId)) { auto panel = getPanel(panelId); panel->addChild(childId); - child->setAttachedPanel(panelId); + child->setAttachedPanel(panel); } else { - auto panel = getPanel(child->getAttachedPanel()); + auto panel = child->getAttachedPanel(); if (panel) { panel->removeChild(childId); child->setAttachedPanel(0); diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 1de1efcf5e..fa029f12c9 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -29,8 +29,8 @@ PanelAttachable::PanelAttachable(const PanelAttachable* panelAttachable) : void PanelAttachable::setTransforms(Transform& transform) { if (getAttachedPanel()) { - transform.setTranslation(getAttachedPanel()->getAnchorPosition()); - transform.setRotation(getAttachedPanel()->getOffsetRotation()); + transform.setTranslation(getAttachedPanel()->getComputedAnchorPosition()); + transform.setRotation(getAttachedPanel()->getComputedOffsetRotation()); transform.postTranslate(getAttachedPanel()->getOffsetPosition()); transform.postRotate(getAttachedPanel()->getFacingRotation()); transform.postTranslate(getOffsetPosition()); From 4a1fcbf160326a15a700292e38cc1451f82d8e82 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 5 Aug 2015 16:11:09 -0700 Subject: [PATCH 14/42] Fix error in an unused method declaration. --- libraries/entities/src/EntityScriptingInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index c232437757..44aae2be33 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -61,7 +61,7 @@ public: virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); } void setEntityTree(EntityTree* modelTree); - EntityTree* getEntityTree(EntityTree*) { return _entityTree; } + EntityTree* getEntityTree() { return _entityTree; } public slots: From 865067aad9f531a674fabfbf2d7ebbe076676cf1 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 5 Aug 2015 16:12:46 -0700 Subject: [PATCH 15/42] Add ability to bind a panel to an entity. --- interface/src/ui/overlays/FloatingUIPanel.cpp | 23 +++++++++++++++++++ interface/src/ui/overlays/FloatingUIPanel.h | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/interface/src/ui/overlays/FloatingUIPanel.cpp b/interface/src/ui/overlays/FloatingUIPanel.cpp index 99eab0f241..2fc33bd9ad 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.cpp +++ b/interface/src/ui/overlays/FloatingUIPanel.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "avatar/AvatarManager.h" #include "avatar/MyAvatar.h" @@ -26,6 +27,9 @@ glm::vec3 FloatingUIPanel::getComputedAnchorPosition() const { pos = getAttachedPanel()->getPosition(); } else if (_anchorPositionBindMyAvatar) { pos = DependencyManager::get()->getMyAvatar()->getPosition(); + } else if (!_anchorPositionBindEntity.isNull()) { + pos = DependencyManager::get()->getEntityTree()-> + findEntityByID(_anchorPositionBindEntity)->getPosition(); } return pos + getAnchorPosition(); } @@ -37,6 +41,9 @@ glm::quat FloatingUIPanel::getComputedOffsetRotation() const { } else if (_offsetRotationBindMyAvatar) { rot = DependencyManager::get()->getMyAvatar()->getOrientation() * glm::angleAxis(glm::pi(), IDENTITY_UP); + } else if (!_offsetRotationBindEntity.isNull()) { + rot = DependencyManager::get()->getEntityTree()-> + findEntityByID(_offsetRotationBindEntity)->getRotation(); } return rot * getOffsetRotation(); } @@ -67,9 +74,13 @@ QScriptValue FloatingUIPanel::getProperty(const QString &property) { } if (property == "anchorPositionBinding") { QScriptValue obj = _scriptEngine->newObject(); + if (_anchorPositionBindMyAvatar) { obj.setProperty("avatar", "MyAvatar"); + } else if (!_anchorPositionBindEntity.isNull()) { + obj.setProperty("entity", _scriptEngine->newVariant(_anchorPositionBindEntity)); } + obj.setProperty("computed", vec3toScriptValue(_scriptEngine, getComputedAnchorPosition())); return obj; } @@ -78,9 +89,13 @@ QScriptValue FloatingUIPanel::getProperty(const QString &property) { } if (property == "offsetRotationBinding") { QScriptValue obj = _scriptEngine->newObject(); + if (_offsetRotationBindMyAvatar) { obj.setProperty("avatar", "MyAvatar"); + } else if (!_offsetRotationBindEntity.isNull()) { + obj.setProperty("entity", _scriptEngine->newVariant(_offsetRotationBindEntity)); } + obj.setProperty("computed", quatToScriptValue(_scriptEngine, getComputedOffsetRotation())); return obj; } @@ -112,11 +127,15 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) { QScriptValue anchorPositionBinding = properties.property("anchorPositionBinding"); if (anchorPositionBinding.isValid()) { _anchorPositionBindMyAvatar = false; + _anchorPositionBindEntity = QUuid(); QScriptValue avatar = anchorPositionBinding.property("avatar"); + QScriptValue entity = anchorPositionBinding.property("entity"); if (avatar.isValid()) { _anchorPositionBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); + } else if (entity.isValid() && !entity.isNull()) { + _anchorPositionBindEntity = entity.toVariant().toUuid(); } } @@ -140,11 +159,15 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) { QScriptValue offsetRotationBinding = properties.property("offsetRotationBinding"); if (offsetRotationBinding.isValid()) { _offsetRotationBindMyAvatar = false; + _offsetRotationBindEntity = QUuid(); QScriptValue avatar = offsetRotationBinding.property("avatar"); + QScriptValue entity = anchorPositionBinding.property("entity"); if (avatar.isValid()) { _offsetRotationBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); + } else if (entity.isValid() && !entity.isNull()) { + _offsetRotationBindEntity = entity.toVariant().toUuid(); } } diff --git a/interface/src/ui/overlays/FloatingUIPanel.h b/interface/src/ui/overlays/FloatingUIPanel.h index a45f57fe4d..fcde560570 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.h +++ b/interface/src/ui/overlays/FloatingUIPanel.h @@ -17,6 +17,7 @@ #include #include #include +#include class FloatingUIPanel : public QObject { Q_OBJECT @@ -59,7 +60,10 @@ private: glm::quat _facingRotation = {1, 0, 0, 0}; bool _anchorPositionBindMyAvatar = false; + QUuid _anchorPositionBindEntity; + bool _offsetRotationBindMyAvatar = false; + QUuid _offsetRotationBindEntity; Pointer _attachedPanel = nullptr; QScriptEngine* _scriptEngine; From 021dff63b43f7be682bffcf90a5f41ee3b754f07 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 5 Aug 2015 16:57:03 -0700 Subject: [PATCH 16/42] Visibility now cascades down panel children. For an overlay to render, it, and all of its ancestor panels, must be set visible. --- examples/example/ui/floatingUIExample.js | 3 +- examples/libraries/overlayManager.js | 31 ++++++------------- interface/src/ui/overlays/FloatingUIPanel.cpp | 16 ++++++++++ interface/src/ui/overlays/FloatingUIPanel.h | 7 ++++- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/PanelAttachable.cpp | 8 +++++ interface/src/ui/overlays/PanelAttachable.h | 1 + interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- 8 files changed, 45 insertions(+), 25 deletions(-) diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/floatingUIExample.js index 8eaeeff98b..f9baf78eea 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/floatingUIExample.js @@ -19,7 +19,7 @@ var RED_DOT_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/red-dot.svg"; var BLUE_SQUARE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/blue-square.svg"; var mainPanel = new FloatingUIPanel({ - anchorPositionBinding: null,//{ avatar: "MyAvatar" }, + anchorPositionBinding: { avatar: "MyAvatar" }, offsetRotation: { w: 1, x: 0, y: 0, z: 0 }, offsetPosition: { x: 0, y: 0.4, z: 1 }, facingRotation: { w: 0, x: 0, y: 1, z: 0 } @@ -153,6 +153,7 @@ blueSquare3.offsetPosition = { z: 0 }; +mainPanel.setChildrenVisible(); var mouseDown = {}; diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index 147df87831..b7c5940929 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -393,7 +393,7 @@ [ "anchorPosition", "anchorPositionBinding", "offsetRotation", "offsetRotationBinding", - "offsetPosition", "facingRotation" + "offsetPosition", "facingRotation", "visible" ].forEach(function(prop) { Object.defineProperty(that.prototype, prop, { get: function() { @@ -408,21 +408,6 @@ }); }); - var PSEUDO_FIELDS = []; - - PSEUDO_FIELDS.push("visible"); - Object.defineProperty(that.prototype, "visible", { - get: function() { - return this._visible; - }, - set: function(visible) { - this._visible = visible; - this._children.forEach(function(child) { - child.visible = visible; - }); - } - }); - Object.defineProperty(that.prototype, "attachedPanel", { get: function() { return findPanel(Overlays.getAttachedPanel(this._id)); @@ -456,14 +441,18 @@ }; that.prototype.setProperties = function(properties) { - for (var i in PSEUDO_FIELDS) { - if (properties[PSEUDO_FIELDS[i]] !== undefined) { - this[PSEUDO_FIELDS[i]] = properties[PSEUDO_FIELDS[i]]; - } - } Overlays.editPanel(this._id, properties); }; + that.prototype.setChildrenVisible = function() { + this._children.forEach(function(child) { + child.visible = true; + if (child.setChildrenVisible !== undefined) { + child.setChildrenVisible(); + } + }); + }; + that.prototype.destroy = function() { Overlays.deletePanel(this._id); }; diff --git a/interface/src/ui/overlays/FloatingUIPanel.cpp b/interface/src/ui/overlays/FloatingUIPanel.cpp index 2fc33bd9ad..a44f26fcc3 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.cpp +++ b/interface/src/ui/overlays/FloatingUIPanel.cpp @@ -56,6 +56,14 @@ glm::quat FloatingUIPanel::getRotation() const { return getComputedOffsetRotation() * getFacingRotation(); } +bool FloatingUIPanel::getParentVisible() const { + if (getAttachedPanel()) { + return getAttachedPanel()->getVisible() && getAttachedPanel()->getParentVisible(); + } else { + return true; + } +} + void FloatingUIPanel::addChild(unsigned int childId) { if (!_children.contains(childId)) { _children.append(childId); @@ -105,6 +113,9 @@ QScriptValue FloatingUIPanel::getProperty(const QString &property) { if (property == "facingRotation") { return quatToScriptValue(_scriptEngine, getFacingRotation()); } + if (property == "visible") { + return getVisible(); + } return QScriptValue(); } @@ -201,4 +212,9 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) { setFacingRotation(newRotation); } } + + QScriptValue visible = properties.property("visible"); + if (visible.isValid()) { + setVisible(visible.toVariant().toBool()); + } } diff --git a/interface/src/ui/overlays/FloatingUIPanel.h b/interface/src/ui/overlays/FloatingUIPanel.h index fcde560570..1a50848f05 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.h +++ b/interface/src/ui/overlays/FloatingUIPanel.h @@ -37,6 +37,8 @@ public: glm::vec3 getPosition() const; glm::quat getRotation() const; Pointer getAttachedPanel() const { return _attachedPanel; } + bool getVisible() const { return _visible; } + bool getParentVisible() const; // setters void setAnchorPosition(const glm::vec3& position) { _anchorPosition = position; } @@ -44,6 +46,7 @@ public: void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; } void setAttachedPanel(Pointer panel) { _attachedPanel = panel; } + void setVisible(bool visible) { _visible = visible; } const QList& getChildren() { return _children; } void addChild(unsigned int childId); @@ -66,8 +69,10 @@ private: QUuid _offsetRotationBindEntity; Pointer _attachedPanel = nullptr; - QScriptEngine* _scriptEngine; QList _children; + bool _visible = false; + + QScriptEngine* _scriptEngine; }; #endif // hifi_FloatingUIPanel_h diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 98e6d31486..349eff9ab9 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -47,7 +47,7 @@ void Image3DOverlay::render(RenderArgs* args) { _texture = DependencyManager::get()->getTexture(_url); } - if (!_visible || !_texture || !_texture->isLoaded()) { + if (!_visible || !getParentVisible() || !_texture || !_texture->isLoaded()) { return; } diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index fa029f12c9..1fb10253b2 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -27,6 +27,14 @@ PanelAttachable::PanelAttachable(const PanelAttachable* panelAttachable) : { } +bool PanelAttachable::getParentVisible() const { + if (getAttachedPanel()) { + return getAttachedPanel()->getVisible() && getAttachedPanel()->getParentVisible(); + } else { + return true; + } +} + void PanelAttachable::setTransforms(Transform& transform) { if (getAttachedPanel()) { transform.setTranslation(getAttachedPanel()->getComputedAnchorPosition()); diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index f22d4cc698..0b1c1a8f14 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -25,6 +25,7 @@ public: FloatingUIPanel::Pointer getAttachedPanel() const { return _attachedPanel; } virtual glm::vec3 getOffsetPosition() const { return _offsetPosition; } virtual glm::quat getFacingRotation() const { return _facingRotation; } + bool getParentVisible() const; void setAttachedPanel(FloatingUIPanel::Pointer panel) { _attachedPanel = panel; } virtual void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 030043b18c..aaa68f06c3 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -79,7 +79,7 @@ void Text3DOverlay::update(float deltatime) { } void Text3DOverlay::render(RenderArgs* args) { - if (!_visible) { + if (!_visible || !getParentVisible()) { return; // do nothing if we're not visible } From 6165e7e6caca031480fa6f7ce37c8db0f09fdc29 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 11:40:49 -0700 Subject: [PATCH 17/42] Improve cross-thread support for panel children. --- examples/example/ui/floatingUIExample.js | 4 ++ examples/libraries/overlayManager.js | 49 +++++++------------ interface/src/ui/overlays/FloatingUIPanel.cpp | 7 +++ interface/src/ui/overlays/FloatingUIPanel.h | 2 +- interface/src/ui/overlays/Overlays.cpp | 10 ++-- 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/floatingUIExample.js index f9baf78eea..7acb081eb5 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/floatingUIExample.js @@ -186,6 +186,10 @@ function onScriptEnd() { mainPanel.destroy(); } +print(JSON.stringify(mainPanel.children)); +print(JSON.stringify(bluePanel.children)); +print(bluePanel._id); + Controller.mousePressEvent.connect(onMouseDown); Controller.mouseReleaseEvent.connect(onMouseUp); Script.scriptEnding.connect(onScriptEnd); diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index b7c5940929..6a993807ad 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -60,10 +60,6 @@ } var overlay = new overlayTypes[type](); overlay._id = id; - var attachedPanel = findPanel(Overlays.getAttachedPanel(id)) - if (attachedPanel) { - attachedPanel.addChild(overlay); - } overlays[id] = overlay; return overlay; } @@ -101,10 +97,6 @@ } var panel = new FloatingUIPanel(); panel._id = id; - var attachedPanel = findPanel(Overlays.getAttachedPanel(id)) - if (attachedPanel) { - attachedPanel.addChild(panel); - } overlays[id] = overlay; return overlay; } @@ -133,6 +125,11 @@ return null; } + function findOverlayOrPanel(id, knownObjectsOnly, searchList) { + return findOverlay(id, knownObjectsOnly, searchList) || + findPanel(id, knownObjectsOnly, searchList); + } + // // Perform global scoped operations on overlays, such as finding by ray intersection. @@ -154,10 +151,10 @@ return OverlayManager.findOnRay(pickRay, knownOverlaysOnly, searchList); } }, - makeSearchList: function(overlayArray) { + makeSearchList: function(array) { var searchList = {}; - overlayArray.forEach(function(overlay){ - searchList[overlay._id] = overlay; + array.forEach(function(object) { + searchList[object._id] = object; }); return searchList; } @@ -280,7 +277,7 @@ }; that.prototype.isPanelAttachable = function() { - return true; + return false; }; return generateOverlayClass(that, ABSTRACT, [ @@ -380,17 +377,11 @@ FloatingUIPanel = (function() { var that = function(params) { this._id = Overlays.addPanel(params); - this._children = []; - this._visible = Boolean(params.visible); panels[this._id] = this; }; that.prototype.constructor = that; - that.AddChildException = function(message) { - this.message = message; - }; - [ "anchorPosition", "anchorPositionBinding", "offsetRotation", "offsetRotationBinding", "offsetPosition", "facingRotation", "visible" @@ -416,27 +407,23 @@ Object.defineProperty(that.prototype, "children", { get: function() { - return this._children.slice(); + var idArray = Overlays.getPanelProperty(this._id, "children"); + var objArray = []; + for (var i = 0; i < idArray.length; i++) { + objArray[i] = findOverlayOrPanel(idArray[i]); + } + return objArray; } }); that.prototype.addChild = function(child) { - if (child instanceof Overlay && child.isPanelAttachable() || - child instanceof FloatingUIPanel) { - Overlays.setAttachedPanel(child._id, this._id); - } else { - throw new that.AddChildException("Given child is not panel attachable."); - } - child.visible = this.visible; - this._children.push(child); + Overlays.setAttachedPanel(child._id, this._id); return child; }; that.prototype.removeChild = function(child) { - var i = this._children.indexOf(child); - if (i >= 0) { + if (child.attachedPanel === this) { Overlays.setAttachedPanel(child._id, 0); - this._children.splice(i, 1); } }; @@ -445,7 +432,7 @@ }; that.prototype.setChildrenVisible = function() { - this._children.forEach(function(child) { + this.children.forEach(function(child) { child.visible = true; if (child.setChildrenVisible !== undefined) { child.setChildrenVisible(); diff --git a/interface/src/ui/overlays/FloatingUIPanel.cpp b/interface/src/ui/overlays/FloatingUIPanel.cpp index a44f26fcc3..eae0a978e0 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.cpp +++ b/interface/src/ui/overlays/FloatingUIPanel.cpp @@ -116,6 +116,13 @@ QScriptValue FloatingUIPanel::getProperty(const QString &property) { if (property == "visible") { return getVisible(); } + if (property == "children") { + QScriptValue array = _scriptEngine->newArray(_children.length()); + for (int i = 0; i < _children.length(); i++) { + array.setProperty(i, _children[i]); + } + return array; + } return QScriptValue(); } diff --git a/interface/src/ui/overlays/FloatingUIPanel.h b/interface/src/ui/overlays/FloatingUIPanel.h index 1a50848f05..2c071b4351 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.h +++ b/interface/src/ui/overlays/FloatingUIPanel.h @@ -70,7 +70,7 @@ private: Pointer _attachedPanel = nullptr; QList _children; - bool _visible = false; + bool _visible = true; QScriptEngine* _scriptEngine; }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index a715001040..17aa99207d 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -202,7 +202,12 @@ unsigned int Overlays::cloneOverlay(unsigned int id) { Overlay::Pointer thisOverlay = getOverlay(id); if (thisOverlay) { - return addOverlay(Overlay::Pointer(thisOverlay->createClone())); + unsigned int cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone())); + auto attachable = std::dynamic_pointer_cast(thisOverlay); + if (attachable && attachable->getAttachedPanel()) { + attachable->getAttachedPanel()->addChild(cloneId); + } + return cloneId; } return 0; // Not found @@ -284,8 +289,7 @@ unsigned int Overlays::getAttachedPanel(unsigned int childId) const { } void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) { - Overlay::Pointer overlay = getOverlay(childId); - auto attachable = std::dynamic_pointer_cast(overlay); + auto attachable = std::dynamic_pointer_cast(getOverlay(childId)); if (attachable) { if (_panels.contains(panelId)) { auto panel = getPanel(panelId); From b94be926f8423ddc0591ce94a88569dd4412d2f1 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 14:23:04 -0700 Subject: [PATCH 18/42] Mass renaming to be more logical/concise. FloatingUIPanel -> OverlayPanel anchorPosition -> position offsetRotation -> rotation facingRotation -> offsetRotation floatingUIExample.js -> overlayPanelExample.js --- examples/controlPanel.js | 10 +- ...ingUIExample.js => overlayPanelExample.js} | 12 +- examples/libraries/overlayManager.js | 10 +- .../{FloatingUIPanel.cpp => OverlayPanel.cpp} | 157 +++++++++--------- .../{FloatingUIPanel.h => OverlayPanel.h} | 44 +++-- interface/src/ui/overlays/Overlays.cpp | 10 +- interface/src/ui/overlays/Overlays.h | 10 +- interface/src/ui/overlays/PanelAttachable.cpp | 22 +-- interface/src/ui/overlays/PanelAttachable.h | 14 +- 9 files changed, 139 insertions(+), 150 deletions(-) rename examples/example/ui/{floatingUIExample.js => overlayPanelExample.js} (94%) rename interface/src/ui/overlays/{FloatingUIPanel.cpp => OverlayPanel.cpp} (52%) rename interface/src/ui/overlays/{FloatingUIPanel.h => OverlayPanel.h} (59%) diff --git a/examples/controlPanel.js b/examples/controlPanel.js index 3ff054f3c8..be742054a7 100644 --- a/examples/controlPanel.js +++ b/examples/controlPanel.js @@ -5,7 +5,7 @@ // Created by Zander Otavka on 7/15/15. // Copyright 2015 High Fidelity, Inc. // -// Shows a few common controls in a FloatingUIPanel on right click. +// Shows a few common controls in a OverlayPanel on right click. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -22,10 +22,10 @@ var MIC_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/mic-toggle.svg"; var FACE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/face-toggle.svg"; var ADDRESS_BAR_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/address-bar-toggle.svg"; -var panel = new FloatingUIPanel({ - anchorPositionBinding: { avatar: "MyAvatar" }, +var panel = new OverlayPanel({ + positionBinding: { avatar: "MyAvatar" }, offsetPosition: { x: 0, y: 0.4, z: 1 }, - facingRotation: { w: 0, x: 0, y: 1, z: 0 } + offsetRotation: { w: 0, x: 0, y: 1, z: 0 } }); var background = new Image3DOverlay({ @@ -192,7 +192,7 @@ function onMouseUp(event) { if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 10) { panel.setProperties({ visible: !panel.visible, - offsetRotation: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 }) + rotation: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 }) }); } diff --git a/examples/example/ui/floatingUIExample.js b/examples/example/ui/overlayPanelExample.js similarity index 94% rename from examples/example/ui/floatingUIExample.js rename to examples/example/ui/overlayPanelExample.js index 7acb081eb5..c14b0764a5 100644 --- a/examples/example/ui/floatingUIExample.js +++ b/examples/example/ui/overlayPanelExample.js @@ -1,5 +1,5 @@ // -// floatingUI.js +// overlayPanelExample.js // examples/example/ui // // Created by Alexander Otavka @@ -18,14 +18,14 @@ var BG_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/card-bg.svg"; var RED_DOT_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/red-dot.svg"; var BLUE_SQUARE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/blue-square.svg"; -var mainPanel = new FloatingUIPanel({ - anchorPositionBinding: { avatar: "MyAvatar" }, - offsetRotation: { w: 1, x: 0, y: 0, z: 0 }, +var mainPanel = new OverlayPanel({ + positionBinding: { avatar: "MyAvatar" }, + rotation: { w: 1, x: 0, y: 0, z: 0 }, offsetPosition: { x: 0, y: 0.4, z: 1 }, - facingRotation: { w: 0, x: 0, y: 1, z: 0 } + offsetRotation: { w: 0, x: 0, y: 1, z: 0 } }); -var bluePanel = mainPanel.addChild(new FloatingUIPanel ({ +var bluePanel = mainPanel.addChild(new OverlayPanel ({ offsetPosition: { x: 0.1, y: 0.1, z: 0.2 } })); diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index 6a993807ad..0655b53c70 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -95,7 +95,7 @@ if (!Overlays.isAddedPanel(id)) { return null; } - var panel = new FloatingUIPanel(); + var panel = new OverlayPanel(); panel._id = id; overlays[id] = overlay; return overlay; @@ -234,7 +234,7 @@ // Supports multiple inheritance of properties. Just `concat` them onto the end of the // properties list. - var PANEL_ATTACHABLE_FIELDS = ["offsetPosition", "facingRotation"]; + var PANEL_ATTACHABLE_FIELDS = ["offsetPosition", "offsetRotation"]; Overlay = (function() { var that = function(type, params) { @@ -374,7 +374,7 @@ // // Object oriented abstraction layer for panels. // - FloatingUIPanel = (function() { + OverlayPanel = (function() { var that = function(params) { this._id = Overlays.addPanel(params); panels[this._id] = this; @@ -383,8 +383,8 @@ that.prototype.constructor = that; [ - "anchorPosition", "anchorPositionBinding", "offsetRotation", "offsetRotationBinding", - "offsetPosition", "facingRotation", "visible" + "position", "positionBinding", "rotation", "rotationBinding", + "offsetPosition", "offsetRotation", "visible" ].forEach(function(prop) { Object.defineProperty(that.prototype, prop, { get: function() { diff --git a/interface/src/ui/overlays/FloatingUIPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp similarity index 52% rename from interface/src/ui/overlays/FloatingUIPanel.cpp rename to interface/src/ui/overlays/OverlayPanel.cpp index eae0a978e0..8c9711bf74 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -1,5 +1,5 @@ // -// FloatingUIPanel.cpp +// OverlayPanel.cpp // interface/src/ui/overlays // // Created by Zander Otavka on 7/2/15. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "FloatingUIPanel.h" +#include "OverlayPanel.h" #include #include @@ -21,42 +21,33 @@ #include "Application.h" #include "Base3DOverlay.h" -glm::vec3 FloatingUIPanel::getComputedAnchorPosition() const { - glm::vec3 pos = {}; +glm::vec3 OverlayPanel::getComputedPosition() const { if (getAttachedPanel()) { - pos = getAttachedPanel()->getPosition(); - } else if (_anchorPositionBindMyAvatar) { - pos = DependencyManager::get()->getMyAvatar()->getPosition(); - } else if (!_anchorPositionBindEntity.isNull()) { - pos = DependencyManager::get()->getEntityTree()-> - findEntityByID(_anchorPositionBindEntity)->getPosition(); + return getAttachedPanel()->getComputedRotation() * getAttachedPanel()->getOffsetPosition() + + getAttachedPanel()->getComputedPosition(); + } else if (_positionBindMyAvatar) { + return DependencyManager::get()->getMyAvatar()->getPosition(); + } else if (!_positionBindEntity.isNull()) { + return DependencyManager::get()->getEntityTree()-> + findEntityByID(_positionBindEntity)->getPosition(); } - return pos + getAnchorPosition(); + return getPosition(); } -glm::quat FloatingUIPanel::getComputedOffsetRotation() const { - glm::quat rot = {1, 0, 0, 0}; +glm::quat OverlayPanel::getComputedRotation() const { if (getAttachedPanel()) { - rot = getAttachedPanel()->getRotation(); - } else if (_offsetRotationBindMyAvatar) { - rot = DependencyManager::get()->getMyAvatar()->getOrientation() * + return getAttachedPanel()->getComputedRotation() * getAttachedPanel()->getFacingRotation(); + } else if (_rotationBindMyAvatar) { + return DependencyManager::get()->getMyAvatar()->getOrientation() * glm::angleAxis(glm::pi(), IDENTITY_UP); - } else if (!_offsetRotationBindEntity.isNull()) { - rot = DependencyManager::get()->getEntityTree()-> - findEntityByID(_offsetRotationBindEntity)->getRotation(); + } else if (!_rotationBindEntity.isNull()) { + return DependencyManager::get()->getEntityTree()-> + findEntityByID(_rotationBindEntity)->getRotation(); } - return rot * getOffsetRotation(); + return getRotation(); } -glm::vec3 FloatingUIPanel::getPosition() const { - return getComputedOffsetRotation() * getOffsetPosition() + getComputedAnchorPosition(); -} - -glm::quat FloatingUIPanel::getRotation() const { - return getComputedOffsetRotation() * getFacingRotation(); -} - -bool FloatingUIPanel::getParentVisible() const { +bool OverlayPanel::getParentVisible() const { if (getAttachedPanel()) { return getAttachedPanel()->getVisible() && getAttachedPanel()->getParentVisible(); } else { @@ -64,53 +55,53 @@ bool FloatingUIPanel::getParentVisible() const { } } -void FloatingUIPanel::addChild(unsigned int childId) { +void OverlayPanel::addChild(unsigned int childId) { if (!_children.contains(childId)) { _children.append(childId); } } -void FloatingUIPanel::removeChild(unsigned int childId) { +void OverlayPanel::removeChild(unsigned int childId) { if (_children.contains(childId)) { _children.removeOne(childId); } } -QScriptValue FloatingUIPanel::getProperty(const QString &property) { - if (property == "anchorPosition") { - return vec3toScriptValue(_scriptEngine, getAnchorPosition()); +QScriptValue OverlayPanel::getProperty(const QString &property) { + if (property == "position") { + return vec3toScriptValue(_scriptEngine, getPosition()); } - if (property == "anchorPositionBinding") { + if (property == "positionBinding") { QScriptValue obj = _scriptEngine->newObject(); - if (_anchorPositionBindMyAvatar) { + if (_positionBindMyAvatar) { obj.setProperty("avatar", "MyAvatar"); - } else if (!_anchorPositionBindEntity.isNull()) { - obj.setProperty("entity", _scriptEngine->newVariant(_anchorPositionBindEntity)); + } else if (!_positionBindEntity.isNull()) { + obj.setProperty("entity", _scriptEngine->newVariant(_positionBindEntity)); } - obj.setProperty("computed", vec3toScriptValue(_scriptEngine, getComputedAnchorPosition())); + obj.setProperty("computed", vec3toScriptValue(_scriptEngine, getComputedPosition())); return obj; } - if (property == "offsetRotation") { - return quatToScriptValue(_scriptEngine, getOffsetRotation()); + if (property == "rotation") { + return quatToScriptValue(_scriptEngine, getRotation()); } - if (property == "offsetRotationBinding") { + if (property == "rotationBinding") { QScriptValue obj = _scriptEngine->newObject(); - if (_offsetRotationBindMyAvatar) { + if (_rotationBindMyAvatar) { obj.setProperty("avatar", "MyAvatar"); - } else if (!_offsetRotationBindEntity.isNull()) { - obj.setProperty("entity", _scriptEngine->newVariant(_offsetRotationBindEntity)); + } else if (!_rotationBindEntity.isNull()) { + obj.setProperty("entity", _scriptEngine->newVariant(_rotationBindEntity)); } - obj.setProperty("computed", quatToScriptValue(_scriptEngine, getComputedOffsetRotation())); + obj.setProperty("computed", quatToScriptValue(_scriptEngine, getComputedRotation())); return obj; } if (property == "offsetPosition") { return vec3toScriptValue(_scriptEngine, getOffsetPosition()); } - if (property == "facingRotation") { + if (property == "offsetRotation") { return quatToScriptValue(_scriptEngine, getFacingRotation()); } if (property == "visible") { @@ -127,42 +118,42 @@ QScriptValue FloatingUIPanel::getProperty(const QString &property) { return QScriptValue(); } -void FloatingUIPanel::setProperties(const QScriptValue &properties) { - QScriptValue anchorPosition = properties.property("anchorPosition"); - if (anchorPosition.isValid()) { - QScriptValue x = anchorPosition.property("x"); - QScriptValue y = anchorPosition.property("y"); - QScriptValue z = anchorPosition.property("z"); +void OverlayPanel::setProperties(const QScriptValue &properties) { + QScriptValue position = properties.property("position"); + if (position.isValid()) { + QScriptValue x = position.property("x"); + QScriptValue y = position.property("y"); + QScriptValue z = position.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(); - setAnchorPosition(newPosition); + setPosition(newPosition); } } - QScriptValue anchorPositionBinding = properties.property("anchorPositionBinding"); - if (anchorPositionBinding.isValid()) { - _anchorPositionBindMyAvatar = false; - _anchorPositionBindEntity = QUuid(); + QScriptValue positionBinding = properties.property("positionBinding"); + if (positionBinding.isValid()) { + _positionBindMyAvatar = false; + _positionBindEntity = QUuid(); - QScriptValue avatar = anchorPositionBinding.property("avatar"); - QScriptValue entity = anchorPositionBinding.property("entity"); + QScriptValue avatar = positionBinding.property("avatar"); + QScriptValue entity = positionBinding.property("entity"); if (avatar.isValid()) { - _anchorPositionBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); + _positionBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); } else if (entity.isValid() && !entity.isNull()) { - _anchorPositionBindEntity = entity.toVariant().toUuid(); + _positionBindEntity = entity.toVariant().toUuid(); } } - 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"); + QScriptValue rotation = properties.property("rotation"); + if (rotation.isValid()) { + QScriptValue x = rotation.property("x"); + QScriptValue y = rotation.property("y"); + QScriptValue z = rotation.property("z"); + QScriptValue w = rotation.property("w"); if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { glm::quat newRotation; @@ -170,22 +161,22 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) { newRotation.y = y.toVariant().toFloat(); newRotation.z = z.toVariant().toFloat(); newRotation.w = w.toVariant().toFloat(); - setOffsetRotation(newRotation); + setRotation(newRotation); } } - QScriptValue offsetRotationBinding = properties.property("offsetRotationBinding"); - if (offsetRotationBinding.isValid()) { - _offsetRotationBindMyAvatar = false; - _offsetRotationBindEntity = QUuid(); + QScriptValue rotationBinding = properties.property("rotationBinding"); + if (rotationBinding.isValid()) { + _rotationBindMyAvatar = false; + _rotationBindEntity = QUuid(); - QScriptValue avatar = offsetRotationBinding.property("avatar"); - QScriptValue entity = anchorPositionBinding.property("entity"); + QScriptValue avatar = rotationBinding.property("avatar"); + QScriptValue entity = positionBinding.property("entity"); if (avatar.isValid()) { - _offsetRotationBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); + _rotationBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); } else if (entity.isValid() && !entity.isNull()) { - _offsetRotationBindEntity = entity.toVariant().toUuid(); + _rotationBindEntity = entity.toVariant().toUuid(); } } @@ -203,12 +194,12 @@ void FloatingUIPanel::setProperties(const QScriptValue &properties) { } } - QScriptValue facingRotation = properties.property("facingRotation"); - if (facingRotation.isValid()) { - QScriptValue x = facingRotation.property("x"); - QScriptValue y = facingRotation.property("y"); - QScriptValue z = facingRotation.property("z"); - QScriptValue w = facingRotation.property("w"); + 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 (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { glm::quat newRotation; diff --git a/interface/src/ui/overlays/FloatingUIPanel.h b/interface/src/ui/overlays/OverlayPanel.h similarity index 59% rename from interface/src/ui/overlays/FloatingUIPanel.h rename to interface/src/ui/overlays/OverlayPanel.h index 2c071b4351..181208e50a 100644 --- a/interface/src/ui/overlays/FloatingUIPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -1,5 +1,5 @@ // -// FloatingUIPanel.h +// OverlayPanel.h // interface/src/ui/overlays // // Created by Zander Otavka on 7/2/15. @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_FloatingUIPanel_h -#define hifi_FloatingUIPanel_h +#ifndef hifi_OverlayPanel_h +#define hifi_OverlayPanel_h #include @@ -19,32 +19,30 @@ #include #include -class FloatingUIPanel : public QObject { +class OverlayPanel : public QObject { Q_OBJECT public: - typedef std::shared_ptr Pointer; + typedef std::shared_ptr Pointer; void init(QScriptEngine* scriptEngine) { _scriptEngine = scriptEngine; } // getters - glm::vec3 getAnchorPosition() const { return _anchorPosition; } - glm::vec3 getComputedAnchorPosition() const; - glm::quat getOffsetRotation() const { return _offsetRotation; } - glm::quat getComputedOffsetRotation() const; + glm::vec3 getPosition() const { return _position; } + glm::vec3 getComputedPosition() const; + glm::quat getRotation() const { return _rotation; } + glm::quat getComputedRotation() const; glm::vec3 getOffsetPosition() const { return _offsetPosition; } - glm::quat getFacingRotation() const { return _facingRotation; } - glm::vec3 getPosition() const; - glm::quat getRotation() const; + glm::quat getFacingRotation() const { return _offsetRotation; } Pointer getAttachedPanel() const { return _attachedPanel; } bool getVisible() const { return _visible; } bool getParentVisible() const; // setters - void setAnchorPosition(const glm::vec3& position) { _anchorPosition = position; } - void setOffsetRotation(const glm::quat& rotation) { _offsetRotation = rotation; } + void setPosition(const glm::vec3& position) { _position = position; } + void setRotation(const glm::quat& rotation) { _rotation = rotation; } void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } - void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; } + void setFacingRotation(const glm::quat& rotation) { _offsetRotation = rotation; } void setAttachedPanel(Pointer panel) { _attachedPanel = panel; } void setVisible(bool visible) { _visible = visible; } @@ -57,16 +55,16 @@ public: void setProperties(const QScriptValue& properties); private: - glm::vec3 _anchorPosition = {0, 0, 0}; - glm::quat _offsetRotation = {1, 0, 0, 0}; + glm::vec3 _position = {0, 0, 0}; + glm::quat _rotation = {1, 0, 0, 0}; glm::vec3 _offsetPosition = {0, 0, 0}; - glm::quat _facingRotation = {1, 0, 0, 0}; + glm::quat _offsetRotation = {1, 0, 0, 0}; - bool _anchorPositionBindMyAvatar = false; - QUuid _anchorPositionBindEntity; + bool _positionBindMyAvatar = false; + QUuid _positionBindEntity; - bool _offsetRotationBindMyAvatar = false; - QUuid _offsetRotationBindEntity; + bool _rotationBindMyAvatar = false; + QUuid _rotationBindEntity; Pointer _attachedPanel = nullptr; QList _children; @@ -75,4 +73,4 @@ private: QScriptEngine* _scriptEngine; }; -#endif // hifi_FloatingUIPanel_h +#endif // hifi_OverlayPanel_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 17aa99207d..73f061bfdd 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -303,7 +303,7 @@ void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) { } } } else if (_panels.contains(childId)) { - FloatingUIPanel::Pointer child = getPanel(childId); + OverlayPanel::Pointer child = getPanel(childId); if (_panels.contains(panelId)) { auto panel = getPanel(panelId); panel->addChild(childId); @@ -531,7 +531,7 @@ QSizeF Overlays::textSize(unsigned int id, const QString& text) const { return QSizeF(0.0f, 0.0f); } -unsigned int Overlays::addPanel(FloatingUIPanel::Pointer panel) { +unsigned int Overlays::addPanel(OverlayPanel::Pointer panel) { QWriteLocker lock(&_lock); unsigned int thisID = _nextOverlayID; @@ -542,7 +542,7 @@ unsigned int Overlays::addPanel(FloatingUIPanel::Pointer panel) { } unsigned int Overlays::addPanel(const QScriptValue& properties) { - FloatingUIPanel::Pointer panel = std::make_shared(); + OverlayPanel::Pointer panel = std::make_shared(); panel->init(_scriptEngine); panel->setProperties(properties); return addPanel(panel); @@ -557,7 +557,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 = getPanel(panelId); + OverlayPanel::Pointer thisPanel = getPanel(panelId); QReadLocker lock(&_lock); result.value = thisPanel->getProperty(property); } @@ -566,7 +566,7 @@ OverlayPropertyResult Overlays::getPanelProperty(unsigned int panelId, const QSt void Overlays::deletePanel(unsigned int panelId) { - FloatingUIPanel::Pointer panelToDelete; + OverlayPanel::Pointer panelToDelete; { QWriteLocker lock(&_lock); diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index a2850b3356..7ff3e2cd59 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -5,7 +5,7 @@ // Modified by Zander Otavka on 7/15/15 // Copyright 2014 High Fidelity, Inc. // -// Exposes methods for managing `Overlay`s and `FloatingUIPanel`s to scripts. +// Exposes methods for managing `Overlay`s and `OverlayPanel`s to scripts. // // YOU SHOULD NOT USE `Overlays` DIRECTLY, unless you like pain and deprecation. Instead, use the // object oriented abstraction layer found in `examples/libraries/overlayUtils.js`. @@ -22,7 +22,7 @@ #include "Overlay.h" -#include "FloatingUIPanel.h" +#include "OverlayPanel.h" #include "PanelAttachable.h" class PickRay; @@ -67,7 +67,7 @@ public: void renderHUD(RenderArgs* renderArgs); Overlay::Pointer getOverlay(unsigned int id) const; - FloatingUIPanel::Pointer getPanel(unsigned int id) const { return _panels[id]; } + OverlayPanel::Pointer getPanel(unsigned int id) const { return _panels[id]; } public slots: /// adds an overlay with the specific properties @@ -111,7 +111,7 @@ public slots: /// adds a panel that has already been created - unsigned int addPanel(FloatingUIPanel::Pointer panel); + unsigned int addPanel(OverlayPanel::Pointer panel); /// creates and adds a panel based on a set of properties unsigned int addPanel(const QScriptValue& properties); @@ -140,7 +140,7 @@ private: QMap _overlaysHUD; QMap _overlaysWorld; - QMap _panels; + QMap _panels; QList _overlaysToDelete; unsigned int _nextOverlayID; diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 1fb10253b2..6e2e58ece3 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -16,14 +16,14 @@ PanelAttachable::PanelAttachable() : _attachedPanel(nullptr), _offsetPosition(0, 0, 0), - _facingRotation(1, 0, 0, 0) + _offsetRotation(1, 0, 0, 0) { } PanelAttachable::PanelAttachable(const PanelAttachable* panelAttachable) : _attachedPanel(panelAttachable->_attachedPanel), _offsetPosition(panelAttachable->_offsetPosition), - _facingRotation(panelAttachable->_facingRotation) + _offsetRotation(panelAttachable->_offsetRotation) { } @@ -37,8 +37,8 @@ bool PanelAttachable::getParentVisible() const { void PanelAttachable::setTransforms(Transform& transform) { if (getAttachedPanel()) { - transform.setTranslation(getAttachedPanel()->getComputedAnchorPosition()); - transform.setRotation(getAttachedPanel()->getComputedOffsetRotation()); + transform.setTranslation(getAttachedPanel()->getComputedPosition()); + transform.setRotation(getAttachedPanel()->getComputedRotation()); transform.postTranslate(getAttachedPanel()->getOffsetPosition()); transform.postRotate(getAttachedPanel()->getFacingRotation()); transform.postTranslate(getOffsetPosition()); @@ -50,7 +50,7 @@ QScriptValue PanelAttachable::getProperty(QScriptEngine* scriptEngine, const QSt if (property == "offsetPosition") { return vec3toScriptValue(scriptEngine, getOffsetPosition()); } - if (property == "facingRotation") { + if (property == "offsetRotation") { return quatToScriptValue(scriptEngine, getFacingRotation()); } return QScriptValue(); @@ -72,12 +72,12 @@ void PanelAttachable::setProperties(const QScriptValue &properties) { } } - QScriptValue facingRotation = properties.property("facingRotation"); - if (facingRotation.isValid()) { - QScriptValue x = facingRotation.property("x"); - QScriptValue y = facingRotation.property("y"); - QScriptValue z = facingRotation.property("z"); - QScriptValue w = facingRotation.property("w"); + 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 (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { glm::quat newRotation; diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index 0b1c1a8f14..9446927136 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -12,7 +12,7 @@ #ifndef hifi_PanelAttachable_h #define hifi_PanelAttachable_h -#include "FloatingUIPanel.h" +#include "OverlayPanel.h" #include #include @@ -22,14 +22,14 @@ public: PanelAttachable(); PanelAttachable(const PanelAttachable* panelAttachable); - FloatingUIPanel::Pointer getAttachedPanel() const { return _attachedPanel; } + OverlayPanel::Pointer getAttachedPanel() const { return _attachedPanel; } virtual glm::vec3 getOffsetPosition() const { return _offsetPosition; } - virtual glm::quat getFacingRotation() const { return _facingRotation; } + virtual glm::quat getFacingRotation() const { return _offsetRotation; } bool getParentVisible() const; - void setAttachedPanel(FloatingUIPanel::Pointer panel) { _attachedPanel = panel; } + void setAttachedPanel(OverlayPanel::Pointer panel) { _attachedPanel = panel; } virtual void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } - virtual void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; } + virtual void setFacingRotation(const glm::quat& rotation) { _offsetRotation = rotation; } QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); void setProperties(const QScriptValue& properties); @@ -38,9 +38,9 @@ protected: virtual void setTransforms(Transform& transform); private: - FloatingUIPanel::Pointer _attachedPanel; + OverlayPanel::Pointer _attachedPanel; glm::vec3 _offsetPosition; - glm::quat _facingRotation; + glm::quat _offsetRotation; }; #endif // hifi_PanelAttachable_h From 497713b0209e7b06e215a58e905d859138a76b2b Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 15:45:07 -0700 Subject: [PATCH 19/42] Rename a few more confusing names. setTransforms -> applyTransformTo attachedPanel -> parentPanel --- examples/example/ui/overlayPanelExample.js | 2 +- examples/libraries/overlayManager.js | 22 +++++++------- .../src/ui/overlays/Billboard3DOverlay.cpp | 5 ++-- .../src/ui/overlays/Billboard3DOverlay.h | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 6 ++-- interface/src/ui/overlays/OverlayPanel.cpp | 14 ++++----- interface/src/ui/overlays/OverlayPanel.h | 6 ++-- interface/src/ui/overlays/Overlays.cpp | 30 +++++++++---------- interface/src/ui/overlays/Overlays.h | 4 +-- interface/src/ui/overlays/PanelAttachable.cpp | 20 ++++++------- interface/src/ui/overlays/PanelAttachable.h | 12 ++++---- interface/src/ui/overlays/Text3DOverlay.cpp | 6 ++-- 12 files changed, 65 insertions(+), 64 deletions(-) diff --git a/examples/example/ui/overlayPanelExample.js b/examples/example/ui/overlayPanelExample.js index c14b0764a5..d5dfc7286e 100644 --- a/examples/example/ui/overlayPanelExample.js +++ b/examples/example/ui/overlayPanelExample.js @@ -170,7 +170,7 @@ function onMouseUp(event) { if (event.isLeftButton) { var overlay = OverlayManager.findAtPoint({ x: event.x, y: event.y }); if (overlay && overlay === mouseDown.overlay) { - if (overlay.attachedPanel === bluePanel) { + if (overlay.parentPanel === bluePanel) { overlay.destroy(); } else { overlay.offsetPosition = Vec3.sum(overlay.offsetPosition, { x: 0, y: 0, z: -0.1 }); diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index 0655b53c70..3e409f5e0f 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -254,9 +254,9 @@ } }); - Object.defineProperty(that.prototype, "attachedPanel", { + Object.defineProperty(that.prototype, "parentPanel", { get: function() { - return findPanel(Overlays.getAttachedPanel(this._id)); + return findPanel(Overlays.getParentPanel(this._id)); } }); @@ -399,9 +399,9 @@ }); }); - Object.defineProperty(that.prototype, "attachedPanel", { + Object.defineProperty(that.prototype, "parentPanel", { get: function() { - return findPanel(Overlays.getAttachedPanel(this._id)); + return findPanel(Overlays.getParentPanel(this._id)); } }); @@ -417,13 +417,13 @@ }); that.prototype.addChild = function(child) { - Overlays.setAttachedPanel(child._id, this._id); + Overlays.setParentPanel(child._id, this._id); return child; }; that.prototype.removeChild = function(child) { - if (child.attachedPanel === this) { - Overlays.setAttachedPanel(child._id, 0); + if (child.parentPanel === this) { + Overlays.setParentPanel(child._id, 0); } }; @@ -450,8 +450,8 @@ function onOverlayDeleted(id) { if (id in overlays) { - if (overlays[id].attachedPanel) { - overlays[id].attachedPanel.removeChild(overlays[id]); + if (overlays[id].parentPanel) { + overlays[id].parentPanel.removeChild(overlays[id]); } delete overlays[id]; } @@ -459,8 +459,8 @@ function onPanelDeleted(id) { if (id in panels) { - if (panels[id].attachedPanel) { - panels[id].attachedPanel.removeChild(panels[id]); + if (panels[id].parentPanel) { + panels[id].parentPanel.removeChild(panels[id]); } delete panels[id]; } diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp index ffec368a53..04283664a8 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.cpp +++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp @@ -46,10 +46,11 @@ QScriptValue Billboard3DOverlay::getProperty(const QString &property) { return Planar3DOverlay::getProperty(property); } -void Billboard3DOverlay::setTransforms(Transform& transform) { - PanelAttachable::setTransforms(transform); +void Billboard3DOverlay::applyTransformTo(Transform& transform) { + PanelAttachable::applyTransformTo(transform); if (_isFacingAvatar) { glm::quat rotation = Application::getInstance()->getCamera()->getOrientation(); + transform.setRotation(rotation); } } diff --git a/interface/src/ui/overlays/Billboard3DOverlay.h b/interface/src/ui/overlays/Billboard3DOverlay.h index 1aa973539b..0a15718414 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 setTransforms(Transform& transform); + virtual void applyTransformTo(Transform& transform); private: bool _isFacingAvatar; diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 349eff9ab9..28d6208020 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -38,7 +38,7 @@ Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) : } void Image3DOverlay::update(float deltatime) { - setTransforms(_transform); + applyTransformTo(_transform); } void Image3DOverlay::render(RenderArgs* args) { @@ -87,7 +87,7 @@ void Image3DOverlay::render(RenderArgs* args) { xColor color = getColor(); float alpha = getAlpha(); - setTransforms(_transform); + applyTransformTo(_transform); 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. - setTransforms(_transform); + applyTransformTo(_transform); // 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 8c9711bf74..58d85241ff 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -22,9 +22,9 @@ #include "Base3DOverlay.h" glm::vec3 OverlayPanel::getComputedPosition() const { - if (getAttachedPanel()) { - return getAttachedPanel()->getComputedRotation() * getAttachedPanel()->getOffsetPosition() + - getAttachedPanel()->getComputedPosition(); + if (getParentPanel()) { + return getParentPanel()->getComputedRotation() * getParentPanel()->getOffsetPosition() + + getParentPanel()->getComputedPosition(); } else if (_positionBindMyAvatar) { return DependencyManager::get()->getMyAvatar()->getPosition(); } else if (!_positionBindEntity.isNull()) { @@ -35,8 +35,8 @@ glm::vec3 OverlayPanel::getComputedPosition() const { } glm::quat OverlayPanel::getComputedRotation() const { - if (getAttachedPanel()) { - return getAttachedPanel()->getComputedRotation() * getAttachedPanel()->getFacingRotation(); + if (getParentPanel()) { + return getParentPanel()->getComputedRotation() * getParentPanel()->getFacingRotation(); } else if (_rotationBindMyAvatar) { return DependencyManager::get()->getMyAvatar()->getOrientation() * glm::angleAxis(glm::pi(), IDENTITY_UP); @@ -48,8 +48,8 @@ glm::quat OverlayPanel::getComputedRotation() const { } bool OverlayPanel::getParentVisible() const { - if (getAttachedPanel()) { - return getAttachedPanel()->getVisible() && getAttachedPanel()->getParentVisible(); + if (getParentPanel()) { + return getParentPanel()->getVisible() && getParentPanel()->getParentVisible(); } else { return true; } diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index 181208e50a..af6ceb2731 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -34,7 +34,7 @@ public: glm::quat getComputedRotation() const; glm::vec3 getOffsetPosition() const { return _offsetPosition; } glm::quat getFacingRotation() const { return _offsetRotation; } - Pointer getAttachedPanel() const { return _attachedPanel; } + Pointer getParentPanel() const { return _parentPanel; } bool getVisible() const { return _visible; } bool getParentVisible() const; @@ -43,7 +43,7 @@ public: void setRotation(const glm::quat& rotation) { _rotation = rotation; } void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } void setFacingRotation(const glm::quat& rotation) { _offsetRotation = rotation; } - void setAttachedPanel(Pointer panel) { _attachedPanel = panel; } + void setParentPanel(Pointer panel) { _parentPanel = panel; } void setVisible(bool visible) { _visible = visible; } const QList& getChildren() { return _children; } @@ -66,7 +66,7 @@ private: bool _rotationBindMyAvatar = false; QUuid _rotationBindEntity; - Pointer _attachedPanel = nullptr; + Pointer _parentPanel = nullptr; QList _children; bool _visible = true; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 73f061bfdd..77a7f2a4aa 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -204,8 +204,8 @@ unsigned int Overlays::cloneOverlay(unsigned int id) { if (thisOverlay) { unsigned int cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone())); auto attachable = std::dynamic_pointer_cast(thisOverlay); - if (attachable && attachable->getAttachedPanel()) { - attachable->getAttachedPanel()->addChild(cloneId); + if (attachable && attachable->getParentPanel()) { + attachable->getParentPanel()->addChild(cloneId); } return cloneId; } @@ -258,9 +258,9 @@ void Overlays::deleteOverlay(unsigned int id) { } auto attachable = std::dynamic_pointer_cast(overlayToDelete); - if (attachable && attachable->getAttachedPanel()) { - attachable->getAttachedPanel()->removeChild(id); - attachable->setAttachedPanel(nullptr); + if (attachable && attachable->getParentPanel()) { + attachable->getParentPanel()->removeChild(id); + attachable->setParentPanel(nullptr); } QWriteLocker lock(&_deleteLock); @@ -277,29 +277,29 @@ QString Overlays::getOverlayType(unsigned int overlayId) const { return ""; } -unsigned int Overlays::getAttachedPanel(unsigned int childId) const { +unsigned int Overlays::getParentPanel(unsigned int childId) const { Overlay::Pointer overlay = getOverlay(childId); auto attachable = std::dynamic_pointer_cast(overlay); if (attachable) { - return _panels.key(attachable->getAttachedPanel()); + return _panels.key(attachable->getParentPanel()); } else if (_panels.contains(childId)) { - return _panels.key(getPanel(childId)->getAttachedPanel()); + return _panels.key(getPanel(childId)->getParentPanel()); } return 0; } -void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) { +void Overlays::setParentPanel(unsigned int childId, unsigned int panelId) { auto attachable = std::dynamic_pointer_cast(getOverlay(childId)); if (attachable) { if (_panels.contains(panelId)) { auto panel = getPanel(panelId); panel->addChild(childId); - attachable->setAttachedPanel(panel); + attachable->setParentPanel(panel); } else { - auto panel = attachable->getAttachedPanel(); + auto panel = attachable->getParentPanel(); if (panel) { panel->removeChild(childId); - attachable->setAttachedPanel(nullptr); + attachable->setParentPanel(nullptr); } } } else if (_panels.contains(childId)) { @@ -307,12 +307,12 @@ void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) { if (_panels.contains(panelId)) { auto panel = getPanel(panelId); panel->addChild(childId); - child->setAttachedPanel(panel); + child->setParentPanel(panel); } else { - auto panel = child->getAttachedPanel(); + auto panel = child->getParentPanel(); if (panel) { panel->removeChild(childId); - child->setAttachedPanel(0); + child->setParentPanel(0); } } } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 7ff3e2cd59..7afcf8a9b1 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -90,8 +90,8 @@ public slots: /// get the string type of the overlay used in addOverlay QString getOverlayType(unsigned int overlayId) const; - unsigned int getAttachedPanel(unsigned int childId) const; - void setAttachedPanel(unsigned int childId, unsigned int panelId); + unsigned int getParentPanel(unsigned int childId) const; + void setParentPanel(unsigned int childId, unsigned int panelId); /// returns the top most 2D overlay at the screen point, or 0 if not overlay at that point unsigned int getOverlayAtPoint(const glm::vec2& point); diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 6e2e58ece3..37b65041e5 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -14,33 +14,33 @@ #include PanelAttachable::PanelAttachable() : - _attachedPanel(nullptr), + _parentPanel(nullptr), _offsetPosition(0, 0, 0), _offsetRotation(1, 0, 0, 0) { } PanelAttachable::PanelAttachable(const PanelAttachable* panelAttachable) : - _attachedPanel(panelAttachable->_attachedPanel), + _parentPanel(panelAttachable->_parentPanel), _offsetPosition(panelAttachable->_offsetPosition), _offsetRotation(panelAttachable->_offsetRotation) { } bool PanelAttachable::getParentVisible() const { - if (getAttachedPanel()) { - return getAttachedPanel()->getVisible() && getAttachedPanel()->getParentVisible(); + if (getParentPanel()) { + return getParentPanel()->getVisible() && getParentPanel()->getParentVisible(); } else { return true; } } -void PanelAttachable::setTransforms(Transform& transform) { - if (getAttachedPanel()) { - transform.setTranslation(getAttachedPanel()->getComputedPosition()); - transform.setRotation(getAttachedPanel()->getComputedRotation()); - transform.postTranslate(getAttachedPanel()->getOffsetPosition()); - transform.postRotate(getAttachedPanel()->getFacingRotation()); +void PanelAttachable::applyTransformTo(Transform& transform) { + if (getParentPanel()) { + transform.setTranslation(getParentPanel()->getComputedPosition()); + transform.setRotation(getParentPanel()->getComputedRotation()); + transform.postTranslate(getParentPanel()->getOffsetPosition()); + transform.postRotate(getParentPanel()->getFacingRotation()); transform.postTranslate(getOffsetPosition()); transform.postRotate(getFacingRotation()); } diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index 9446927136..4cf9c768c5 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -22,12 +22,12 @@ public: PanelAttachable(); PanelAttachable(const PanelAttachable* panelAttachable); - OverlayPanel::Pointer getAttachedPanel() const { return _attachedPanel; } + OverlayPanel::Pointer getParentPanel() const { return _parentPanel; } virtual glm::vec3 getOffsetPosition() const { return _offsetPosition; } virtual glm::quat getFacingRotation() const { return _offsetRotation; } bool getParentVisible() const; - void setAttachedPanel(OverlayPanel::Pointer panel) { _attachedPanel = panel; } + void setParentPanel(OverlayPanel::Pointer panel) { _parentPanel = panel; } virtual void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } virtual void setFacingRotation(const glm::quat& rotation) { _offsetRotation = rotation; } @@ -35,12 +35,12 @@ public: void setProperties(const QScriptValue& properties); protected: - virtual void setTransforms(Transform& transform); + virtual void applyTransformTo(Transform& transform); private: - OverlayPanel::Pointer _attachedPanel; - glm::vec3 _offsetPosition; - glm::quat _offsetRotation; + OverlayPanel::Pointer _parentPanel;// = nullptr; + glm::vec3 _offsetPosition;// = {0, 0, 0}; + glm::quat _offsetRotation;// = {1, 0, 0, 0}; }; #endif // hifi_PanelAttachable_h diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index aaa68f06c3..5a60ad6029 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -75,7 +75,7 @@ xColor Text3DOverlay::getBackgroundColor() { } void Text3DOverlay::update(float deltatime) { - setTransforms(_transform); + applyTransformTo(_transform); } void Text3DOverlay::render(RenderArgs* args) { @@ -86,7 +86,7 @@ void Text3DOverlay::render(RenderArgs* args) { Q_ASSERT(args->_batch); auto& batch = *args->_batch; - setTransforms(_transform); + applyTransformTo(_transform); 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) { - setTransforms(_transform); + applyTransformTo(_transform); return Billboard3DOverlay::findRayIntersection(origin, direction, distance, face); } From 13a63a5a3d706f59deec05f94cbcd37be27d90ca Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 16:04:11 -0700 Subject: [PATCH 20/42] Improve mouse click logic in scripts. Also restore behavior of controlPanel.js being hidden on startup. --- examples/controlPanel.js | 33 +++++++++++++++++----- examples/example/ui/overlayPanelExample.js | 19 ++++++++----- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/examples/controlPanel.js b/examples/controlPanel.js index be742054a7..0472597692 100644 --- a/examples/controlPanel.js +++ b/examples/controlPanel.js @@ -25,7 +25,8 @@ var ADDRESS_BAR_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/address-bar-toggl var panel = new OverlayPanel({ positionBinding: { avatar: "MyAvatar" }, offsetPosition: { x: 0, y: 0.4, z: 1 }, - offsetRotation: { w: 0, x: 0, y: 1, z: 0 } + offsetRotation: { w: 0, x: 0, y: 1, z: 0 }, + visible: false }); var background = new Image3DOverlay({ @@ -36,7 +37,8 @@ var background = new Image3DOverlay({ }, isFacingAvatar: false, alpha: 1.0, - ignoreRayIntersection: false + ignoreRayIntersection: false, + visible: false }); panel.addChild(background); @@ -53,7 +55,8 @@ var closeButton = new Image3DOverlay({ x: 0.1, y: 0.1, z: 0.001 - } + }, + visible: false }); closeButton.onClick = function(event) { panel.visible = false; @@ -79,7 +82,8 @@ var micMuteButton = new Image3DOverlay({ x: -0.1, y: 0.1, z: 0.001 - } + }, + visible: false }); micMuteButton.onClick = function(event) { AudioDevice.toggleMute(); @@ -105,7 +109,8 @@ var faceMuteButton = new Image3DOverlay({ x: -0.1, y: -0.1, z: 0.001 - } + }, + visible: false }); faceMuteButton.onClick = function(event) { FaceTracker.toggleMute(); @@ -131,13 +136,16 @@ var addressBarButton = new Image3DOverlay({ x: 0.1, y: -0.1, z: 0.001 - } + }, + visible: false }); addressBarButton.onClick = function(event) { DialogsManager.toggleAddressBar(); }; panel.addChild(addressBarButton); +panel.setChildrenVisible(); + function onMicMuteToggled() { var offset; @@ -180,6 +188,16 @@ function onMouseDown(event) { if (event.isRightButton) { mouseDown.pos = { x: event.x, y: event.y }; } + mouseDown.maxDistance = 0; +} + +function onMouseMove(event) { + if (mouseDown.maxDistance !== undefined) { + var dist = Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }); + if (dist > mouseDown.maxDistance) { + mouseDown.maxDistance = dist; + } + } } function onMouseUp(event) { @@ -189,7 +207,7 @@ function onMouseUp(event) { overlay.onClick(event); } } - if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 10) { + if (event.isRightButton && mouseDown.maxDistance < 10) { panel.setProperties({ visible: !panel.visible, rotation: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 }) @@ -204,6 +222,7 @@ function onScriptEnd(event) { } Controller.mousePressEvent.connect(onMouseDown); +Controller.mouseMoveEvent.connect(onMouseMove); Controller.mouseReleaseEvent.connect(onMouseUp); AudioDevice.muteToggled.connect(onMicMuteToggled); FaceTracker.muteToggled.connect(onFaceMuteToggled); diff --git a/examples/example/ui/overlayPanelExample.js b/examples/example/ui/overlayPanelExample.js index d5dfc7286e..481db282fd 100644 --- a/examples/example/ui/overlayPanelExample.js +++ b/examples/example/ui/overlayPanelExample.js @@ -153,8 +153,6 @@ blueSquare3.offsetPosition = { z: 0 }; -mainPanel.setChildrenVisible(); - var mouseDown = {}; function onMouseDown(event) { @@ -164,6 +162,16 @@ function onMouseDown(event) { if (event.isRightButton) { mouseDown.pos = { x: event.x, y: event.y }; } + mouseDown.maxDistance = 0; +} + +function onMouseMove(event) { + if (mouseDown.maxDistance !== undefined) { + var dist = Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }); + if (dist > mouseDown.maxDistance) { + mouseDown.maxDistance = dist; + } + } } function onMouseUp(event) { @@ -177,7 +185,7 @@ function onMouseUp(event) { } } } - if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 10) { + if (event.isRightButton && mouseDown.maxDistance < 10) { mainPanel.visible = !mainPanel.visible; } } @@ -186,10 +194,7 @@ function onScriptEnd() { mainPanel.destroy(); } -print(JSON.stringify(mainPanel.children)); -print(JSON.stringify(bluePanel.children)); -print(bluePanel._id); - Controller.mousePressEvent.connect(onMouseDown); +Controller.mouseMoveEvent.connect(onMouseMove); Controller.mouseReleaseEvent.connect(onMouseUp); Script.scriptEnding.connect(onScriptEnd); From c7639537d03470d9cd0f3462e4b024891cad7ee1 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 16:13:21 -0700 Subject: [PATCH 21/42] Use implicit copy constructor for PanelAttachable. --- interface/src/ui/overlays/Billboard3DOverlay.cpp | 2 +- interface/src/ui/overlays/PanelAttachable.cpp | 14 -------------- interface/src/ui/overlays/PanelAttachable.h | 9 +++------ 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp index 04283664a8..7b195ad466 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.cpp +++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp @@ -19,7 +19,7 @@ Billboard3DOverlay::Billboard3DOverlay() : Billboard3DOverlay::Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay) : Planar3DOverlay(billboard3DOverlay), - PanelAttachable(billboard3DOverlay), + PanelAttachable(*billboard3DOverlay), _isFacingAvatar(billboard3DOverlay->_isFacingAvatar) { } diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 37b65041e5..6626107247 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -13,20 +13,6 @@ #include -PanelAttachable::PanelAttachable() : - _parentPanel(nullptr), - _offsetPosition(0, 0, 0), - _offsetRotation(1, 0, 0, 0) -{ -} - -PanelAttachable::PanelAttachable(const PanelAttachable* panelAttachable) : - _parentPanel(panelAttachable->_parentPanel), - _offsetPosition(panelAttachable->_offsetPosition), - _offsetRotation(panelAttachable->_offsetRotation) -{ -} - bool PanelAttachable::getParentVisible() const { if (getParentPanel()) { return getParentPanel()->getVisible() && getParentPanel()->getParentVisible(); diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index 4cf9c768c5..db2665e6eb 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -19,9 +19,6 @@ class PanelAttachable { public: - PanelAttachable(); - PanelAttachable(const PanelAttachable* panelAttachable); - OverlayPanel::Pointer getParentPanel() const { return _parentPanel; } virtual glm::vec3 getOffsetPosition() const { return _offsetPosition; } virtual glm::quat getFacingRotation() const { return _offsetRotation; } @@ -38,9 +35,9 @@ protected: virtual void applyTransformTo(Transform& transform); private: - OverlayPanel::Pointer _parentPanel;// = nullptr; - glm::vec3 _offsetPosition;// = {0, 0, 0}; - glm::quat _offsetRotation;// = {1, 0, 0, 0}; + OverlayPanel::Pointer _parentPanel = nullptr; + glm::vec3 _offsetPosition = {0, 0, 0}; + glm::quat _offsetRotation = {1, 0, 0, 0}; }; #endif // hifi_PanelAttachable_h From 42cc34cd64dae1e8d9edd129ae0d83f88c420e44 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 6 Aug 2015 16:54:09 -0700 Subject: [PATCH 22/42] JointState has our own copy of any ivars we want from FBXJoint, instead of keeping a reference to the fbx. --- interface/src/avatar/FaceModel.cpp | 22 +++--- interface/src/avatar/FaceModel.h | 4 +- interface/src/avatar/SkeletonModel.cpp | 13 ++-- libraries/animation/src/AvatarRig.cpp | 7 +- libraries/animation/src/EntityRig.cpp | 5 +- libraries/animation/src/JointState.cpp | 101 ++++++++++++++++--------- libraries/animation/src/JointState.h | 29 ++++++- libraries/animation/src/Rig.cpp | 32 ++++---- tests/animation/src/RigTests.cpp | 2 +- 9 files changed, 131 insertions(+), 84 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 066144a425..22ba7455b8 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -56,12 +56,12 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) { } } -void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, int index) { +void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const JointState& state, int index) { // get the rotation axes in joint space and use them to adjust the rotation glm::mat3 axes = glm::mat3_cast(glm::quat()); glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(_rig->getJointDefaultTranslationInConstrainedFrame(index)) * - joint.preTransform * glm::mat4_cast(joint.preRotation))); + state.getPreTransform() * glm::mat4_cast(state.getPreRotation()))); glm::vec3 pitchYawRoll = safeEulerAngles(_owningHead->getFinalOrientationInLocalFrame()); glm::vec3 lean = glm::radians(glm::vec3(_owningHead->getFinalLeanForward(), _owningHead->getTorsoTwist(), @@ -71,15 +71,15 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * axes[2])) * glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * axes[1])) * glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * axes[0])) - * joint.rotation, DEFAULT_PRIORITY); + * state.getOriginalRotation(), DEFAULT_PRIORITY); } -void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentState, const FBXJoint& joint, int index) { +void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentState, const JointState& state, int index) { // likewise with the eye joints // NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual. glm::mat4 inverse = glm::inverse(glm::mat4_cast(model->getRotation()) * parentState.getTransform() * glm::translate(_rig->getJointDefaultTranslationInConstrainedFrame(index)) * - joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); + state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getOriginalRotation())); glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f)); glm::vec3 lookAtDelta = _owningHead->getCorrectedLookAtPosition() - model->getTranslation(); glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * _owningHead->getSaccade(), 1.0f)); @@ -87,22 +87,22 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; _rig->setJointRotationInConstrainedFrame(index, glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) * - joint.rotation, DEFAULT_PRIORITY); + state.getOriginalRotation(), DEFAULT_PRIORITY); } void FaceModel::maybeUpdateNeckAndEyeRotation(int index) { const JointState& state = _rig->getJointState(index); - const FBXJoint& joint = state.getFBXJoint(); const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const int parentIndex = state.getParentIndex(); // guard against out-of-bounds access to _jointStates - if (joint.parentIndex != -1 && joint.parentIndex >= 0 && joint.parentIndex < _rig->getJointStateCount()) { - const JointState& parentState = _rig->getJointState(joint.parentIndex); + if (parentIndex != -1 && parentIndex >= 0 && parentIndex < _rig->getJointStateCount()) { + const JointState& parentState = _rig->getJointState(parentIndex); if (index == geometry.neckJointIndex) { - maybeUpdateNeckRotation(parentState, joint, index); + maybeUpdateNeckRotation(parentState, state, index); } else if (index == geometry.leftEyeJointIndex || index == geometry.rightEyeJointIndex) { - maybeUpdateEyeRotation(this, parentState, joint, index); + maybeUpdateEyeRotation(this, parentState, state, index); } } } diff --git a/interface/src/avatar/FaceModel.h b/interface/src/avatar/FaceModel.h index 54d685c73c..ed1ea28508 100644 --- a/interface/src/avatar/FaceModel.h +++ b/interface/src/avatar/FaceModel.h @@ -26,8 +26,8 @@ public: virtual void simulate(float deltaTime, bool fullUpdate = true); - void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, int index); - void maybeUpdateEyeRotation(Model* model, const JointState& parentState, const FBXJoint& joint, int index); + void maybeUpdateNeckRotation(const JointState& parentState, const JointState& state, int index); + void maybeUpdateEyeRotation(Model* model, const JointState& parentState, const JointState& state, int index); void maybeUpdateNeckAndEyeRotation(int index); /// Retrieve the positions of up to two eye meshes. diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index d5cb0517a7..8000ed8d26 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -401,7 +401,7 @@ bool SkeletonModel::getNeckParentRotationFromDefaultOrientation(glm::quat& neckP glm::quat worldFrameRotation; bool success = getJointRotationInWorldFrame(parentIndex, worldFrameRotation); if (success) { - neckParentRotation = worldFrameRotation * _rig->getJointState(parentIndex).getFBXJoint().inverseDefaultRotation; + neckParentRotation = worldFrameRotation * _rig->getJointState(parentIndex).getInverseDefaultRotation(); } return success; } @@ -477,18 +477,17 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) { for (int i = 0; i < numStates; i++) { // compute the default transform of this joint const JointState& state = _rig->getJointState(i); - const FBXJoint& joint = state.getFBXJoint(); - int parentIndex = joint.parentIndex; + int parentIndex = state.getParentIndex(); if (parentIndex == -1) { transforms[i] = _rig->getJointTransform(i); } else { - glm::quat modifiedRotation = joint.preRotation * joint.rotation * joint.postRotation; - transforms[i] = transforms[parentIndex] * glm::translate(joint.translation) - * joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform; + glm::quat modifiedRotation = state.getPreRotation() * state.getOriginalRotation() * state.getPostRotation(); + transforms[i] = transforms[parentIndex] * glm::translate(state.getTranslation()) + * state.getPreTransform() * glm::mat4_cast(modifiedRotation) * state.getPostTransform(); } // Each joint contributes a sphere at its position - glm::vec3 axis(joint.boneRadius); + glm::vec3 axis(state.getBoneRadius()); glm::vec3 jointPosition = extractTranslation(transforms[i]); totalExtents.addPoint(jointPosition + axis); totalExtents.addPoint(jointPosition - axis); diff --git a/libraries/animation/src/AvatarRig.cpp b/libraries/animation/src/AvatarRig.cpp index 97fbb82944..ebf0a8795e 100644 --- a/libraries/animation/src/AvatarRig.cpp +++ b/libraries/animation/src/AvatarRig.cpp @@ -17,7 +17,6 @@ void AvatarRig::updateJointState(int index, glm::mat4 parentTransform) { return; // bail } JointState& state = _jointStates[index]; - const FBXJoint& joint = state.getFBXJoint(); // compute model transforms if (index == _rootJointIndex) { @@ -26,7 +25,7 @@ void AvatarRig::updateJointState(int index, glm::mat4 parentTransform) { clearJointTransformTranslation(index); } else { // guard against out-of-bounds access to _jointStates - int parentIndex = joint.parentIndex; + int parentIndex = state.getParentIndex(); if (parentIndex >= 0 && parentIndex < _jointStates.size()) { const JointState& parentState = _jointStates.at(parentIndex); state.computeTransform(parentState.getTransform(), parentState.getTransformChanged()); @@ -53,8 +52,8 @@ void AvatarRig::setHandPosition(int jointIndex, } // precomputed lengths - float upperArmLength = _jointStates[elbowJointIndex].getFBXJoint().distanceToParent * scale; - float lowerArmLength = _jointStates[jointIndex].getFBXJoint().distanceToParent * scale; + float upperArmLength = _jointStates[elbowJointIndex].getDistanceToParent() * scale; + float lowerArmLength = _jointStates[jointIndex].getDistanceToParent() * scale; // first set wrist position glm::vec3 wristPosition = position; diff --git a/libraries/animation/src/EntityRig.cpp b/libraries/animation/src/EntityRig.cpp index 5ed1799671..eddbdd6464 100644 --- a/libraries/animation/src/EntityRig.cpp +++ b/libraries/animation/src/EntityRig.cpp @@ -14,15 +14,14 @@ /// Updates the state of the joint at the specified index. void EntityRig::updateJointState(int index, glm::mat4 parentTransform) { JointState& state = _jointStates[index]; - const FBXJoint& joint = state.getFBXJoint(); // compute model transforms - int parentIndex = joint.parentIndex; + int parentIndex = state.getParentIndex(); if (parentIndex == -1) { state.computeTransform(parentTransform); } else { // guard against out-of-bounds access to _jointStates - if (joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) { + if (parentIndex >= 0 && parentIndex < _jointStates.size()) { const JointState& parentState = _jointStates.at(parentIndex); state.computeTransform(parentState.getTransform(), parentState.getTransformChanged()); } diff --git a/libraries/animation/src/JointState.cpp b/libraries/animation/src/JointState.cpp index 3682837719..f867369c1d 100644 --- a/libraries/animation/src/JointState.cpp +++ b/libraries/animation/src/JointState.cpp @@ -24,7 +24,6 @@ JointState::JointState() : _rotationIsValid(false), _positionInParentFrame(0.0f), _distanceToParent(0.0f), - _fbxJoint(NULL), _constraint(NULL) { } @@ -37,8 +36,21 @@ JointState::JointState(const JointState& other) : _constraint(NULL) { _positionInParentFrame = other._positionInParentFrame; _distanceToParent = other._distanceToParent; _animationPriority = other._animationPriority; - _fbxJoint = other._fbxJoint; // DO NOT copy _constraint + _name = other._name; + _isFree = other._isFree; + _boneRadius = other._boneRadius; + _parentIndex = other._parentIndex; + _translation = other._translation; + _originalRotation = other._originalRotation; + _inverseDefaultRotation = other._inverseDefaultRotation; + _rotationMin = other._rotationMin; + _rotationMax = other._rotationMax; + _preRotation = other._preRotation; + _postRotation = other._postRotation; + _preTransform = other._preTransform; + _postTransform = other._postTransform; + _inverseBindRotation = other._inverseBindRotation; } JointState::~JointState() { @@ -65,8 +77,20 @@ void JointState::setFBXJoint(const FBXJoint* joint) { _transformChanged = true; _rotationIsValid = false; - // NOTE: JointState does not own the FBXJoint to which it points. - _fbxJoint = joint; + _name = joint->name; + _isFree = joint->isFree; + _boneRadius = joint->boneRadius; + _parentIndex = joint->parentIndex; + _translation = joint->translation; + _originalRotation = joint->rotation; + _inverseDefaultRotation = joint->inverseDefaultRotation; + _rotationMin = joint->rotationMin; + _rotationMax = joint->rotationMax; + _preRotation = joint->preRotation; + _postRotation = joint->postRotation; + _preTransform = joint->preTransform; + _postTransform = joint->postTransform; + _inverseBindRotation = joint->inverseBindRotation; if (_constraint) { delete _constraint; _constraint = NULL; @@ -78,10 +102,10 @@ void JointState::buildConstraint() { delete _constraint; _constraint = NULL; } - if (glm::distance2(glm::vec3(-PI), _fbxJoint->rotationMin) > EPSILON || - glm::distance2(glm::vec3(PI), _fbxJoint->rotationMax) > EPSILON ) { + if (glm::distance2(glm::vec3(-PI), _rotationMin) > EPSILON || + glm::distance2(glm::vec3(PI), _rotationMax) > EPSILON ) { // this joint has rotation constraints - _constraint = AngularConstraint::newAngularConstraint(_fbxJoint->rotationMin, _fbxJoint->rotationMax); + _constraint = AngularConstraint::newAngularConstraint(_rotationMin, _rotationMax); } } @@ -98,7 +122,21 @@ void JointState::copyState(const JointState& state) { _visibleTransform = state._visibleTransform; _visibleRotation = extractRotation(_visibleTransform); _visibleRotationInConstrainedFrame = state._visibleRotationInConstrainedFrame; - // DO NOT copy _fbxJoint or _constraint + // DO NOT copy _constraint + _name = state._name; + _isFree = state._isFree; + _boneRadius = state._boneRadius; + _parentIndex = state._parentIndex; + _originalRotation = state._originalRotation; + _inverseDefaultRotation = state._inverseDefaultRotation; + _translation = state._translation; + _rotationMin = state._rotationMin; + _rotationMax = state._rotationMax; + _preRotation = state._preRotation; + _postRotation = state._postRotation; + _preTransform = state._preTransform; + _postTransform = state._postTransform; + _inverseBindRotation = state._inverseBindRotation; } void JointState::initTransform(const glm::mat4& parentTransform) { @@ -112,9 +150,9 @@ void JointState::computeTransform(const glm::mat4& parentTransform, bool parentT return; } - glm::quat rotationInParentFrame = _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; - glm::mat4 transformInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInParentFrame) * _fbxJoint->postTransform; - glm::mat4 newTransform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame; + glm::quat rotationInParentFrame = _preRotation * _rotationInConstrainedFrame * _postRotation; + glm::mat4 transformInParentFrame = _preTransform * glm::mat4_cast(rotationInParentFrame) * _postTransform; + glm::mat4 newTransform = parentTransform * glm::translate(_translation) * transformInParentFrame; if (newTransform != _transform) { _transform = newTransform; @@ -124,37 +162,35 @@ void JointState::computeTransform(const glm::mat4& parentTransform, bool parentT } void JointState::computeVisibleTransform(const glm::mat4& parentTransform) { - glm::quat rotationInParentFrame = _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; - glm::mat4 transformInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInParentFrame) * _fbxJoint->postTransform; - _visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame; + glm::quat rotationInParentFrame = _preRotation * _visibleRotationInConstrainedFrame * _postRotation; + glm::mat4 transformInParentFrame = _preTransform * glm::mat4_cast(rotationInParentFrame) * _postTransform; + _visibleTransform = parentTransform * glm::translate(_translation) * transformInParentFrame; _visibleRotation = extractRotation(_visibleTransform); } glm::quat JointState::getRotationInBindFrame() const { - return getRotation() * _fbxJoint->inverseBindRotation; + return getRotation() * _inverseBindRotation; } glm::quat JointState::getRotationInParentFrame() const { - return _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; + return _preRotation * _rotationInConstrainedFrame * _postRotation; } glm::quat JointState::getVisibleRotationInParentFrame() const { - return _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; + return _preRotation * _visibleRotationInConstrainedFrame * _postRotation; } void JointState::restoreRotation(float fraction, float priority) { - assert(_fbxJoint != NULL); if (priority == _animationPriority || _animationPriority == 0.0f) { - setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _fbxJoint->rotation, fraction)); + setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _originalRotation, fraction)); _animationPriority = 0.0f; } } void JointState::setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain) { // rotation is from bind- to model-frame - assert(_fbxJoint != NULL); if (priority >= _animationPriority) { - glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_fbxJoint->inverseBindRotation); + glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_inverseBindRotation); if (constrain && _constraint) { _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); } @@ -175,7 +211,6 @@ void JointState::clearTransformTranslation() { void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { // NOTE: delta is in model-frame - assert(_fbxJoint != NULL); if (priority < _animationPriority || delta == glm::quat()) { return; } @@ -196,14 +231,13 @@ void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, floa /// This helps keep an IK solution stable. void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float priority) { // NOTE: delta is in model-frame - assert(_fbxJoint != NULL); if (priority < _animationPriority) { return; } _animationPriority = priority; glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation(); if (mixFactor > 0.0f && mixFactor <= 1.0f) { - targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor); + targetRotation = safeMix(targetRotation, _originalRotation, mixFactor); } if (_constraint) { _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); @@ -213,10 +247,8 @@ void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float void JointState::mixVisibleRotationDelta(const glm::quat& delta, float mixFactor) { // NOTE: delta is in model-frame - assert(_fbxJoint != NULL); glm::quat targetRotation = _visibleRotationInConstrainedFrame * glm::inverse(_visibleRotation) * delta * _visibleRotation; if (mixFactor > 0.0f && mixFactor <= 1.0f) { - //targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor); targetRotation = safeMix(targetRotation, _rotationInConstrainedFrame, mixFactor); } setVisibleRotationInConstrainedFrame(targetRotation); @@ -225,11 +257,11 @@ void JointState::mixVisibleRotationDelta(const glm::quat& delta, float mixFactor glm::quat JointState::computeParentRotation() const { // R = Rp * Rpre * r * Rpost // Rp = R * (Rpre * r * Rpost)^ - return getRotation() * glm::inverse(_fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation); + return getRotation() * glm::inverse(_preRotation * _rotationInConstrainedFrame * _postRotation); } glm::quat JointState::computeVisibleParentRotation() const { - return _visibleRotation * glm::inverse(_fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation); + return _visibleRotation * glm::inverse(_preRotation * _visibleRotationInConstrainedFrame * _postRotation); } void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain, float mix) { @@ -248,17 +280,17 @@ void JointState::setRotationInConstrainedFrameInternal(const glm::quat& targetRo _rotationInConstrainedFrame = targetRotation; _transformChanged = true; // R' = Rp * Rpre * r' * Rpost - _rotation = parentRotation * _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation; + _rotation = parentRotation * _preRotation * _rotationInConstrainedFrame * _postRotation; } void JointState::setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation) { glm::quat parentRotation = computeVisibleParentRotation(); _visibleRotationInConstrainedFrame = targetRotation; - _visibleRotation = parentRotation * _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation; + _visibleRotation = parentRotation * _preRotation * _visibleRotationInConstrainedFrame * _postRotation; } bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) const { - glm::quat defaultRotation = _fbxJoint->rotation; + glm::quat defaultRotation = _originalRotation; return glm::abs(rotation.x - defaultRotation.x) < tolerance && glm::abs(rotation.y - defaultRotation.y) < tolerance && glm::abs(rotation.z - defaultRotation.z) < tolerance && @@ -266,13 +298,12 @@ bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) c } glm::quat JointState::getDefaultRotationInParentFrame() const { - // NOTE: the result is constant and could be cached in the FBXJoint - return _fbxJoint->preRotation * _fbxJoint->rotation * _fbxJoint->postRotation; + // NOTE: the result is constant and could be cached + return _preRotation * _originalRotation * _postRotation; } const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const { - assert(_fbxJoint != NULL); - return _fbxJoint->translation; + return _translation; } void JointState::slaveVisibleTransform() { diff --git a/libraries/animation/src/JointState.h b/libraries/animation/src/JointState.h index 93bf83d2c4..d7e954d59c 100644 --- a/libraries/animation/src/JointState.h +++ b/libraries/animation/src/JointState.h @@ -31,7 +31,6 @@ public: ~JointState(); void setFBXJoint(const FBXJoint* joint); - const FBXJoint& getFBXJoint() const { return *_fbxJoint; } void buildConstraint(); void copyState(const JointState& state); @@ -61,7 +60,7 @@ public: const glm::vec3& getPositionInParentFrame() const { return _positionInParentFrame; } float getDistanceToParent() const { return _distanceToParent; } - int getParentIndex() const { return _fbxJoint->parentIndex; } + int getParentIndex() const { return _parentIndex; } /// \param delta is in the model-frame void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); @@ -108,6 +107,17 @@ public: void setTransform(const glm::mat4& transform) { _transform = transform; } void setVisibleTransform(const glm::mat4& transform) { _visibleTransform = transform; } + + const glm::vec3& getTranslation() const { return _translation; } + const glm::mat4& getPreTransform() const { return _preTransform; } + const glm::mat4& getPostTransform() const { return _postTransform; } + const glm::quat& getPreRotation() const { return _preRotation; } + const glm::quat& getPostRotation() const { return _postRotation; } + const glm::quat& getOriginalRotation() const { return _originalRotation; } + const glm::quat& getInverseDefaultRotation() const { return _inverseDefaultRotation; } + const QString& getName() const { return _name; } + float getBoneRadius() const { return _boneRadius; } + bool getIsFree() const { return _isFree; } private: void setRotationInConstrainedFrameInternal(const glm::quat& targetRotation); @@ -126,7 +136,20 @@ private: glm::quat _visibleRotation; glm::quat _visibleRotationInConstrainedFrame; - const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint + glm::quat _originalRotation; // Not necessarilly bind rotation. See FBXJoint transform/bindTransform + glm::quat _inverseDefaultRotation; + glm::vec3 _translation; + float _boneRadius; + bool _isFree; + glm::vec3 _rotationMin; + glm::vec3 _rotationMax; + glm::quat _preRotation; + glm::quat _postRotation; + glm::mat4 _preTransform; + glm::mat4 _postTransform; + glm::quat _inverseBindRotation; + int _parentIndex; + QString _name; AngularConstraint* _constraint; // JointState owns its AngularConstraint }; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index ec34e90b5c..1c7257adc7 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -222,7 +222,7 @@ float Rig::initJointStates(QVector states, glm::mat4 parentTransform // Should we be using .fst mapping instead/also? int Rig::indexOfJoint(const QString& jointName) { for (int i = 0; i < _jointStates.count(); i++) { - if (_jointStates[i].getFBXJoint().name == jointName) { + if (_jointStates[i].getName() == jointName) { return i; } } @@ -235,8 +235,7 @@ void Rig::initJointTransforms(glm::mat4 parentTransform) { int numStates = _jointStates.size(); for (int i = 0; i < numStates; ++i) { JointState& state = _jointStates[i]; - const FBXJoint& joint = state.getFBXJoint(); - int parentIndex = joint.parentIndex; + int parentIndex = state.getParentIndex(); if (parentIndex == -1) { state.initTransform(parentTransform); } else { @@ -528,8 +527,7 @@ bool Rig::setJointPosition(int jointIndex, const glm::vec3& position, const glm: for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) { int index = freeLineage.at(j); JointState& state = _jointStates[index]; - const FBXJoint& joint = state.getFBXJoint(); - if (!(joint.isFree || allIntermediatesFree)) { + if (!(state.getIsFree() || allIntermediatesFree)) { continue; } glm::vec3 jointPosition = extractTranslation(state.getTransform()); @@ -598,8 +596,7 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q { int index = freeLineage.last(); const JointState& state = _jointStates.at(index); - const FBXJoint& joint = state.getFBXJoint(); - int parentIndex = joint.parentIndex; + int parentIndex = state.getParentIndex(); if (parentIndex == -1) { topParentTransform = parentTransform; } else { @@ -624,8 +621,7 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q for (int j = 1; j < numFree; j++) { int nextIndex = freeLineage.at(j); JointState& nextState = _jointStates[nextIndex]; - FBXJoint nextJoint = nextState.getFBXJoint(); - if (! nextJoint.isFree) { + if (! nextState.getIsFree()) { continue; } @@ -799,20 +795,20 @@ void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, floa glm::angleAxis(- RADIANS_PER_DEGREE * leanSideways, inverse * zAxis) * glm::angleAxis(- RADIANS_PER_DEGREE * leanForward, inverse * xAxis) * glm::angleAxis(RADIANS_PER_DEGREE * torsoTwist, inverse * yAxis) * - getJointState(index).getFBXJoint().rotation, DEFAULT_PRIORITY); + getJointState(index).getOriginalRotation(), DEFAULT_PRIORITY); } } void Rig::updateNeckJoint(int index, const glm::quat& localHeadOrientation, float leanSideways, float leanForward, float torsoTwist) { if (index >= 0 && _jointStates[index].getParentIndex() >= 0) { - auto& parentState = _jointStates[_jointStates[index].getParentIndex()]; - auto joint = _jointStates[index].getFBXJoint(); + auto& state = _jointStates[index]; + auto& parentState = _jointStates[state.getParentIndex()]; // get the rotation axes in joint space and use them to adjust the rotation glm::mat3 axes = glm::mat3_cast(glm::quat()); glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(getJointDefaultTranslationInConstrainedFrame(index)) * - joint.preTransform * glm::mat4_cast(joint.preRotation))); + state.getPreTransform() * glm::mat4_cast(state.getPreRotation()))); glm::vec3 pitchYawRoll = safeEulerAngles(localHeadOrientation); glm::vec3 lean = glm::radians(glm::vec3(leanForward, torsoTwist, leanSideways)); pitchYawRoll -= lean; @@ -820,19 +816,19 @@ void Rig::updateNeckJoint(int index, const glm::quat& localHeadOrientation, floa glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * axes[2])) * glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * axes[1])) * glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * axes[0])) * - joint.rotation, DEFAULT_PRIORITY); + state.getOriginalRotation(), DEFAULT_PRIORITY); } } void Rig::updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade) { if (index >= 0 && _jointStates[index].getParentIndex() >= 0) { - auto& parentState = _jointStates[_jointStates[index].getParentIndex()]; - auto joint = _jointStates[index].getFBXJoint(); + auto& state = _jointStates[index]; + auto& parentState = _jointStates[state.getParentIndex()]; // NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual. glm::mat4 inverse = glm::inverse(parentState.getTransform() * glm::translate(getJointDefaultTranslationInConstrainedFrame(index)) * - joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); + state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getOriginalRotation())); glm::vec3 front = glm::vec3(inverse * glm::vec4(worldHeadOrientation * IDENTITY_FRONT, 0.0f)); glm::vec3 lookAtDelta = lookAt; glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * saccade, 1.0f)); @@ -840,6 +836,6 @@ void Rig::updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; float angle = glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE); glm::quat rot = glm::angleAxis(angle, glm::axis(between)); - setJointRotationInConstrainedFrame(index, rot * joint.rotation, DEFAULT_PRIORITY); + setJointRotationInConstrainedFrame(index, rot * state.getOriginalRotation(), DEFAULT_PRIORITY); } } diff --git a/tests/animation/src/RigTests.cpp b/tests/animation/src/RigTests.cpp index 8dbba30031..79c2f3b5df 100644 --- a/tests/animation/src/RigTests.cpp +++ b/tests/animation/src/RigTests.cpp @@ -79,7 +79,7 @@ void RigTests::initTestCase() { static void reportJoint(int index, JointState joint) { // Handy for debugging std::cout << "\n"; - std::cout << index << " " << joint.getFBXJoint().name.toUtf8().data() << "\n"; + std::cout << index << " " << joint.getName.toUtf8().data() << "\n"; std::cout << " pos:" << joint.getPosition() << "/" << joint.getPositionInParentFrame() << " from " << joint.getParentIndex() << "\n"; std::cout << " rot:" << safeEulerAngles(joint.getRotation()) << "/" << safeEulerAngles(joint.getRotationInParentFrame()) << "/" << safeEulerAngles(joint.getRotationInBindFrame()) << "\n"; std::cout << "\n"; From 2aacd17843ffbf806cf21390f66de94faf08723d Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 16:58:03 -0700 Subject: [PATCH 23/42] Make OverlayPanel PanelAttachable. --- interface/src/ui/overlays/OverlayPanel.cpp | 51 ++----------------- interface/src/ui/overlays/OverlayPanel.h | 14 ++--- interface/src/ui/overlays/PanelAttachable.cpp | 10 ++-- interface/src/ui/overlays/PanelAttachable.h | 16 +++--- 4 files changed, 23 insertions(+), 68 deletions(-) diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index 58d85241ff..a4f1454add 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -36,7 +36,7 @@ glm::vec3 OverlayPanel::getComputedPosition() const { glm::quat OverlayPanel::getComputedRotation() const { if (getParentPanel()) { - return getParentPanel()->getComputedRotation() * getParentPanel()->getFacingRotation(); + return getParentPanel()->getComputedRotation() * getParentPanel()->getOffsetRotation(); } else if (_rotationBindMyAvatar) { return DependencyManager::get()->getMyAvatar()->getOrientation() * glm::angleAxis(glm::pi(), IDENTITY_UP); @@ -47,14 +47,6 @@ glm::quat OverlayPanel::getComputedRotation() const { return getRotation(); } -bool OverlayPanel::getParentVisible() const { - if (getParentPanel()) { - return getParentPanel()->getVisible() && getParentPanel()->getParentVisible(); - } else { - return true; - } -} - void OverlayPanel::addChild(unsigned int childId) { if (!_children.contains(childId)) { _children.append(childId); @@ -98,12 +90,6 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { obj.setProperty("computed", quatToScriptValue(_scriptEngine, getComputedRotation())); return obj; } - if (property == "offsetPosition") { - return vec3toScriptValue(_scriptEngine, getOffsetPosition()); - } - if (property == "offsetRotation") { - return quatToScriptValue(_scriptEngine, getFacingRotation()); - } if (property == "visible") { return getVisible(); } @@ -115,10 +101,12 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { return array; } - return QScriptValue(); + return PanelAttachable::getProperty(_scriptEngine, property); } void OverlayPanel::setProperties(const QScriptValue &properties) { + PanelAttachable::setProperties(properties); + QScriptValue position = properties.property("position"); if (position.isValid()) { QScriptValue x = position.property("x"); @@ -180,37 +168,6 @@ void OverlayPanel::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); - } - } - - 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 (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(); - setFacingRotation(newRotation); - } - } - QScriptValue visible = properties.property("visible"); if (visible.isValid()) { setVisible(visible.toVariant().toBool()); diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index af6ceb2731..bd08ab87eb 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -19,7 +19,9 @@ #include #include -class OverlayPanel : public QObject { +#include "PanelAttachable.h" + +class OverlayPanel : public QObject, public PanelAttachable { Q_OBJECT public: @@ -32,18 +34,11 @@ public: glm::vec3 getComputedPosition() const; glm::quat getRotation() const { return _rotation; } glm::quat getComputedRotation() const; - glm::vec3 getOffsetPosition() const { return _offsetPosition; } - glm::quat getFacingRotation() const { return _offsetRotation; } - Pointer getParentPanel() const { return _parentPanel; } bool getVisible() const { return _visible; } - bool getParentVisible() const; // setters void setPosition(const glm::vec3& position) { _position = position; } void setRotation(const glm::quat& rotation) { _rotation = rotation; } - void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } - void setFacingRotation(const glm::quat& rotation) { _offsetRotation = rotation; } - void setParentPanel(Pointer panel) { _parentPanel = panel; } void setVisible(bool visible) { _visible = visible; } const QList& getChildren() { return _children; } @@ -57,8 +52,6 @@ public: private: glm::vec3 _position = {0, 0, 0}; glm::quat _rotation = {1, 0, 0, 0}; - glm::vec3 _offsetPosition = {0, 0, 0}; - glm::quat _offsetRotation = {1, 0, 0, 0}; bool _positionBindMyAvatar = false; QUuid _positionBindEntity; @@ -66,7 +59,6 @@ private: bool _rotationBindMyAvatar = false; QUuid _rotationBindEntity; - Pointer _parentPanel = nullptr; QList _children; bool _visible = true; diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 6626107247..b95e7391f3 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -13,6 +13,8 @@ #include +#include "OverlayPanel.h" + bool PanelAttachable::getParentVisible() const { if (getParentPanel()) { return getParentPanel()->getVisible() && getParentPanel()->getParentVisible(); @@ -26,9 +28,9 @@ void PanelAttachable::applyTransformTo(Transform& transform) { transform.setTranslation(getParentPanel()->getComputedPosition()); transform.setRotation(getParentPanel()->getComputedRotation()); transform.postTranslate(getParentPanel()->getOffsetPosition()); - transform.postRotate(getParentPanel()->getFacingRotation()); + transform.postRotate(getParentPanel()->getOffsetRotation()); transform.postTranslate(getOffsetPosition()); - transform.postRotate(getFacingRotation()); + transform.postRotate(getOffsetRotation()); } } @@ -37,7 +39,7 @@ QScriptValue PanelAttachable::getProperty(QScriptEngine* scriptEngine, const QSt return vec3toScriptValue(scriptEngine, getOffsetPosition()); } if (property == "offsetRotation") { - return quatToScriptValue(scriptEngine, getFacingRotation()); + return quatToScriptValue(scriptEngine, getOffsetRotation()); } return QScriptValue(); } @@ -71,7 +73,7 @@ void PanelAttachable::setProperties(const QScriptValue &properties) { newRotation.y = y.toVariant().toFloat(); newRotation.z = z.toVariant().toFloat(); newRotation.w = w.toVariant().toFloat(); - setFacingRotation(newRotation); + setOffsetRotation(newRotation); } } } diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index db2665e6eb..0014b81729 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -12,21 +12,25 @@ #ifndef hifi_PanelAttachable_h #define hifi_PanelAttachable_h -#include "OverlayPanel.h" +#include #include #include +#include +#include + +class OverlayPanel; class PanelAttachable { public: - OverlayPanel::Pointer getParentPanel() const { return _parentPanel; } + std::shared_ptr getParentPanel() const { return _parentPanel; } virtual glm::vec3 getOffsetPosition() const { return _offsetPosition; } - virtual glm::quat getFacingRotation() const { return _offsetRotation; } + virtual glm::quat getOffsetRotation() const { return _offsetRotation; } bool getParentVisible() const; - void setParentPanel(OverlayPanel::Pointer panel) { _parentPanel = panel; } + void setParentPanel(std::shared_ptr panel) { _parentPanel = panel; } virtual void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } - virtual void setFacingRotation(const glm::quat& rotation) { _offsetRotation = rotation; } + virtual void setOffsetRotation(const glm::quat& rotation) { _offsetRotation = rotation; } QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); void setProperties(const QScriptValue& properties); @@ -35,7 +39,7 @@ protected: virtual void applyTransformTo(Transform& transform); private: - OverlayPanel::Pointer _parentPanel = nullptr; + std::shared_ptr _parentPanel = nullptr; glm::vec3 _offsetPosition = {0, 0, 0}; glm::quat _offsetRotation = {1, 0, 0, 0}; }; From f870f198377d45e2c22081de0d1fa8325bbe760c Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 17:29:37 -0700 Subject: [PATCH 24/42] Make transforms cascade down the pannel chain. --- interface/src/ui/overlays/OverlayPanel.cpp | 62 ++++++++++--------- interface/src/ui/overlays/OverlayPanel.h | 7 ++- interface/src/ui/overlays/PanelAttachable.cpp | 9 +-- 3 files changed, 44 insertions(+), 34 deletions(-) diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index a4f1454add..e388e981ea 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -21,32 +21,6 @@ #include "Application.h" #include "Base3DOverlay.h" -glm::vec3 OverlayPanel::getComputedPosition() const { - if (getParentPanel()) { - return getParentPanel()->getComputedRotation() * getParentPanel()->getOffsetPosition() + - getParentPanel()->getComputedPosition(); - } else if (_positionBindMyAvatar) { - return DependencyManager::get()->getMyAvatar()->getPosition(); - } else if (!_positionBindEntity.isNull()) { - return DependencyManager::get()->getEntityTree()-> - findEntityByID(_positionBindEntity)->getPosition(); - } - return getPosition(); -} - -glm::quat OverlayPanel::getComputedRotation() const { - if (getParentPanel()) { - return getParentPanel()->getComputedRotation() * getParentPanel()->getOffsetRotation(); - } else if (_rotationBindMyAvatar) { - return DependencyManager::get()->getMyAvatar()->getOrientation() * - glm::angleAxis(glm::pi(), IDENTITY_UP); - } else if (!_rotationBindEntity.isNull()) { - return DependencyManager::get()->getEntityTree()-> - findEntityByID(_rotationBindEntity)->getRotation(); - } - return getRotation(); -} - void OverlayPanel::addChild(unsigned int childId) { if (!_children.contains(childId)) { _children.append(childId); @@ -72,7 +46,6 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { obj.setProperty("entity", _scriptEngine->newVariant(_positionBindEntity)); } - obj.setProperty("computed", vec3toScriptValue(_scriptEngine, getComputedPosition())); return obj; } if (property == "rotation") { @@ -87,7 +60,6 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { obj.setProperty("entity", _scriptEngine->newVariant(_rotationBindEntity)); } - obj.setProperty("computed", quatToScriptValue(_scriptEngine, getComputedRotation())); return obj; } if (property == "visible") { @@ -173,3 +145,37 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { setVisible(visible.toVariant().toBool()); } } + +void OverlayPanel::applyTransformTo(Transform& transform) { + if (getParentPanel()) { + getParentPanel()->applyTransformTo(transform); + } else { + transform.setTranslation(getComputedPosition()); + transform.setRotation(getComputedRotation()); + } + _position = transform.getTranslation(); + _rotation = transform.getRotation(); + transform.postTranslate(getOffsetPosition()); + transform.postRotate(getOffsetRotation()); +} + +glm::vec3 OverlayPanel::getComputedPosition() const { + if (_positionBindMyAvatar) { + return DependencyManager::get()->getMyAvatar()->getPosition(); + } else if (!_positionBindEntity.isNull()) { + return 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); + } else if (!_rotationBindEntity.isNull()) { + return 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 bd08ab87eb..7c077e90da 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -31,9 +31,7 @@ public: // getters glm::vec3 getPosition() const { return _position; } - glm::vec3 getComputedPosition() const; glm::quat getRotation() const { return _rotation; } - glm::quat getComputedRotation() const; bool getVisible() const { return _visible; } // setters @@ -49,7 +47,12 @@ public: QScriptValue getProperty(const QString& property); void setProperties(const QScriptValue& properties); + virtual void applyTransformTo(Transform& transform); + private: + glm::vec3 getComputedPosition() const; + glm::quat getComputedRotation() const; + glm::vec3 _position = {0, 0, 0}; glm::quat _rotation = {1, 0, 0, 0}; diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index b95e7391f3..5c02ab1184 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -25,10 +25,11 @@ bool PanelAttachable::getParentVisible() const { void PanelAttachable::applyTransformTo(Transform& transform) { if (getParentPanel()) { - transform.setTranslation(getParentPanel()->getComputedPosition()); - transform.setRotation(getParentPanel()->getComputedRotation()); - transform.postTranslate(getParentPanel()->getOffsetPosition()); - transform.postRotate(getParentPanel()->getOffsetRotation()); +// transform.setTranslation(getParentPanel()->getComputedPosition()); +// transform.setRotation(getParentPanel()->getComputedRotation()); +// transform.postTranslate(getParentPanel()->getOffsetPosition()); +// transform.postRotate(getParentPanel()->getOffsetRotation()); + getParentPanel()->applyTransformTo(transform); transform.postTranslate(getOffsetPosition()); transform.postRotate(getOffsetRotation()); } From fa24df765d774f828e7c98f4608e2a7f63681f5f Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 18:07:59 -0700 Subject: [PATCH 25/42] Register OverlayPanel binding map as a meta type. --- interface/src/Application.cpp | 1 + interface/src/ui/overlays/OverlayPanel.cpp | 110 +++++++++++------- interface/src/ui/overlays/OverlayPanel.h | 13 +++ interface/src/ui/overlays/PanelAttachable.cpp | 4 - interface/src/ui/overlays/PanelAttachable.h | 1 + 5 files changed, 82 insertions(+), 47 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 503acc2ce3..c45f46fffc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3750,6 +3750,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue); qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue, RayToOverlayIntersectionResultFromScriptValue); + qScriptRegisterMetaType(scriptEngine, propertyBindingToScriptValue, propertyBindingFromScriptValue); QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", DependencyManager::get().data()); scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index e388e981ea..ff7b218a5a 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -21,6 +21,38 @@ #include "Application.h" #include "Base3DOverlay.h" +PropertyBinding::PropertyBinding(QString avatar, QUuid entity) : + avatar(avatar), + entity(entity) +{ +} + +QScriptValue propertyBindingToScriptValue(QScriptEngine* engine, const PropertyBinding& value) { + QScriptValue obj = engine->newObject(); + + if (value.avatar == "MyAvatar") { + obj.setProperty("avatar", "MyAvatar"); + } else if (!value.entity.isNull()) { + obj.setProperty("entity", engine->newVariant(value.entity)); + } + + return obj; +} + +void propertyBindingFromScriptValue(const QScriptValue& object, PropertyBinding& value) { + value.avatar = ""; + value.entity = {}; + QScriptValue avatar = object.property("avatar"); + QScriptValue entity = object.property("entity"); + + if (avatar.isValid() && !avatar.isNull()) { + value.avatar = avatar.toVariant().toString(); + } else if (entity.isValid() && !entity.isNull()) { + value.entity = entity.toVariant().toUuid(); + } +} + + void OverlayPanel::addChild(unsigned int childId) { if (!_children.contains(childId)) { _children.append(childId); @@ -38,29 +70,35 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { return vec3toScriptValue(_scriptEngine, getPosition()); } if (property == "positionBinding") { - QScriptValue obj = _scriptEngine->newObject(); - - if (_positionBindMyAvatar) { - obj.setProperty("avatar", "MyAvatar"); - } else if (!_positionBindEntity.isNull()) { - obj.setProperty("entity", _scriptEngine->newVariant(_positionBindEntity)); - } - - return obj; + return propertyBindingToScriptValue(_scriptEngine, PropertyBinding(_positionBindMyAvatar ? + "MyAvatar" : "", + _positionBindEntity)); +// QScriptValue obj = _scriptEngine->newObject(); +// +// if (_positionBindMyAvatar) { +// obj.setProperty("avatar", "MyAvatar"); +// } else if (!_positionBindEntity.isNull()) { +// obj.setProperty("entity", _scriptEngine->newVariant(_positionBindEntity)); +// } +// +// return obj; } if (property == "rotation") { return quatToScriptValue(_scriptEngine, getRotation()); } if (property == "rotationBinding") { - QScriptValue obj = _scriptEngine->newObject(); - - if (_rotationBindMyAvatar) { - obj.setProperty("avatar", "MyAvatar"); - } else if (!_rotationBindEntity.isNull()) { - obj.setProperty("entity", _scriptEngine->newVariant(_rotationBindEntity)); - } - - return obj; + return propertyBindingToScriptValue(_scriptEngine, PropertyBinding(_rotationBindMyAvatar ? + "MyAvatar" : "", + _rotationBindEntity)); +// QScriptValue obj = _scriptEngine->newObject(); +// +// if (_rotationBindMyAvatar) { +// obj.setProperty("avatar", "MyAvatar"); +// } else if (!_rotationBindEntity.isNull()) { +// obj.setProperty("entity", _scriptEngine->newVariant(_rotationBindEntity)); +// } +// +// return obj; } if (property == "visible") { return getVisible(); @@ -80,17 +118,11 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { PanelAttachable::setProperties(properties); QScriptValue position = properties.property("position"); - if (position.isValid()) { - QScriptValue x = position.property("x"); - QScriptValue y = position.property("y"); - QScriptValue z = position.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(); - setPosition(newPosition); - } + if (position.isValid() && + position.property("x").isValid() && + position.property("y").isValid() && + position.property("z").isValid()) { + vec3FromScriptValue(position, _position); } QScriptValue positionBinding = properties.property("positionBinding"); @@ -109,20 +141,12 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { } QScriptValue rotation = properties.property("rotation"); - if (rotation.isValid()) { - QScriptValue x = rotation.property("x"); - QScriptValue y = rotation.property("y"); - QScriptValue z = rotation.property("z"); - QScriptValue w = rotation.property("w"); - - 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(); - setRotation(newRotation); - } + if (rotation.isValid() && + rotation.property("x").isValid() && + rotation.property("y").isValid() && + rotation.property("z").isValid() && + rotation.property("w").isValid()) { + quatFromScriptValue(rotation, _rotation); } QScriptValue rotationBinding = properties.property("rotationBinding"); diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index 7c077e90da..9e790afd9f 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -21,6 +21,19 @@ #include "PanelAttachable.h" +class PropertyBinding { +public: + PropertyBinding() {} + PropertyBinding(QString avatar, QUuid entity); + QString avatar; + QUuid entity; +}; + +Q_DECLARE_METATYPE(PropertyBinding); +QScriptValue propertyBindingToScriptValue(QScriptEngine* engine, const PropertyBinding& value); +void propertyBindingFromScriptValue(const QScriptValue& object, PropertyBinding& value); + + class OverlayPanel : public QObject, public PanelAttachable { Q_OBJECT diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 5c02ab1184..90b8112de2 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -25,10 +25,6 @@ bool PanelAttachable::getParentVisible() const { void PanelAttachable::applyTransformTo(Transform& transform) { if (getParentPanel()) { -// transform.setTranslation(getParentPanel()->getComputedPosition()); -// transform.setRotation(getParentPanel()->getComputedRotation()); -// transform.postTranslate(getParentPanel()->getOffsetPosition()); -// transform.postRotate(getParentPanel()->getOffsetRotation()); getParentPanel()->applyTransformTo(transform); transform.postTranslate(getOffsetPosition()); transform.postRotate(getOffsetRotation()); diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index 0014b81729..a41f20152e 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -18,6 +18,7 @@ #include #include #include +#include class OverlayPanel; From 6e8c154c422a07c0a7591bed45ff17271af2f698 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 18:54:08 -0700 Subject: [PATCH 26/42] Undo registering PropertyBinding as a meta type. --- interface/src/Application.cpp | 1 - interface/src/ui/overlays/OverlayPanel.cpp | 50 ++++------------------ interface/src/ui/overlays/OverlayPanel.h | 1 - 3 files changed, 8 insertions(+), 44 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c45f46fffc..503acc2ce3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3750,7 +3750,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue); qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue, RayToOverlayIntersectionResultFromScriptValue); - qScriptRegisterMetaType(scriptEngine, propertyBindingToScriptValue, propertyBindingFromScriptValue); QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", DependencyManager::get().data()); scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index ff7b218a5a..c1ef9fcdb4 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -40,8 +40,6 @@ QScriptValue propertyBindingToScriptValue(QScriptEngine* engine, const PropertyB } void propertyBindingFromScriptValue(const QScriptValue& object, PropertyBinding& value) { - value.avatar = ""; - value.entity = {}; QScriptValue avatar = object.property("avatar"); QScriptValue entity = object.property("entity"); @@ -73,15 +71,6 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { return propertyBindingToScriptValue(_scriptEngine, PropertyBinding(_positionBindMyAvatar ? "MyAvatar" : "", _positionBindEntity)); -// QScriptValue obj = _scriptEngine->newObject(); -// -// if (_positionBindMyAvatar) { -// obj.setProperty("avatar", "MyAvatar"); -// } else if (!_positionBindEntity.isNull()) { -// obj.setProperty("entity", _scriptEngine->newVariant(_positionBindEntity)); -// } -// -// return obj; } if (property == "rotation") { return quatToScriptValue(_scriptEngine, getRotation()); @@ -90,15 +79,6 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { return propertyBindingToScriptValue(_scriptEngine, PropertyBinding(_rotationBindMyAvatar ? "MyAvatar" : "", _rotationBindEntity)); -// QScriptValue obj = _scriptEngine->newObject(); -// -// if (_rotationBindMyAvatar) { -// obj.setProperty("avatar", "MyAvatar"); -// } else if (!_rotationBindEntity.isNull()) { -// obj.setProperty("entity", _scriptEngine->newVariant(_rotationBindEntity)); -// } -// -// return obj; } if (property == "visible") { return getVisible(); @@ -127,17 +107,10 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { QScriptValue positionBinding = properties.property("positionBinding"); if (positionBinding.isValid()) { - _positionBindMyAvatar = false; - _positionBindEntity = QUuid(); - - QScriptValue avatar = positionBinding.property("avatar"); - QScriptValue entity = positionBinding.property("entity"); - - if (avatar.isValid()) { - _positionBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); - } else if (entity.isValid() && !entity.isNull()) { - _positionBindEntity = entity.toVariant().toUuid(); - } + PropertyBinding binding = {}; + propertyBindingFromScriptValue(positionBinding, binding); + _positionBindMyAvatar = binding.avatar == "MyAvatar"; + _positionBindEntity = binding.entity; } QScriptValue rotation = properties.property("rotation"); @@ -151,17 +124,10 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { QScriptValue rotationBinding = properties.property("rotationBinding"); if (rotationBinding.isValid()) { - _rotationBindMyAvatar = false; - _rotationBindEntity = QUuid(); - - QScriptValue avatar = rotationBinding.property("avatar"); - QScriptValue entity = positionBinding.property("entity"); - - if (avatar.isValid()) { - _rotationBindMyAvatar = (avatar.toVariant().toString() == "MyAvatar"); - } else if (entity.isValid() && !entity.isNull()) { - _rotationBindEntity = entity.toVariant().toUuid(); - } + PropertyBinding binding = {}; + propertyBindingFromScriptValue(positionBinding, binding); + _rotationBindMyAvatar = binding.avatar == "MyAvatar"; + _rotationBindEntity = binding.entity; } QScriptValue visible = properties.property("visible"); diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index 9e790afd9f..f398abb4f8 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -29,7 +29,6 @@ public: QUuid entity; }; -Q_DECLARE_METATYPE(PropertyBinding); QScriptValue propertyBindingToScriptValue(QScriptEngine* engine, const PropertyBinding& value); void propertyBindingFromScriptValue(const QScriptValue& object, PropertyBinding& value); From a840a17106475fa284870f6d1c7e7cdcea07316a Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 6 Aug 2015 19:45:58 -0700 Subject: [PATCH 27/42] Change name originalRotation defaultRotation. --- interface/src/avatar/FaceModel.cpp | 6 +++--- interface/src/avatar/SkeletonModel.cpp | 2 +- libraries/animation/src/JointState.cpp | 14 +++++++------- libraries/animation/src/JointState.h | 4 ++-- libraries/animation/src/Rig.cpp | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 22ba7455b8..e31c804185 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -71,7 +71,7 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const Joi glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * axes[2])) * glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * axes[1])) * glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * axes[0])) - * state.getOriginalRotation(), DEFAULT_PRIORITY); + * state.getDefaultRotation(), DEFAULT_PRIORITY); } void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentState, const JointState& state, int index) { @@ -79,7 +79,7 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta // NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual. glm::mat4 inverse = glm::inverse(glm::mat4_cast(model->getRotation()) * parentState.getTransform() * glm::translate(_rig->getJointDefaultTranslationInConstrainedFrame(index)) * - state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getOriginalRotation())); + state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getDefaultRotation())); glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f)); glm::vec3 lookAtDelta = _owningHead->getCorrectedLookAtPosition() - model->getTranslation(); glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * _owningHead->getSaccade(), 1.0f)); @@ -87,7 +87,7 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; _rig->setJointRotationInConstrainedFrame(index, glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) * - state.getOriginalRotation(), DEFAULT_PRIORITY); + state.getDefaultRotation(), DEFAULT_PRIORITY); } void FaceModel::maybeUpdateNeckAndEyeRotation(int index) { diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 8000ed8d26..dab7770a09 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -481,7 +481,7 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) { if (parentIndex == -1) { transforms[i] = _rig->getJointTransform(i); } else { - glm::quat modifiedRotation = state.getPreRotation() * state.getOriginalRotation() * state.getPostRotation(); + glm::quat modifiedRotation = state.getPreRotation() * state.getDefaultRotation() * state.getPostRotation(); transforms[i] = transforms[parentIndex] * glm::translate(state.getTranslation()) * state.getPreTransform() * glm::mat4_cast(modifiedRotation) * state.getPostTransform(); } diff --git a/libraries/animation/src/JointState.cpp b/libraries/animation/src/JointState.cpp index f867369c1d..c81aae468d 100644 --- a/libraries/animation/src/JointState.cpp +++ b/libraries/animation/src/JointState.cpp @@ -42,7 +42,7 @@ JointState::JointState(const JointState& other) : _constraint(NULL) { _boneRadius = other._boneRadius; _parentIndex = other._parentIndex; _translation = other._translation; - _originalRotation = other._originalRotation; + _defaultRotation = other._defaultRotation; _inverseDefaultRotation = other._inverseDefaultRotation; _rotationMin = other._rotationMin; _rotationMax = other._rotationMax; @@ -82,7 +82,7 @@ void JointState::setFBXJoint(const FBXJoint* joint) { _boneRadius = joint->boneRadius; _parentIndex = joint->parentIndex; _translation = joint->translation; - _originalRotation = joint->rotation; + _defaultRotation = joint->rotation; _inverseDefaultRotation = joint->inverseDefaultRotation; _rotationMin = joint->rotationMin; _rotationMax = joint->rotationMax; @@ -127,7 +127,7 @@ void JointState::copyState(const JointState& state) { _isFree = state._isFree; _boneRadius = state._boneRadius; _parentIndex = state._parentIndex; - _originalRotation = state._originalRotation; + _defaultRotation = state._defaultRotation; _inverseDefaultRotation = state._inverseDefaultRotation; _translation = state._translation; _rotationMin = state._rotationMin; @@ -182,7 +182,7 @@ glm::quat JointState::getVisibleRotationInParentFrame() const { void JointState::restoreRotation(float fraction, float priority) { if (priority == _animationPriority || _animationPriority == 0.0f) { - setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _originalRotation, fraction)); + setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _defaultRotation, fraction)); _animationPriority = 0.0f; } } @@ -237,7 +237,7 @@ void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float _animationPriority = priority; glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation(); if (mixFactor > 0.0f && mixFactor <= 1.0f) { - targetRotation = safeMix(targetRotation, _originalRotation, mixFactor); + targetRotation = safeMix(targetRotation, _defaultRotation, mixFactor); } if (_constraint) { _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); @@ -290,7 +290,7 @@ void JointState::setVisibleRotationInConstrainedFrame(const glm::quat& targetRot } bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) const { - glm::quat defaultRotation = _originalRotation; + glm::quat defaultRotation = _defaultRotation; return glm::abs(rotation.x - defaultRotation.x) < tolerance && glm::abs(rotation.y - defaultRotation.y) < tolerance && glm::abs(rotation.z - defaultRotation.z) < tolerance && @@ -299,7 +299,7 @@ bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) c glm::quat JointState::getDefaultRotationInParentFrame() const { // NOTE: the result is constant and could be cached - return _preRotation * _originalRotation * _postRotation; + return _preRotation * _defaultRotation * _postRotation; } const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const { diff --git a/libraries/animation/src/JointState.h b/libraries/animation/src/JointState.h index d7e954d59c..51f92f3ace 100644 --- a/libraries/animation/src/JointState.h +++ b/libraries/animation/src/JointState.h @@ -113,7 +113,7 @@ public: const glm::mat4& getPostTransform() const { return _postTransform; } const glm::quat& getPreRotation() const { return _preRotation; } const glm::quat& getPostRotation() const { return _postRotation; } - const glm::quat& getOriginalRotation() const { return _originalRotation; } + const glm::quat& getDefaultRotation() const { return _defaultRotation; } const glm::quat& getInverseDefaultRotation() const { return _inverseDefaultRotation; } const QString& getName() const { return _name; } float getBoneRadius() const { return _boneRadius; } @@ -136,7 +136,7 @@ private: glm::quat _visibleRotation; glm::quat _visibleRotationInConstrainedFrame; - glm::quat _originalRotation; // Not necessarilly bind rotation. See FBXJoint transform/bindTransform + glm::quat _defaultRotation; // Not necessarilly bind rotation. See FBXJoint transform/bindTransform glm::quat _inverseDefaultRotation; glm::vec3 _translation; float _boneRadius; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 1c7257adc7..207cb5e4e1 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -795,7 +795,7 @@ void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, floa glm::angleAxis(- RADIANS_PER_DEGREE * leanSideways, inverse * zAxis) * glm::angleAxis(- RADIANS_PER_DEGREE * leanForward, inverse * xAxis) * glm::angleAxis(RADIANS_PER_DEGREE * torsoTwist, inverse * yAxis) * - getJointState(index).getOriginalRotation(), DEFAULT_PRIORITY); + getJointState(index).getDefaultRotation(), DEFAULT_PRIORITY); } } @@ -816,7 +816,7 @@ void Rig::updateNeckJoint(int index, const glm::quat& localHeadOrientation, floa glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * axes[2])) * glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * axes[1])) * glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * axes[0])) * - state.getOriginalRotation(), DEFAULT_PRIORITY); + state.getDefaultRotation(), DEFAULT_PRIORITY); } } @@ -828,7 +828,7 @@ void Rig::updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const // NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual. glm::mat4 inverse = glm::inverse(parentState.getTransform() * glm::translate(getJointDefaultTranslationInConstrainedFrame(index)) * - state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getOriginalRotation())); + state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getDefaultRotation())); glm::vec3 front = glm::vec3(inverse * glm::vec4(worldHeadOrientation * IDENTITY_FRONT, 0.0f)); glm::vec3 lookAtDelta = lookAt; glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * saccade, 1.0f)); @@ -836,6 +836,6 @@ void Rig::updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; float angle = glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE); glm::quat rot = glm::angleAxis(angle, glm::axis(between)); - setJointRotationInConstrainedFrame(index, rot * state.getOriginalRotation(), DEFAULT_PRIORITY); + setJointRotationInConstrainedFrame(index, rot * state.getDefaultRotation(), DEFAULT_PRIORITY); } } From 0b4be8fca29378b465ecb026a700d45efb9d6926 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 6 Aug 2015 21:46:36 -0700 Subject: [PATCH 28/42] Improve transforms for panels and attachables. Add offsetScale to PanelAttachable for scaling all the contents of a panel properly. Also reduce the number of transform operations per second while rendering a PanelAttachable Overlay. --- examples/example/ui/overlayPanelExample.js | 30 ++++---- examples/libraries/overlayManager.js | 6 +- .../src/ui/overlays/Billboard3DOverlay.cpp | 12 ++-- .../src/ui/overlays/Billboard3DOverlay.h | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 4 +- interface/src/ui/overlays/OverlayPanel.cpp | 68 ++++++++++++------- interface/src/ui/overlays/OverlayPanel.h | 19 +++--- interface/src/ui/overlays/PanelAttachable.cpp | 68 +++++++++++-------- interface/src/ui/overlays/PanelAttachable.h | 19 ++++-- interface/src/ui/overlays/Text3DOverlay.cpp | 4 +- 10 files changed, 134 insertions(+), 98 deletions(-) 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); } From 3dcfa84a8700f0f91c61e93f70a2b88ec5f0fdee Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 7 Aug 2015 01:38:33 -0700 Subject: [PATCH 29/42] Fix billboarding behavior. Billboards now always face the camera position. Also, OverlayPanels can be set to face the avatar. --- examples/example/ui/overlayPanelExample.js | 5 +--- examples/libraries/overlayManager.js | 2 +- .../src/ui/overlays/Billboard3DOverlay.cpp | 14 +++++----- .../src/ui/overlays/Billboard3DOverlay.h | 4 +-- interface/src/ui/overlays/OverlayPanel.cpp | 28 +++++++++++++++---- interface/src/ui/overlays/OverlayPanel.h | 5 +++- 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/examples/example/ui/overlayPanelExample.js b/examples/example/ui/overlayPanelExample.js index 3a735c3e15..24372188ef 100644 --- a/examples/example/ui/overlayPanelExample.js +++ b/examples/example/ui/overlayPanelExample.js @@ -22,12 +22,9 @@ var mainPanel = new OverlayPanel({ positionBinding: { avatar: "MyAvatar" }, rotation: { w: 1, x: 0, y: 0, z: 0 }, offsetPosition: { x: 0, y: 0.4, z: 1 }, - offsetRotation: { w: 0, x: 0, y: 1, z: 0 } + isFacingAvatar: true }); -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 }, offsetScale: 0.5 diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index aee4472491..949db66c81 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -384,7 +384,7 @@ [ "position", "positionBinding", "rotation", "rotationBinding", "scale", - "offsetPosition", "offsetRotation", "offsetScale", "visible" + "offsetPosition", "offsetRotation", "offsetScale", "visible", "isFacingAvatar" ].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 282289af92..c57c6269cf 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.cpp +++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp @@ -12,11 +12,6 @@ #include "Billboard3DOverlay.h" #include "Application.h" -Billboard3DOverlay::Billboard3DOverlay() : - _isFacingAvatar(false) -{ -} - Billboard3DOverlay::Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay) : Planar3DOverlay(billboard3DOverlay), PanelAttachable(*billboard3DOverlay), @@ -50,9 +45,14 @@ void Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) { if (force || usecTimestampNow() > _transformExpiry) { PanelAttachable::applyTransformTo(transform, true); if (_isFacingAvatar) { - glm::quat rotation = Application::getInstance()->getCamera()->getOrientation(); - + glm::vec3 billboardPos = transform.getTranslation(); + glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); + glm::vec3 look = cameraPos - billboardPos; + float elevation = -asinf(look.y / glm::length(look)); + float azimuth = atan2f(look.x, look.z); + glm::quat rotation(glm::vec3(elevation, azimuth, 0)); transform.setRotation(rotation); + transform.postRotate(getOffsetRotation()); } } } diff --git a/interface/src/ui/overlays/Billboard3DOverlay.h b/interface/src/ui/overlays/Billboard3DOverlay.h index f9a5081123..124f38b94b 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.h +++ b/interface/src/ui/overlays/Billboard3DOverlay.h @@ -19,7 +19,7 @@ class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable { Q_OBJECT public: - Billboard3DOverlay(); + Billboard3DOverlay() {} Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay); bool getIsFacingAvatar() const { return _isFacingAvatar; } @@ -32,7 +32,7 @@ protected: virtual void applyTransformTo(Transform& transform, bool force = false); private: - bool _isFacingAvatar; + bool _isFacingAvatar = false; }; #endif // hifi_Billboard3DOverlay_h diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index df14e2f448..cd68b31c3f 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -86,6 +86,9 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { if (property == "visible") { return getVisible(); } + if (property == "isFacingAvatar") { + return getIsFacingAvatar(); + } if (property == "children") { QScriptValue array = _scriptEngine->newArray(_children.length()); for (int i = 0; i < _children.length(); i++) { @@ -137,11 +140,6 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { _rotationBindEntity = binding.entity; } - QScriptValue visible = properties.property("visible"); - if (visible.isValid()) { - setVisible(visible.toVariant().toBool()); - } - QScriptValue scale = properties.property("scale"); if (scale.isValid()) { if (scale.property("x").isValid() && @@ -154,6 +152,16 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { setScale(scale.toVariant().toFloat()); } } + + QScriptValue visible = properties.property("visible"); + if (visible.isValid()) { + setVisible(visible.toVariant().toBool()); + } + + QScriptValue isFacingAvatar = properties.property("isFacingAvatar"); + if (isFacingAvatar.isValid()) { + setIsFacingAvatar(isFacingAvatar.toVariant().toBool()); + } } void OverlayPanel::applyTransformTo(Transform& transform, bool force) { @@ -168,6 +176,16 @@ void OverlayPanel::applyTransformTo(Transform& transform, bool force) { transform.postRotate(getOffsetRotation()); transform.postScale(getOffsetScale()); } + if (_isFacingAvatar) { + glm::vec3 billboardPos = transform.getTranslation(); + glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); + glm::vec3 look = cameraPos - billboardPos; + float elevation = -asinf(look.y / glm::length(look)); + float azimuth = atan2f(look.x, look.z); + glm::quat rotation(glm::vec3(elevation, azimuth, 0.0f)); + transform.setRotation(rotation); + transform.postRotate(getOffsetRotation()); + } } } diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index 6e0c6c5a6a..1d6cae48cd 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -46,6 +46,7 @@ public: glm::quat getRotation() const { return _transform.getRotation(); } glm::vec3 getScale() const { return _transform.getScale(); } bool getVisible() const { return _visible; } + bool getIsFacingAvatar() const { return _isFacingAvatar; } // setters void setPosition(const glm::vec3& position) { _transform.setTranslation(position); } @@ -53,6 +54,7 @@ public: void setScale(float scale) { _transform.setScale(scale); } void setScale(const glm::vec3& scale) { _transform.setScale(scale); } void setVisible(bool visible) { _visible = visible; } + void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } const QList& getChildren() { return _children; } void addChild(unsigned int childId); @@ -75,8 +77,9 @@ private: bool _rotationBindMyAvatar = false; QUuid _rotationBindEntity; - QList _children; bool _visible = true; + bool _isFacingAvatar = false; + QList _children; QScriptEngine* _scriptEngine; }; From 3356bf31ac6c5a8c8590b313c6371a38d20a210e Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 7 Aug 2015 02:34:56 -0700 Subject: [PATCH 30/42] Refactor billboarding into Billboardable class. --- examples/libraries/overlayManager.js | 31 ++++++++------ .../src/ui/overlays/Billboard3DOverlay.cpp | 29 +++++--------- .../src/ui/overlays/Billboard3DOverlay.h | 9 +---- interface/src/ui/overlays/Billboardable.cpp | 40 +++++++++++++++++++ interface/src/ui/overlays/Billboardable.h | 35 ++++++++++++++++ interface/src/ui/overlays/OverlayPanel.cpp | 25 ++++-------- interface/src/ui/overlays/OverlayPanel.h | 6 +-- interface/src/ui/overlays/PanelAttachable.h | 2 +- 8 files changed, 115 insertions(+), 62 deletions(-) create mode 100644 interface/src/ui/overlays/Billboardable.cpp create mode 100644 interface/src/ui/overlays/Billboardable.h diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index 949db66c81..256a710c8b 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -41,14 +41,20 @@ var overlays = {}; var panels = {}; - var overlayTypes, - Overlay, + var overlayTypes; + + // Abstract overlay types + var Overlay, Overlay2D, Base3DOverlay, Planar3DOverlay, Billboard3DOverlay, Volume3DOverlay; + // Multiple inheritance mixins + var PanelAttachable, + Billboardable; + // // Create a new JavaScript object for an overlay of given ID. @@ -232,10 +238,6 @@ return that; } - // Supports multiple inheritance of properties. Just `concat` them onto the end of the - // properties list. - var PANEL_ATTACHABLE_FIELDS = ["offsetPosition", "offsetRotation", "offsetScale"]; - Overlay = (function() { var that = function(type, params) { if (type && params) { @@ -286,6 +288,11 @@ ]); })(); + // Supports multiple inheritance of properties. Just `concat` them onto the end of the + // properties list. + PanelAttachable = ["offsetPosition", "offsetRotation", "offsetScale"]; + Billboardable = ["isFacingAvatar"]; + Overlay2D = generateOverlayClass(Overlay, ABSTRACT, [ "bounds", "x", "y", "width", "height" ]); @@ -300,8 +307,7 @@ ]); Billboard3DOverlay = generateOverlayClass(Planar3DOverlay, ABSTRACT, [ - "isFacingAvatar" - ].concat(PANEL_ATTACHABLE_FIELDS)); + ].concat(PanelAttachable).concat(Billboardable)); Billboard3DOverlay.prototype.isPanelAttachable = function() { return true; }; Volume3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [ @@ -382,10 +388,11 @@ that.prototype.constructor = that; - [ - "position", "positionBinding", "rotation", "rotationBinding", "scale", - "offsetPosition", "offsetRotation", "offsetScale", "visible", "isFacingAvatar" - ].forEach(function(prop) { + var props = [ + "position", "positionBinding", "rotation", "rotationBinding", "scale", "visible" + ].concat(PanelAttachable).concat(Billboardable) + + props.forEach(function(prop) { Object.defineProperty(that.prototype, prop, { get: function() { return Overlays.getPanelProperty(this._id, prop); diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp index c57c6269cf..abb33c29e7 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.cpp +++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp @@ -15,26 +15,23 @@ Billboard3DOverlay::Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay) : Planar3DOverlay(billboard3DOverlay), PanelAttachable(*billboard3DOverlay), - _isFacingAvatar(billboard3DOverlay->_isFacingAvatar) + Billboardable(*billboard3DOverlay) { } void Billboard3DOverlay::setProperties(const QScriptValue &properties) { Planar3DOverlay::setProperties(properties); PanelAttachable::setProperties(properties); - - QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar"); - if (isFacingAvatarValue.isValid()) { - _isFacingAvatar = isFacingAvatarValue.toVariant().toBool(); - } + Billboardable::setProperties(properties); } QScriptValue Billboard3DOverlay::getProperty(const QString &property) { - if (property == "isFacingAvatar") { - return _isFacingAvatar; + QScriptValue value; + value = Billboardable::getProperty(_scriptEngine, property); + if (value.isValid()) { + return value; } - - QScriptValue value = PanelAttachable::getProperty(_scriptEngine, property); + value = PanelAttachable::getProperty(_scriptEngine, property); if (value.isValid()) { return value; } @@ -44,15 +41,7 @@ QScriptValue Billboard3DOverlay::getProperty(const QString &property) { void Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) { if (force || usecTimestampNow() > _transformExpiry) { PanelAttachable::applyTransformTo(transform, true); - if (_isFacingAvatar) { - glm::vec3 billboardPos = transform.getTranslation(); - glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); - glm::vec3 look = cameraPos - billboardPos; - float elevation = -asinf(look.y / glm::length(look)); - float azimuth = atan2f(look.x, look.z); - glm::quat rotation(glm::vec3(elevation, azimuth, 0)); - transform.setRotation(rotation); - transform.postRotate(getOffsetRotation()); - } + transformLookAtCamera(transform); + transform.postRotate(getOffsetRotation()); } } diff --git a/interface/src/ui/overlays/Billboard3DOverlay.h b/interface/src/ui/overlays/Billboard3DOverlay.h index 124f38b94b..2f5af1068f 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.h +++ b/interface/src/ui/overlays/Billboard3DOverlay.h @@ -14,25 +14,20 @@ #include "Planar3DOverlay.h" #include "PanelAttachable.h" +#include "Billboardable.h" -class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable { +class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable, public Billboardable { Q_OBJECT public: Billboard3DOverlay() {} Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay); - bool getIsFacingAvatar() const { return _isFacingAvatar; } - void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } - virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); protected: virtual void applyTransformTo(Transform& transform, bool force = false); - -private: - bool _isFacingAvatar = false; }; #endif // hifi_Billboard3DOverlay_h diff --git a/interface/src/ui/overlays/Billboardable.cpp b/interface/src/ui/overlays/Billboardable.cpp new file mode 100644 index 0000000000..cecbbf3712 --- /dev/null +++ b/interface/src/ui/overlays/Billboardable.cpp @@ -0,0 +1,40 @@ +// +// Billboardable.cpp +// interface/src/ui/overlays +// +// Created by Zander Otavka on 8/7/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Billboardable.h" + +#include + +void Billboardable::setProperties(const QScriptValue &properties) { + QScriptValue isFacingAvatar = properties.property("isFacingAvatar"); + if (isFacingAvatar.isValid()) { + setIsFacingAvatar(isFacingAvatar.toVariant().toBool()); + } +} + +QScriptValue Billboardable::getProperty(QScriptEngine* scriptEngine, const QString &property) { + if (property == "isFacingAvatar") { + return isFacingAvatar(); + } + return QScriptValue(); +} + +void Billboardable::transformLookAtCamera(Transform& transform) { + if (_isFacingAvatar) { + glm::vec3 billboardPos = transform.getTranslation(); + glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); + glm::vec3 look = cameraPos - billboardPos; + float elevation = -asinf(look.y / glm::length(look)); + float azimuth = atan2f(look.x, look.z); + glm::quat rotation(glm::vec3(elevation, azimuth, 0)); + transform.setRotation(rotation); + } +} diff --git a/interface/src/ui/overlays/Billboardable.h b/interface/src/ui/overlays/Billboardable.h new file mode 100644 index 0000000000..f63a8f48d2 --- /dev/null +++ b/interface/src/ui/overlays/Billboardable.h @@ -0,0 +1,35 @@ +// +// Billboardable.h +// interface/src/ui/overlays +// +// Created by Zander Otavka on 8/7/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_Billboardable_h +#define hifi_Billboardable_h + +#include +#include + +#include + +class Billboardable { +public: + bool isFacingAvatar() const { return _isFacingAvatar; } + void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } + +protected: + void setProperties(const QScriptValue& properties); + QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); + + void transformLookAtCamera(Transform& transform); + +private: + bool _isFacingAvatar = false; +}; + +#endif // hifi_Billboardable_h diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index cd68b31c3f..5ddfc3129e 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -86,9 +86,6 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { if (property == "visible") { return getVisible(); } - if (property == "isFacingAvatar") { - return getIsFacingAvatar(); - } if (property == "children") { QScriptValue array = _scriptEngine->newArray(_children.length()); for (int i = 0; i < _children.length(); i++) { @@ -97,11 +94,16 @@ QScriptValue OverlayPanel::getProperty(const QString &property) { return array; } + QScriptValue value = Billboardable::getProperty(_scriptEngine, property); + if (value.isValid()) { + return value; + } return PanelAttachable::getProperty(_scriptEngine, property); } void OverlayPanel::setProperties(const QScriptValue &properties) { PanelAttachable::setProperties(properties); + Billboardable::setProperties(properties); QScriptValue position = properties.property("position"); if (position.isValid() && @@ -157,11 +159,6 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { if (visible.isValid()) { setVisible(visible.toVariant().toBool()); } - - QScriptValue isFacingAvatar = properties.property("isFacingAvatar"); - if (isFacingAvatar.isValid()) { - setIsFacingAvatar(isFacingAvatar.toVariant().toBool()); - } } void OverlayPanel::applyTransformTo(Transform& transform, bool force) { @@ -176,16 +173,8 @@ void OverlayPanel::applyTransformTo(Transform& transform, bool force) { transform.postRotate(getOffsetRotation()); transform.postScale(getOffsetScale()); } - if (_isFacingAvatar) { - glm::vec3 billboardPos = transform.getTranslation(); - glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); - glm::vec3 look = cameraPos - billboardPos; - float elevation = -asinf(look.y / glm::length(look)); - float azimuth = atan2f(look.x, look.z); - glm::quat rotation(glm::vec3(elevation, azimuth, 0.0f)); - transform.setRotation(rotation); - transform.postRotate(getOffsetRotation()); - } + transformLookAtCamera(transform); + transform.postRotate(getOffsetRotation()); } } diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index 1d6cae48cd..633e4e41fd 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -20,6 +20,7 @@ #include #include "PanelAttachable.h" +#include "Billboardable.h" class PropertyBinding { public: @@ -33,7 +34,7 @@ QScriptValue propertyBindingToScriptValue(QScriptEngine* engine, const PropertyB void propertyBindingFromScriptValue(const QScriptValue& object, PropertyBinding& value); -class OverlayPanel : public QObject, public PanelAttachable { +class OverlayPanel : public QObject, public PanelAttachable, public Billboardable { Q_OBJECT public: @@ -46,7 +47,6 @@ public: glm::quat getRotation() const { return _transform.getRotation(); } glm::vec3 getScale() const { return _transform.getScale(); } bool getVisible() const { return _visible; } - bool getIsFacingAvatar() const { return _isFacingAvatar; } // setters void setPosition(const glm::vec3& position) { _transform.setTranslation(position); } @@ -54,7 +54,6 @@ public: void setScale(float scale) { _transform.setScale(scale); } void setScale(const glm::vec3& scale) { _transform.setScale(scale); } void setVisible(bool visible) { _visible = visible; } - void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } const QList& getChildren() { return _children; } void addChild(unsigned int childId); @@ -78,7 +77,6 @@ private: QUuid _rotationBindEntity; bool _visible = true; - bool _isFacingAvatar = false; QList _children; QScriptEngine* _scriptEngine; diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index 700bc2c5f1..5242450e5d 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -38,10 +38,10 @@ public: void setOffsetScale(float scale) { _offset.setScale(scale); } void setOffsetScale(const glm::vec3& scale) { _offset.setScale(scale); } +protected: QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); void setProperties(const QScriptValue& properties); -protected: virtual void applyTransformTo(Transform& transform, bool force = false); quint64 _transformExpiry = 0; From 09bb61e4d81693b397982fc8e23c0b2194562a23 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 7 Aug 2015 02:45:05 -0700 Subject: [PATCH 31/42] Add backwards compatibility for Image3DOverlays. Using "billboard" to create an Image3DOverlay is deprecated. Instead, use "image3d" or, even better, use overlayManager.js. --- interface/src/ui/overlays/Overlays.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index ab4270b615..cb235b37fb 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -138,6 +138,8 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope if (type == ImageOverlay::TYPE) { thisOverlay = std::make_shared(); + } else if (type == Image3DOverlay::TYPE || type == "billboard") { // "billboard" for backwards compatibility + thisOverlay = std::make_shared(); } else if (type == TextOverlay::TYPE) { thisOverlay = std::make_shared(); } else if (type == Text3DOverlay::TYPE) { @@ -158,8 +160,6 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay = std::make_shared(Application::getInstance()->getEntityClipboardRenderer()); } else if (type == ModelOverlay::TYPE) { thisOverlay = std::make_shared(); - } else if (type == Image3DOverlay::TYPE) { - thisOverlay = std::make_shared(); } if (thisOverlay) { From a46cc4e1c369dc33a7fd4c3c8d739ffdf9ae96cd Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 7 Aug 2015 09:30:45 -0700 Subject: [PATCH 32/42] Fix issue with offsetRotation being applied twice. --- interface/src/ui/overlays/Billboard3DOverlay.cpp | 4 +++- interface/src/ui/overlays/OverlayPanel.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp index abb33c29e7..0c28b2d4a8 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.cpp +++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp @@ -42,6 +42,8 @@ void Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) { if (force || usecTimestampNow() > _transformExpiry) { PanelAttachable::applyTransformTo(transform, true); transformLookAtCamera(transform); - transform.postRotate(getOffsetRotation()); + if (isFacingAvatar()) { + transform.postRotate(getOffsetRotation()); + } } } diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index 5ddfc3129e..4088af1ec9 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -174,7 +174,9 @@ void OverlayPanel::applyTransformTo(Transform& transform, bool force) { transform.postScale(getOffsetScale()); } transformLookAtCamera(transform); - transform.postRotate(getOffsetRotation()); + if (isFacingAvatar()) { + transform.postRotate(getOffsetRotation()); + } } } From f9630942aab85277ff7fa6c17df45d4ff34d7406 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 7 Aug 2015 09:31:21 -0700 Subject: [PATCH 33/42] Small tweaks to improve code readability. --- examples/example/ui/overlayPanelExample.js | 4 ++- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/PanelAttachable.cpp | 26 +++++++++---------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/examples/example/ui/overlayPanelExample.js b/examples/example/ui/overlayPanelExample.js index 24372188ef..5e0e49a5ce 100644 --- a/examples/example/ui/overlayPanelExample.js +++ b/examples/example/ui/overlayPanelExample.js @@ -20,8 +20,10 @@ var BLUE_SQUARE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/blue-square.svg"; var mainPanel = new OverlayPanel({ positionBinding: { avatar: "MyAvatar" }, - rotation: { w: 1, x: 0, y: 0, z: 0 }, + position: { x: 0, y: 0, z: 0 }, + rotation: { w: 0, x: 0, y: 1, z: 0 }, offsetPosition: { x: 0, y: 0.4, z: 1 }, + offsetRotation: { w: 1, x: 0, y: 0, z: 0 }, isFacingAvatar: true }); diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index efa51ca899..c13dbbb139 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -52,7 +52,7 @@ void Image3DOverlay::render(RenderArgs* args) { } Q_ASSERT(args->_batch); - auto batch = args->_batch; + gpu::Batch* batch = args->_batch; float imageWidth = _texture->getWidth(); float imageHeight = _texture->getHeight(); diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 20b06c55b2..91a7525257 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -23,19 +23,6 @@ bool PanelAttachable::getParentVisible() const { } } -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()); - } - } -} - QScriptValue PanelAttachable::getProperty(QScriptEngine* scriptEngine, const QString &property) { if (property == "offsetPosition") { return vec3toScriptValue(scriptEngine, getOffsetPosition()); @@ -84,3 +71,16 @@ void PanelAttachable::setProperties(const QScriptValue &properties) { } } } + +void PanelAttachable::applyTransformTo(Transform& transform, bool force) { + if (force || usecTimestampNow() > _transformExpiry) { + const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz + _transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD; + if (getParentPanel()) { + getParentPanel()->applyTransformTo(transform, true); + transform.postTranslate(getOffsetPosition()); + transform.postRotate(getOffsetRotation()); + transform.postScale(getOffsetScale()); + } + } +} From 8441868e74e22c3687441dcb40349437e47c07eb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 7 Aug 2015 10:32:03 -0700 Subject: [PATCH 34/42] change LOD dialog to no longer reset when you close the dialog box --- interface/src/ui/LodToolsDialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp index 378a1391f4..4d476fb649 100644 --- a/interface/src/ui/LodToolsDialog.cpp +++ b/interface/src/ui/LodToolsDialog.cpp @@ -115,6 +115,8 @@ void LodToolsDialog::reject() { void LodToolsDialog::closeEvent(QCloseEvent* event) { this->QDialog::closeEvent(event); emit closed(); + +#if RESET_TO_AUTOMATIC_WHEN_YOU_CLOSE_THE_DIALOG_BOX auto lodManager = DependencyManager::get(); // always revert back to automatic LOD adjustment when closed @@ -124,6 +126,7 @@ void LodToolsDialog::closeEvent(QCloseEvent* event) { if (lodManager->getOctreeSizeScale() > DEFAULT_OCTREE_SIZE_SCALE) { lodManager->setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE); } +#endif } From 87f609b9af5b25a1186da238f203cb7f9f312215 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 7 Aug 2015 11:26:07 -0700 Subject: [PATCH 35/42] remove shadow menu items, left in the dead code for now, until we have a plan for replacing shadows --- interface/src/Application.cpp | 10 ---------- interface/src/Application.h | 2 -- interface/src/Menu.cpp | 6 ------ interface/src/Menu.h | 2 -- .../render-utils/src/AbstractViewStateInterface.h | 3 --- libraries/render-utils/src/DeferredLightingEffect.cpp | 10 ++++++++-- 6 files changed, 8 insertions(+), 25 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 503acc2ce3..32aa0283f2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3335,16 +3335,6 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom } } -bool Application::getShadowsEnabled() { - Menu* menubar = Menu::getInstance(); - return menubar->isOptionChecked(MenuOption::SimpleShadows) || - menubar->isOptionChecked(MenuOption::CascadedShadows); -} - -bool Application::getCascadeShadowsEnabled() { - return Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows); -} - glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { float horizontalScale = _glWidget->getDeviceWidth() / 2.0f; float verticalScale = _glWidget->getDeviceHeight() / 2.0f; diff --git a/interface/src/Application.h b/interface/src/Application.h index 56c126462a..367efa9924 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -268,8 +268,6 @@ public: float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); } - virtual bool getShadowsEnabled(); - virtual bool getCascadeShadowsEnabled(); virtual QThread* getMainThread() { return thread(); } virtual float getSizeScale() const; virtual int getBoundaryLevelAdjust() const; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6fcc46478e..8a037c2d85 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -346,12 +346,6 @@ Menu::Menu() { ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight8, 0, false)); ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight9, 0, false)); - MenuWrapper* shadowMenu = renderOptionsMenu->addMenu("Shadows"); - QActionGroup* shadowGroup = new QActionGroup(shadowMenu); - shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, "None", 0, true)); - shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::SimpleShadows, 0, false)); - shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::CascadedShadows, 0, false)); - { MenuWrapper* framerateMenu = renderOptionsMenu->addMenu(MenuOption::RenderTargetFramerate); QActionGroup* framerateGroup = new QActionGroup(framerateMenu); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index bd6c982d70..89876bccb8 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -154,7 +154,6 @@ namespace MenuOption { const QString BlueSpeechSphere = "Blue Sphere While Speaking"; const QString BookmarkLocation = "Bookmark Location"; const QString Bookmarks = "Bookmarks"; - const QString CascadedShadows = "Cascaded"; const QString CachesSize = "RAM Caches Size"; const QString CalibrateCamera = "Calibrate Camera"; const QString CenterPlayerInView = "Center Player In View"; @@ -271,7 +270,6 @@ namespace MenuOption { const QString ShowIKConstraints = "Show IK Constraints"; const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats"; const QString ShowWhosLookingAtMe = "Show Who's Looking at Me"; - const QString SimpleShadows = "Simple"; const QString SixenseEnabled = "Enable Hydra Support"; const QString SixenseMouseInput = "Enable Sixense Mouse Input"; const QString Stars = "Stars"; diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 27b4fa6ede..53214b3d5b 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -47,9 +47,6 @@ public: /// gets the shadow view frustum for rendering the view state virtual ViewFrustum* getShadowViewFrustum() = 0; - virtual bool getShadowsEnabled() = 0; - virtual bool getCascadeShadowsEnabled() = 0; - virtual QThread* getMainThread() = 0; virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera) = 0; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 08ab6e0cf6..4941818bf4 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -277,13 +277,19 @@ void DeferredLightingEffect::render(RenderArgs* args) { auto& program = _directionalLight; const LightLocations* locations = &_directionalLightLocations; - bool shadowsEnabled = _viewState->getShadowsEnabled(); + + // FIXME: Note: we've removed the menu items to enable shadows, so this will always be false for now. + // When we add back shadow support, this old approach may likely be removed and completely replaced + // but I've left it in for now. + bool shadowsEnabled = false; + bool cascadeShadowsEnabled = false; + if (shadowsEnabled) { batch.setResourceTexture(4, framebufferCache->getShadowFramebuffer()->getDepthStencilBuffer()); program = _directionalLightShadowMap; locations = &_directionalLightShadowMapLocations; - if (_viewState->getCascadeShadowsEnabled()) { + if (cascadeShadowsEnabled) { program = _directionalLightCascadedShadowMap; locations = &_directionalLightCascadedShadowMapLocations; if (useSkyboxCubemap) { From 743e73874f0726839093afabcbf153746c1c7760 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 7 Aug 2015 11:38:33 -0700 Subject: [PATCH 36/42] Add back the anchor to panel transform names. position -> anchorPosition rotation -> anchorRotation scale -> anchorScale --- examples/controlPanel.js | 4 +- examples/example/ui/overlayPanelExample.js | 10 +- examples/libraries/overlayManager.js | 2 +- .../src/ui/overlays/Billboard3DOverlay.cpp | 5 +- interface/src/ui/overlays/Billboardable.cpp | 5 +- interface/src/ui/overlays/Billboardable.h | 2 +- interface/src/ui/overlays/OverlayPanel.cpp | 146 +++++++++--------- interface/src/ui/overlays/OverlayPanel.h | 26 ++-- 8 files changed, 99 insertions(+), 101 deletions(-) diff --git a/examples/controlPanel.js b/examples/controlPanel.js index 0472597692..3561bdfcb4 100644 --- a/examples/controlPanel.js +++ b/examples/controlPanel.js @@ -23,7 +23,7 @@ var FACE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/face-toggle.svg"; var ADDRESS_BAR_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/address-bar-toggle.svg"; var panel = new OverlayPanel({ - positionBinding: { avatar: "MyAvatar" }, + anchorPositionBinding: { avatar: "MyAvatar" }, offsetPosition: { x: 0, y: 0.4, z: 1 }, offsetRotation: { w: 0, x: 0, y: 1, z: 0 }, visible: false @@ -210,7 +210,7 @@ function onMouseUp(event) { if (event.isRightButton && mouseDown.maxDistance < 10) { panel.setProperties({ visible: !panel.visible, - rotation: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 }) + anchorRotation: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 }) }); } diff --git a/examples/example/ui/overlayPanelExample.js b/examples/example/ui/overlayPanelExample.js index 5e0e49a5ce..e3c66dd532 100644 --- a/examples/example/ui/overlayPanelExample.js +++ b/examples/example/ui/overlayPanelExample.js @@ -19,12 +19,12 @@ var RED_DOT_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/red-dot.svg"; var BLUE_SQUARE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/blue-square.svg"; var mainPanel = new OverlayPanel({ - positionBinding: { avatar: "MyAvatar" }, - position: { x: 0, y: 0, z: 0 }, - rotation: { w: 0, x: 0, y: 1, z: 0 }, + anchorPositionBinding: { avatar: "MyAvatar" }, + anchorPosition: { x: 0, y: 0, z: 0 }, + anchorRotation: { w: 1, x: 0, y: 0, z: 0 }, offsetPosition: { x: 0, y: 0.4, z: 1 }, - offsetRotation: { w: 1, x: 0, y: 0, z: 0 }, - isFacingAvatar: true + offsetRotation: { w: 0, x: 0, y: 1, z: 0 }, + isFacingAvatar: false }); var bluePanel = mainPanel.addChild(new OverlayPanel ({ diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index 256a710c8b..bf882c3d78 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -389,7 +389,7 @@ that.prototype.constructor = that; var props = [ - "position", "positionBinding", "rotation", "rotationBinding", "scale", "visible" + "anchorPosition", "anchorPositionBinding", "anchorRotation", "anchorRotationBinding", "anchorScale", "visible" ].concat(PanelAttachable).concat(Billboardable) props.forEach(function(prop) { diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp index 0c28b2d4a8..0b27673e18 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.cpp +++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp @@ -41,9 +41,6 @@ QScriptValue Billboard3DOverlay::getProperty(const QString &property) { void Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) { if (force || usecTimestampNow() > _transformExpiry) { PanelAttachable::applyTransformTo(transform, true); - transformLookAtCamera(transform); - if (isFacingAvatar()) { - transform.postRotate(getOffsetRotation()); - } + pointTransformAtCamera(transform, getOffsetRotation()); } } diff --git a/interface/src/ui/overlays/Billboardable.cpp b/interface/src/ui/overlays/Billboardable.cpp index cecbbf3712..c6edad501f 100644 --- a/interface/src/ui/overlays/Billboardable.cpp +++ b/interface/src/ui/overlays/Billboardable.cpp @@ -27,8 +27,8 @@ QScriptValue Billboardable::getProperty(QScriptEngine* scriptEngine, const QStri return QScriptValue(); } -void Billboardable::transformLookAtCamera(Transform& transform) { - if (_isFacingAvatar) { +void Billboardable::pointTransformAtCamera(Transform& transform, glm::quat offsetRotation) { + if (isFacingAvatar()) { glm::vec3 billboardPos = transform.getTranslation(); glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); glm::vec3 look = cameraPos - billboardPos; @@ -36,5 +36,6 @@ void Billboardable::transformLookAtCamera(Transform& transform) { float azimuth = atan2f(look.x, look.z); glm::quat rotation(glm::vec3(elevation, azimuth, 0)); transform.setRotation(rotation); + transform.postRotate(offsetRotation); } } diff --git a/interface/src/ui/overlays/Billboardable.h b/interface/src/ui/overlays/Billboardable.h index f63a8f48d2..1388f13e60 100644 --- a/interface/src/ui/overlays/Billboardable.h +++ b/interface/src/ui/overlays/Billboardable.h @@ -26,7 +26,7 @@ protected: void setProperties(const QScriptValue& properties); QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); - void transformLookAtCamera(Transform& transform); + void pointTransformAtCamera(Transform& transform, glm::quat offsetRotation = {1, 0, 0, 0}); private: bool _isFacingAvatar = false; diff --git a/interface/src/ui/overlays/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp index 4088af1ec9..db91b7e0e3 100644 --- a/interface/src/ui/overlays/OverlayPanel.cpp +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -64,24 +64,26 @@ void OverlayPanel::removeChild(unsigned int childId) { } QScriptValue OverlayPanel::getProperty(const QString &property) { - if (property == "position") { - return vec3toScriptValue(_scriptEngine, getPosition()); + if (property == "anchorPosition") { + return vec3toScriptValue(_scriptEngine, getAnchorPosition()); } - if (property == "positionBinding") { - return propertyBindingToScriptValue(_scriptEngine, PropertyBinding(_positionBindMyAvatar ? - "MyAvatar" : "", - _positionBindEntity)); + if (property == "anchorPositionBinding") { + return propertyBindingToScriptValue(_scriptEngine, + PropertyBinding(_anchorPositionBindMyAvatar ? + "MyAvatar" : "", + _anchorPositionBindEntity)); } - if (property == "rotation") { - return quatToScriptValue(_scriptEngine, getRotation()); + if (property == "anchorRotation") { + return quatToScriptValue(_scriptEngine, getAnchorRotation()); } - if (property == "rotationBinding") { - return propertyBindingToScriptValue(_scriptEngine, PropertyBinding(_rotationBindMyAvatar ? - "MyAvatar" : "", - _rotationBindEntity)); + if (property == "anchorRotationBinding") { + return propertyBindingToScriptValue(_scriptEngine, + PropertyBinding(_anchorRotationBindMyAvatar ? + "MyAvatar" : "", + _anchorRotationBindEntity)); } - if (property == "scale") { - return vec3toScriptValue(_scriptEngine, getScale()); + if (property == "anchorScale") { + return vec3toScriptValue(_scriptEngine, getAnchorScale()); } if (property == "visible") { return getVisible(); @@ -105,53 +107,53 @@ void OverlayPanel::setProperties(const QScriptValue &properties) { PanelAttachable::setProperties(properties); Billboardable::setProperties(properties); - QScriptValue position = properties.property("position"); - if (position.isValid() && - position.property("x").isValid() && - position.property("y").isValid() && - position.property("z").isValid()) { + QScriptValue anchorPosition = properties.property("anchorPosition"); + if (anchorPosition.isValid() && + anchorPosition.property("x").isValid() && + anchorPosition.property("y").isValid() && + anchorPosition.property("z").isValid()) { glm::vec3 newPosition; - vec3FromScriptValue(position, newPosition); - setPosition(newPosition); + vec3FromScriptValue(anchorPosition, newPosition); + setAnchorPosition(newPosition); } - QScriptValue positionBinding = properties.property("positionBinding"); - if (positionBinding.isValid()) { + QScriptValue anchorPositionBinding = properties.property("anchorPositionBinding"); + if (anchorPositionBinding.isValid()) { PropertyBinding binding = {}; - propertyBindingFromScriptValue(positionBinding, binding); - _positionBindMyAvatar = binding.avatar == "MyAvatar"; - _positionBindEntity = binding.entity; + propertyBindingFromScriptValue(anchorPositionBinding, binding); + _anchorPositionBindMyAvatar = binding.avatar == "MyAvatar"; + _anchorPositionBindEntity = binding.entity; } - QScriptValue rotation = properties.property("rotation"); - if (rotation.isValid() && - rotation.property("x").isValid() && - rotation.property("y").isValid() && - rotation.property("z").isValid() && - rotation.property("w").isValid()) { + QScriptValue anchorRotation = properties.property("anchorRotation"); + if (anchorRotation.isValid() && + anchorRotation.property("x").isValid() && + anchorRotation.property("y").isValid() && + anchorRotation.property("z").isValid() && + anchorRotation.property("w").isValid()) { glm::quat newRotation; - quatFromScriptValue(rotation, newRotation); - setRotation(newRotation); + quatFromScriptValue(anchorRotation, newRotation); + setAnchorRotation(newRotation); } - QScriptValue rotationBinding = properties.property("rotationBinding"); - if (rotationBinding.isValid()) { + QScriptValue anchorRotationBinding = properties.property("anchorRotationBinding"); + if (anchorRotationBinding.isValid()) { PropertyBinding binding = {}; - propertyBindingFromScriptValue(positionBinding, binding); - _rotationBindMyAvatar = binding.avatar == "MyAvatar"; - _rotationBindEntity = binding.entity; + propertyBindingFromScriptValue(anchorPositionBinding, binding); + _anchorRotationBindMyAvatar = binding.avatar == "MyAvatar"; + _anchorRotationBindEntity = binding.entity; } - QScriptValue scale = properties.property("scale"); - if (scale.isValid()) { - if (scale.property("x").isValid() && - scale.property("y").isValid() && - scale.property("z").isValid()) { + QScriptValue anchorScale = properties.property("anchorScale"); + if (anchorScale.isValid()) { + if (anchorScale.property("x").isValid() && + anchorScale.property("y").isValid() && + anchorScale.property("z").isValid()) { glm::vec3 newScale; - vec3FromScriptValue(scale, newScale); - setScale(newScale); + vec3FromScriptValue(anchorScale, newScale); + setAnchorScale(newScale); } else { - setScale(scale.toVariant().toFloat()); + setAnchorScale(anchorScale.toVariant().toFloat()); } } @@ -165,34 +167,34 @@ 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()); + if (_anchorPositionBindMyAvatar) { + transform.setTranslation(DependencyManager::get()->getMyAvatar() + ->getPosition()); + } else if (!_anchorPositionBindEntity.isNull()) { + transform.setTranslation(DependencyManager::get() + ->getEntityTree()->findEntityByID(_anchorPositionBindEntity) + ->getPosition()); + } else { + transform.setTranslation(getAnchorPosition()); + } + + if (_anchorRotationBindMyAvatar) { + transform.setRotation(DependencyManager::get()->getMyAvatar() + ->getOrientation()); + } else if (!_anchorRotationBindEntity.isNull()) { + transform.setRotation(DependencyManager::get() + ->getEntityTree()->findEntityByID(_anchorRotationBindEntity) + ->getRotation()); + } else { + transform.setRotation(getAnchorRotation()); + } + + transform.setScale(getAnchorScale()); + transform.postTranslate(getOffsetPosition()); transform.postRotate(getOffsetRotation()); transform.postScale(getOffsetScale()); } - transformLookAtCamera(transform); - if (isFacingAvatar()) { - transform.postRotate(getOffsetRotation()); - } - } -} - -void OverlayPanel::updateTransform() { - if (_positionBindMyAvatar) { - setPosition(DependencyManager::get()->getMyAvatar()->getPosition()); - } else if (!_positionBindEntity.isNull()) { - setPosition(DependencyManager::get()->getEntityTree()-> - findEntityByID(_positionBindEntity)->getPosition()); - } - - if (_rotationBindMyAvatar) { - setRotation(DependencyManager::get()->getMyAvatar()->getOrientation() * - glm::angleAxis(glm::pi(), IDENTITY_UP)); - } else if (!_rotationBindEntity.isNull()) { - setRotation(DependencyManager::get()->getEntityTree()-> - findEntityByID(_rotationBindEntity)->getRotation()); + pointTransformAtCamera(transform, getOffsetRotation()); } } diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h index 633e4e41fd..221763fe87 100644 --- a/interface/src/ui/overlays/OverlayPanel.h +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -43,16 +43,16 @@ public: void init(QScriptEngine* scriptEngine) { _scriptEngine = scriptEngine; } // getters - glm::vec3 getPosition() const { return _transform.getTranslation(); } - glm::quat getRotation() const { return _transform.getRotation(); } - glm::vec3 getScale() const { return _transform.getScale(); } + glm::vec3 getAnchorPosition() const { return _anchorTransform.getTranslation(); } + glm::quat getAnchorRotation() const { return _anchorTransform.getRotation(); } + glm::vec3 getAnchorScale() const { return _anchorTransform.getScale(); } bool getVisible() const { return _visible; } // setters - 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 setAnchorPosition(const glm::vec3& position) { _anchorTransform.setTranslation(position); } + void setAnchorRotation(const glm::quat& rotation) { _anchorTransform.setRotation(rotation); } + void setAnchorScale(float scale) { _anchorTransform.setScale(scale); } + void setAnchorScale(const glm::vec3& scale) { _anchorTransform.setScale(scale); } void setVisible(bool visible) { _visible = visible; } const QList& getChildren() { return _children; } @@ -66,15 +66,13 @@ public: virtual void applyTransformTo(Transform& transform, bool force = false); private: - void updateTransform(); + Transform _anchorTransform; - Transform _transform; + bool _anchorPositionBindMyAvatar = false; + QUuid _anchorPositionBindEntity; - bool _positionBindMyAvatar = false; - QUuid _positionBindEntity; - - bool _rotationBindMyAvatar = false; - QUuid _rotationBindEntity; + bool _anchorRotationBindMyAvatar = false; + QUuid _anchorRotationBindEntity; bool _visible = true; QList _children; From 987fb561249d8194e834cfc586c6743cc1d7d08f Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 7 Aug 2015 11:51:22 -0700 Subject: [PATCH 37/42] Simplify applied transformations in scripts. --- examples/controlPanel.js | 5 ++--- examples/example/ui/overlayPanelExample.js | 5 +---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/examples/controlPanel.js b/examples/controlPanel.js index 3561bdfcb4..76fbd49577 100644 --- a/examples/controlPanel.js +++ b/examples/controlPanel.js @@ -24,8 +24,7 @@ var ADDRESS_BAR_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/address-bar-toggl var panel = new OverlayPanel({ anchorPositionBinding: { avatar: "MyAvatar" }, - offsetPosition: { x: 0, y: 0.4, z: 1 }, - offsetRotation: { w: 0, x: 0, y: 1, z: 0 }, + offsetPosition: { x: 0, y: 0.4, z: -1 }, visible: false }); @@ -210,7 +209,7 @@ function onMouseUp(event) { if (event.isRightButton && mouseDown.maxDistance < 10) { panel.setProperties({ visible: !panel.visible, - anchorRotation: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 }) + anchorRotation: MyAvatar.orientation }); } diff --git a/examples/example/ui/overlayPanelExample.js b/examples/example/ui/overlayPanelExample.js index e3c66dd532..c27123c9ad 100644 --- a/examples/example/ui/overlayPanelExample.js +++ b/examples/example/ui/overlayPanelExample.js @@ -20,10 +20,7 @@ var BLUE_SQUARE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/blue-square.svg"; var mainPanel = new OverlayPanel({ anchorPositionBinding: { avatar: "MyAvatar" }, - anchorPosition: { x: 0, y: 0, z: 0 }, - anchorRotation: { w: 1, x: 0, y: 0, z: 0 }, - offsetPosition: { x: 0, y: 0.4, z: 1 }, - offsetRotation: { w: 0, x: 0, y: 1, z: 0 }, + offsetPosition: { x: 0, y: 0.4, z: -1 }, isFacingAvatar: false }); From 145b730f80d4f52eba5861b53d37d0dcf825f463 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 7 Aug 2015 12:27:26 -0700 Subject: [PATCH 38/42] Clean up instantiation. --- libraries/animation/src/JointState.cpp | 114 ++++++++----------------- libraries/animation/src/JointState.h | 36 ++++---- libraries/animation/src/Rig.cpp | 6 +- libraries/render-utils/src/Model.cpp | 4 +- tests/animation/src/RigTests.cpp | 61 +++++++------ 5 files changed, 85 insertions(+), 136 deletions(-) diff --git a/libraries/animation/src/JointState.cpp b/libraries/animation/src/JointState.cpp index c81aae468d..440a1c18b3 100644 --- a/libraries/animation/src/JointState.cpp +++ b/libraries/animation/src/JointState.cpp @@ -18,16 +18,14 @@ #include "JointState.h" -JointState::JointState() : - _animationPriority(0.0f), - _transformChanged(true), - _rotationIsValid(false), - _positionInParentFrame(0.0f), - _distanceToParent(0.0f), - _constraint(NULL) { +JointState::~JointState() { + if (_constraint) { + delete _constraint; + _constraint = NULL; + } } -JointState::JointState(const JointState& other) : _constraint(NULL) { +void JointState::copyState(const JointState& other) { _transformChanged = other._transformChanged; _transform = other._transform; _rotationIsValid = other._rotationIsValid; @@ -36,14 +34,18 @@ JointState::JointState(const JointState& other) : _constraint(NULL) { _positionInParentFrame = other._positionInParentFrame; _distanceToParent = other._distanceToParent; _animationPriority = other._animationPriority; + + _visibleTransform = other._visibleTransform; + _visibleRotation = extractRotation(_visibleTransform); + _visibleRotationInConstrainedFrame = other._visibleRotationInConstrainedFrame; // DO NOT copy _constraint _name = other._name; _isFree = other._isFree; _boneRadius = other._boneRadius; _parentIndex = other._parentIndex; - _translation = other._translation; _defaultRotation = other._defaultRotation; _inverseDefaultRotation = other._inverseDefaultRotation; + _translation = other._translation; _rotationMin = other._rotationMin; _rotationMax = other._rotationMax; _preRotation = other._preRotation; @@ -52,49 +54,22 @@ JointState::JointState(const JointState& other) : _constraint(NULL) { _postTransform = other._postTransform; _inverseBindRotation = other._inverseBindRotation; } - -JointState::~JointState() { - delete _constraint; - _constraint = NULL; - if (_constraint) { - delete _constraint; - _constraint = NULL; - } -} - -glm::quat JointState::getRotation() const { - if (!_rotationIsValid) { - const_cast(this)->_rotation = extractRotation(_transform); - const_cast(this)->_rotationIsValid = true; - } - - return _rotation; -} - -void JointState::setFBXJoint(const FBXJoint* joint) { - assert(joint != NULL); - _rotationInConstrainedFrame = joint->rotation; - _transformChanged = true; - _rotationIsValid = false; - - _name = joint->name; - _isFree = joint->isFree; - _boneRadius = joint->boneRadius; - _parentIndex = joint->parentIndex; - _translation = joint->translation; - _defaultRotation = joint->rotation; - _inverseDefaultRotation = joint->inverseDefaultRotation; - _rotationMin = joint->rotationMin; - _rotationMax = joint->rotationMax; - _preRotation = joint->preRotation; - _postRotation = joint->postRotation; - _preTransform = joint->preTransform; - _postTransform = joint->postTransform; - _inverseBindRotation = joint->inverseBindRotation; - if (_constraint) { - delete _constraint; - _constraint = NULL; - } +JointState::JointState(const FBXJoint& joint) { + _rotationInConstrainedFrame = joint.rotation; + _name = joint.name; + _isFree = joint.isFree; + _boneRadius = joint.boneRadius; + _parentIndex = joint.parentIndex; + _translation = joint.translation; + _defaultRotation = joint.rotation; + _inverseDefaultRotation = joint.inverseDefaultRotation; + _rotationMin = joint.rotationMin; + _rotationMax = joint.rotationMax; + _preRotation = joint.preRotation; + _postRotation = joint.postRotation; + _preTransform = joint.preTransform; + _postTransform = joint.postTransform; + _inverseBindRotation = joint.inverseBindRotation; } void JointState::buildConstraint() { @@ -109,34 +84,13 @@ void JointState::buildConstraint() { } } -void JointState::copyState(const JointState& state) { - _animationPriority = state._animationPriority; - _transformChanged = state._transformChanged; - _transform = state._transform; - _rotationIsValid = state._rotationIsValid; - _rotation = state._rotation; - _rotationInConstrainedFrame = state._rotationInConstrainedFrame; - _positionInParentFrame = state._positionInParentFrame; - _distanceToParent = state._distanceToParent; - - _visibleTransform = state._visibleTransform; - _visibleRotation = extractRotation(_visibleTransform); - _visibleRotationInConstrainedFrame = state._visibleRotationInConstrainedFrame; - // DO NOT copy _constraint - _name = state._name; - _isFree = state._isFree; - _boneRadius = state._boneRadius; - _parentIndex = state._parentIndex; - _defaultRotation = state._defaultRotation; - _inverseDefaultRotation = state._inverseDefaultRotation; - _translation = state._translation; - _rotationMin = state._rotationMin; - _rotationMax = state._rotationMax; - _preRotation = state._preRotation; - _postRotation = state._postRotation; - _preTransform = state._preTransform; - _postTransform = state._postTransform; - _inverseBindRotation = state._inverseBindRotation; +glm::quat JointState::getRotation() const { + if (!_rotationIsValid) { + const_cast(this)->_rotation = extractRotation(_transform); + const_cast(this)->_rotationIsValid = true; + } + + return _rotation; } void JointState::initTransform(const glm::mat4& parentTransform) { diff --git a/libraries/animation/src/JointState.h b/libraries/animation/src/JointState.h index 51f92f3ace..694700338d 100644 --- a/libraries/animation/src/JointState.h +++ b/libraries/animation/src/JointState.h @@ -26,15 +26,13 @@ class AngularConstraint; class JointState { public: - JointState(); - JointState(const JointState& other); + JointState() {} + JointState(const JointState& other) : _constraint(NULL) { copyState(other); } + JointState(const FBXJoint& joint); ~JointState(); - - void setFBXJoint(const FBXJoint* joint); - - void buildConstraint(); void copyState(const JointState& state); - + void buildConstraint(); + void initTransform(const glm::mat4& parentTransform); // if synchronousRotationCompute is true, then _transform is still computed synchronously, // but _rotation will be asynchronously extracted @@ -98,9 +96,7 @@ public: void slaveVisibleTransform(); - float _animationPriority; // the priority of the animation affecting this joint - - /// \return parent model-frame rotation + /// \return parent model-frame rotation // (used to keep _rotation consistent when modifying _rotationInWorldFrame directly) glm::quat computeParentRotation() const; glm::quat computeVisibleParentRotation() const; @@ -118,19 +114,24 @@ public: const QString& getName() const { return _name; } float getBoneRadius() const { return _boneRadius; } bool getIsFree() const { return _isFree; } + float getAnimationPriority() const { return _animationPriority; } + void setAnimationPriority(float priority) { _animationPriority = priority; } private: void setRotationInConstrainedFrameInternal(const glm::quat& targetRotation); /// debug helper function void loadBindRotation(); - bool _transformChanged; + bool _transformChanged {true}; + bool _rotationIsValid {false}; + glm::vec3 _positionInParentFrame {0.0f}; // only changes when the Model is scaled + float _animationPriority {0.0f}; // the priority of the animation affecting this joint + float _distanceToParent {0.0f}; + AngularConstraint* _constraint{nullptr}; // JointState owns its AngularConstraint + glm::mat4 _transform; // joint- to model-frame - bool _rotationIsValid; glm::quat _rotation; // joint- to model-frame glm::quat _rotationInConstrainedFrame; // rotation in frame where angular constraints would be applied - glm::vec3 _positionInParentFrame; // only changes when the Model is scaled - float _distanceToParent; glm::mat4 _visibleTransform; glm::quat _visibleRotation; @@ -139,8 +140,10 @@ private: glm::quat _defaultRotation; // Not necessarilly bind rotation. See FBXJoint transform/bindTransform glm::quat _inverseDefaultRotation; glm::vec3 _translation; - float _boneRadius; + QString _name; + int _parentIndex; bool _isFree; + float _boneRadius; glm::vec3 _rotationMin; glm::vec3 _rotationMax; glm::quat _preRotation; @@ -148,9 +151,6 @@ private: glm::mat4 _preTransform; glm::mat4 _postTransform; glm::quat _inverseBindRotation; - int _parentIndex; - QString _name; - AngularConstraint* _constraint; // JointState owns its AngularConstraint }; #endif // hifi_JointState_h diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 207cb5e4e1..8b6c768bbd 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -299,20 +299,20 @@ void Rig::clearJointStates() { void Rig::clearJointAnimationPriority(int index) { if (index != -1 && index < _jointStates.size()) { - _jointStates[index]._animationPriority = 0.0f; + _jointStates[index].setAnimationPriority(0.0f); } } float Rig::getJointAnimatinoPriority(int index) { if (index != -1 && index < _jointStates.size()) { - return _jointStates[index]._animationPriority; + return _jointStates[index].getAnimationPriority(); } return 0.0f; } void Rig::setJointAnimatinoPriority(int index, float newPriority) { if (index != -1 && index < _jointStates.size()) { - _jointStates[index]._animationPriority = newPriority; + _jointStates[index].setAnimationPriority(newPriority); } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index cf0fb67d8c..5aa89c4cf7 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -226,9 +226,7 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { for (int i = 0; i < geometry.joints.size(); ++i) { const FBXJoint& joint = geometry.joints[i]; // store a pointer to the FBXJoint in the JointState - JointState state; - state.setFBXJoint(&joint); - + JointState state(joint); jointStates.append(state); } return jointStates; diff --git a/tests/animation/src/RigTests.cpp b/tests/animation/src/RigTests.cpp index 79c2f3b5df..b0e0a53ee5 100644 --- a/tests/animation/src/RigTests.cpp +++ b/tests/animation/src/RigTests.cpp @@ -47,39 +47,9 @@ #include "AvatarRig.h" // We might later test Rig vs AvatarRig separately, but for now, we're concentrating on the main use case. #include "RigTests.h" -QTEST_MAIN(RigTests) - -void RigTests::initTestCase() { -//#define FROM_FILE "/Users/howardstearns/howardHiFi/Zack.fbx" -#ifdef FROM_FILE - QFile file(FROM_FILE); - QCOMPARE(file.open(QIODevice::ReadOnly), true); - FBXGeometry geometry = readFBX(file.readAll(), QVariantHash()); -#else - QUrl fbxUrl("https://s3.amazonaws.com/hifi-public/models/skeletons/Zack/Zack.fbx"); - QNetworkReply* reply = OBJReader().request(fbxUrl, false); // Just a convenience hack for synchronoud http request - auto fbxHttpCode = !reply->isFinished() ? -1 : reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - QCOMPARE(fbxHttpCode, 200); - FBXGeometry geometry = readFBX(reply->readAll(), QVariantHash()); -#endif - - QVector jointStates; - for (int i = 0; i < geometry.joints.size(); ++i) { - // Note that if the geometry is stack allocated and goes away, so will the joints. Hence the heap copy here. - FBXJoint* joint = new FBXJoint(geometry.joints[i]); - JointState state; - state.setFBXJoint(joint); - jointStates.append(state); - } - - _rig = std::make_shared(); - _rig->initJointStates(jointStates, glm::mat4()); - std::cout << "Rig is ready " << geometry.joints.count() << " joints " << std::endl; - } - static void reportJoint(int index, JointState joint) { // Handy for debugging std::cout << "\n"; - std::cout << index << " " << joint.getName.toUtf8().data() << "\n"; + std::cout << index << " " << joint.getName().toUtf8().data() << "\n"; std::cout << " pos:" << joint.getPosition() << "/" << joint.getPositionInParentFrame() << " from " << joint.getParentIndex() << "\n"; std::cout << " rot:" << safeEulerAngles(joint.getRotation()) << "/" << safeEulerAngles(joint.getRotationInParentFrame()) << "/" << safeEulerAngles(joint.getRotationInBindFrame()) << "\n"; std::cout << "\n"; @@ -101,7 +71,34 @@ static void reportSome(RigPointer rig) { } } +QTEST_MAIN(RigTests) + +void RigTests::initTestCase() { +//#define FROM_FILE "/Users/howardstearns/howardHiFi/Zack.fbx" +#ifdef FROM_FILE + QFile file(FROM_FILE); + QCOMPARE(file.open(QIODevice::ReadOnly), true); + FBXGeometry geometry = readFBX(file.readAll(), QVariantHash()); +#else + QUrl fbxUrl("https://s3.amazonaws.com/hifi-public/models/skeletons/Zack/Zack.fbx"); + QNetworkReply* reply = OBJReader().request(fbxUrl, false); // Just a convenience hack for synchronoud http request + auto fbxHttpCode = !reply->isFinished() ? -1 : reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(fbxHttpCode, 200); + FBXGeometry geometry = readFBX(reply->readAll(), QVariantHash()); +#endif + + QVector jointStates; + for (int i = 0; i < geometry.joints.size(); ++i) { + JointState state(geometry.joints[i]); + jointStates.append(state); + } + + _rig = std::make_shared(); + _rig->initJointStates(jointStates, glm::mat4(), 0, 41, 40, 39, 17, 16, 15); // FIXME? get by name? do we really want to exclude the shoulder blades? + std::cout << "Rig is ready " << geometry.joints.count() << " joints " << std::endl; + reportAll(_rig); + } + void RigTests::initialPoseArmsDown() { - //reportAll(_rig); reportSome(_rig); } From f4c3c30f6a70a49323370860754daca2a451f59e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 7 Aug 2015 12:49:48 -0700 Subject: [PATCH 39/42] quick optimization to RenderableModelEntityItem::render() --- .../src/RenderableModelEntityItem.cpp | 16 +++++++++++----- libraries/render-utils/src/Model.cpp | 15 +++++++-------- libraries/render-utils/src/Model.h | 2 ++ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 1576007263..e6441a5386 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -227,24 +227,30 @@ void RenderableModelEntityItem::render(RenderArgs* args) { if (hasModel()) { if (_model) { - if (QUrl(getModelURL()) != _model->getURL()) { + if (getModelURL() != _model->getURLAsString()) { qDebug() << "Updating model URL: " << getModelURL(); _model->setURL(getModelURL()); } + render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); + // check to see if when we added our models to the scene they were ready, if they were not ready, then // fix them up in the scene - render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - render::PendingChanges pendingChanges; if (_model->needsFixupInScene()) { + render::PendingChanges pendingChanges; + _model->removeFromScene(scene, pendingChanges); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(this, statusGetters); _model->addToScene(scene, pendingChanges, statusGetters); - } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueuePendingChanges(pendingChanges); + } + + // FIXME: this seems like it could be optimized if we tracked our last known visible state in + // the renderable item. As it stands now the model checks it's visible/invisible state + // so most of the time we don't do anything in this function. _model->setVisibleInScene(getVisible(), scene); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 8839a5b463..04f72debd7 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -54,6 +54,7 @@ static int modelPointerTypeId = qRegisterMetaType >(); static int weakNetworkGeometryPointerTypeId = qRegisterMetaType >(); static int vec3VectorTypeId = qRegisterMetaType >(); float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; +#define HTTP_INVALID_COM "http://invalid.com" Model::Model(RigPointer rig, QObject* parent) : QObject(parent), @@ -67,7 +68,8 @@ Model::Model(RigPointer rig, QObject* parent) : _cauterizeBones(false), _lodDistance(0.0f), _pupilDilation(0.0f), - _url("http://invalid.com"), + _url(HTTP_INVALID_COM), + _urlAsString(HTTP_INVALID_COM), _isVisible(true), _blendNumber(0), _appliedBlendNumber(0), @@ -181,17 +183,12 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model: locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); - locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); - locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); - locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); - locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices"); - locations.clusterIndices = program->getInputs().findLocation("inSkinClusterIndex"); locations.clusterWeights = program->getInputs().findLocation("inSkinClusterWeight"); } @@ -1085,6 +1082,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo invalidCalculatedMeshBoxes(); _url = url; + _urlAsString = _url.toString(); onInvalidate(); @@ -1868,8 +1866,9 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f batch._glUniform1f(locations->glowIntensity, DEFAULT_GLOW_INTENSITY); } - if ((locations->normalFittingMapUnit > -1)) { - batch.setResourceTexture(locations->normalFittingMapUnit, DependencyManager::get()->getNormalFittingTexture()); + if ((locations->normalFittingMapUnit > -1)) { + batch.setResourceTexture(locations->normalFittingMapUnit, + DependencyManager::get()->getNormalFittingTexture()); } } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 9fdb2f3691..c9b63b598e 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -74,6 +74,7 @@ public: Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl(), bool retainCurrent = false, bool delayLoad = false); const QUrl& getURL() const { return _url; } + const QString& getURLAsString() const { return _urlAsString; } // new Scene/Engine rendering support void setVisibleInScene(bool newValue, std::shared_ptr scene); @@ -328,6 +329,7 @@ private: QVector _blendshapeCoefficients; QUrl _url; + QString _urlAsString; QUrl _collisionUrl; bool _isVisible; From cec0f8ed1da5e2884da5494510b03a7d02b2d41a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 7 Aug 2015 13:43:57 -0700 Subject: [PATCH 40/42] optimize ModelEntityItem::getAnimationFrame() --- libraries/animation/src/AnimationCache.cpp | 4 +++ libraries/animation/src/AnimationCache.h | 2 ++ .../src/RenderableModelEntityItem.cpp | 2 +- libraries/entities/src/ModelEntityItem.cpp | 31 ++++++++++++------- libraries/entities/src/ModelEntityItem.h | 5 ++- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index d1c4408178..634e0589b7 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -91,6 +91,10 @@ QVector Animation::getFrames() const { return _geometry.animationFrames; } +const QVector& Animation::getFramesReference() const { + return _geometry.animationFrames; +} + void Animation::setGeometry(const FBXGeometry& geometry) { _geometry = geometry; finishedLoading(true); diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 840d7a0355..6a0a77f659 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -57,6 +57,8 @@ public: Q_INVOKABLE QStringList getJointNames() const; Q_INVOKABLE QVector getFrames() const; + + const QVector& getFramesReference() const; protected: diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e6441a5386..6d2ff30d4b 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -275,7 +275,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } if (jointsMapped()) { - QVector frameData = getAnimationFrame(); + auto frameData = getAnimationFrame(); for (int i = 0; i < frameData.size(); i++) { _model->setJointState(i, true, frameData[i]); } diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index b0e7dcd022..362f5dc72a 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -39,6 +39,7 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityI setProperties(properties); _lastAnimated = usecTimestampNow(); _jointMappingCompleted = false; + _lastKnownFrameIndex = -1; _color[0] = _color[1] = _color[2] = 0; } @@ -217,15 +218,17 @@ void ModelEntityItem::mapJoints(const QStringList& modelJointNames) { } } -QVector ModelEntityItem::getAnimationFrame() { - QVector frameData; +const QVector& ModelEntityItem::getAnimationFrame() { + if (!hasAnimation() || !_jointMappingCompleted) { - return frameData; + return _lastKnownFrameData; } - AnimationPointer myAnimation = getAnimation(_animationURL); + AnimationPointer myAnimation = getAnimation(_animationURL); // FIXME: this could be optimized if (myAnimation && myAnimation->isLoaded()) { - QVector frames = myAnimation->getFrames(); + + const QVector& frames = myAnimation->getFramesReference(); // NOTE: getFrames() is too heavy + int frameCount = frames.size(); if (frameCount > 0) { int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount; @@ -233,18 +236,22 @@ QVector ModelEntityItem::getAnimationFrame() { animationFrameIndex = 0; } - QVector rotations = frames[animationFrameIndex].rotations; + if (animationFrameIndex != _lastKnownFrameIndex) { + _lastKnownFrameIndex = animationFrameIndex; + + const QVector& rotations = frames[animationFrameIndex].rotations; - frameData.resize(_jointMapping.size()); - for (int j = 0; j < _jointMapping.size(); j++) { - int rotationIndex = _jointMapping[j]; - if (rotationIndex != -1 && rotationIndex < rotations.size()) { - frameData[j] = rotations[rotationIndex]; + _lastKnownFrameData.resize(_jointMapping.size()); + for (int j = 0; j < _jointMapping.size(); j++) { + int rotationIndex = _jointMapping[j]; + if (rotationIndex != -1 && rotationIndex < rotations.size()) { + _lastKnownFrameData[j] = rotations[rotationIndex]; + } } } } } - return frameData; + return _lastKnownFrameData; } bool ModelEntityItem::isAnimatingSomething() const { diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index ae6a86cde1..e3d42e6b2c 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -106,7 +106,7 @@ public: float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } void mapJoints(const QStringList& modelJointNames); - QVector getAnimationFrame(); + const QVector& getAnimationFrame(); bool jointsMapped() const { return _jointMappingCompleted; } bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); } @@ -123,6 +123,9 @@ public: static void cleanupLoadedAnimations(); protected: + QVector _lastKnownFrameData; + int _lastKnownFrameIndex; + bool isAnimatingSomething() const; From 3995c4476d498d44607224b8382b29f059488497 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 7 Aug 2015 14:38:43 -0700 Subject: [PATCH 41/42] Add temporary debug info for tracking down invalid scale value assert --- interface/src/avatar/Avatar.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index b25eaa4030..a5388208c6 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -717,6 +717,29 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, floa // Compute correct scale to apply float scale = DESIRED_HIGHT_ON_SCREEN / (fontSize * pixelHeight) * devicePixelRatio; +#ifdef DEBUG + // TODO: Temporary logging to track cause of invalid scale vale; remove once cause has been fixed. + if (scale == 0.0f || glm::isnan(scale) || glm::isinf(scale)) { + if (scale == 0.0f) { + qDebug() << "ASSERT because scale == 0.0f"; + } + if (glm::isnan(scale)) { + qDebug() << "ASSERT because isnan(scale)"; + } + if (glm::isinf(scale)) { + qDebug() << "ASSERT because isinf(scale)"; + } + qDebug() << "windowSizeY =" << windowSizeY; + qDebug() << "p1.y =" << p1.y; + qDebug() << "p1.w =" << p1.w; + qDebug() << "p0.y =" << p0.y; + qDebug() << "p0.w =" << p0.w; + qDebug() << "qApp->getDevicePixelRatio() =" << qApp->getDevicePixelRatio(); + qDebug() << "fontSize =" << fontSize; + qDebug() << "pixelHeight =" << pixelHeight; + qDebug() << "devicePixelRatio =" << devicePixelRatio; + } +#endif // Compute pixel alignment offset float clipToPix = 0.5f * windowSizeY / p1.w; // Got from clip to pixel coordinates From d5691b1196a392db1fb4c960379700b8097e01f2 Mon Sep 17 00:00:00 2001 From: Bennett Goble Date: Sat, 8 Aug 2015 17:15:57 -0400 Subject: [PATCH 42/42] Add QDataStream include to DomainServerWebSessionData.cpp Fixes compilation error with Qt 5.5.0, QDataStream >> QSet --- domain-server/src/DomainServerWebSessionData.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/domain-server/src/DomainServerWebSessionData.cpp b/domain-server/src/DomainServerWebSessionData.cpp index 0a921d65c3..3744af77f3 100644 --- a/domain-server/src/DomainServerWebSessionData.cpp +++ b/domain-server/src/DomainServerWebSessionData.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include #include