From dc68e12963326329d3fbf03fa69110ba59baa64a Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 12 Aug 2015 22:01:24 -0700 Subject: [PATCH 1/2] Improve documentation for overlay changes. --- examples/libraries/overlayManager.js | 32 ++++++++++++++----- interface/src/ui/overlays/Overlays.h | 19 +++++------ interface/src/ui/overlays/PanelAttachable.cpp | 2 +- interface/src/ui/overlays/PanelAttachable.h | 20 ++++++++++++ 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index bf882c3d78..cf4df04747 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -5,6 +5,9 @@ // Created by Zander Otavka on 7/24/15 // Copyright 2015 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 +// // Manage overlays with object oriented goodness, instead of ugly `Overlays.h` methods. // Instead of: // @@ -22,14 +25,27 @@ // ... // billboard.destroy(); // -// See more on usage below. +// More on usage below. Examples in `examples/example/overlayPanelExample.js`. // -// Note that including this file will delete Overlays from the global scope. All the -// functionality of Overlays is represented here, just better. If you try to use Overlays in -// tandem, there may be performance problems or nasty surprises. +// Note that including this file will delete `Overlays` from the global scope. All the +// functionality of `Overlays` is represented here, just better. If you try to use `Overlays` +// in tandem, there may be performance problems or nasty surprises. // -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// Names added to the global scope: +// OverlayManager +// ImageOverlay +// Image3DOverlay +// TextOverlay +// Text3DOverlay +// Cube3DOverlay +// Sphere3DOverlay +// Circle3DOverlay +// Rectangle3DOverlay +// Line3DOverlay +// Grid3DOverlay +// LocalModelsOverlay +// ModelOverlay +// OverlayPanel // @@ -197,8 +213,8 @@ // billboard.destroy(); // // // Remember, there is a poor orphaned JavaScript object left behind. You should - // // remove any references to it so you don't accidentally try to modify an overlay that - // // isn't there. + // // remove any references to it so you don't accidentally try to modify an overlay + // // that isn't there. // billboard = undefined; // (function() { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 212b7b227d..bb4d94cdab 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -5,14 +5,15 @@ // Modified by Zander Otavka on 7/15/15 // Copyright 2014 High Fidelity, Inc. // -// 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`. -// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// Exposes methods to scripts for managing `Overlay`s and `OverlayPanel`s. +// +// YOU SHOULD NOT USE `Overlays` DIRECTLY, unless you like pain and deprecation. Instead, use +// the object oriented API replacement found in `examples/libraries/overlayManager.js`. See +// that file for docs and usage. +// #ifndef hifi_Overlays_h #define hifi_Overlays_h @@ -57,11 +58,11 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R class Overlays : public QObject { Q_OBJECT - + public: Overlays(); ~Overlays(); - + void init(); void update(float deltatime); void renderHUD(RenderArgs* renderArgs); @@ -103,7 +104,7 @@ public slots: /// returns details about the closest 3D Overlay hit by the pick ray RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray); - + /// returns whether the overlay's assets are loaded or not bool isLoaded(unsigned int id); @@ -153,5 +154,5 @@ private: }; - + #endif // hifi_Overlays_h diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index 91a7525257..da3a37db45 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -1,6 +1,6 @@ // // PanelAttachable.cpp -// hifi +// interface/src/ui/overlays // // Created by Zander Otavka on 7/15/15. // Copyright 2015 High Fidelity, Inc. diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index 5242450e5d..f4e982f8e9 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -8,6 +8,24 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// Base class for anything that can attach itself to an `OverlayPanel` as a child. +// `PanelAttachable keeps an `std::shared_ptr` to it's parent panel, and sets its +// transformations and visibility based on the parent. +// +// When subclassing `PanelAttachable`, make sure `applyTransformTo`, `getProperty`, and +// `setProperties are all called in the appropriate places. Look through `Image3DOverlay` and +// `Billboard3DOverlay` for examples. Pay special attention to `applyTransformTo`; it should +// be called in three places for `Overlay`s: `render`, `update`, and `findRayIntersection`. +// +// When overriding `applyTransformTo`, make sure to wrap all of your code, including the call +// to the superclass method, with the following `if` block. Then call the superclass method +// with force = true. +// +// if (force || usecTimestampNow() > _transformExpiry) { +// PanelAttachable::applyTransformTo(transform, true); +// ... +// } +// #ifndef hifi_PanelAttachable_h #define hifi_PanelAttachable_h @@ -42,6 +60,8 @@ protected: QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); void setProperties(const QScriptValue& properties); + /// set position, rotation and scale on transform based on offsets, and parent panel offsets + /// if force is false, only apply transform if it hasn't been applied in the last .1 seconds virtual void applyTransformTo(Transform& transform, bool force = false); quint64 _transformExpiry = 0; From b84b8b6119abbcf363c65d33df2f7bf547e152ae Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 12 Aug 2015 23:30:07 -0700 Subject: [PATCH 2/2] Restructure overlayManager.js to be more readable. --- examples/libraries/overlayManager.js | 426 +++++++++++---------------- 1 file changed, 172 insertions(+), 254 deletions(-) diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index cf4df04747..0623721375 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -31,46 +31,53 @@ // functionality of `Overlays` is represented here, just better. If you try to use `Overlays` // in tandem, there may be performance problems or nasty surprises. // -// Names added to the global scope: -// OverlayManager -// ImageOverlay -// Image3DOverlay -// TextOverlay -// Text3DOverlay -// Cube3DOverlay -// Sphere3DOverlay -// Circle3DOverlay -// Rectangle3DOverlay -// Line3DOverlay -// Grid3DOverlay -// LocalModelsOverlay -// ModelOverlay -// OverlayPanel -// - (function() { // Delete `Overlays` from the global scope. var Overlays = this.Overlays; delete this.Overlays; + + var ABSTRACT = null; + var overlays = {}; var panels = {}; - var overlayTypes; + var overlayTypes = {}; - // Abstract overlay types - var Overlay, - Overlay2D, - Base3DOverlay, - Planar3DOverlay, - Billboard3DOverlay, - Volume3DOverlay; - // Multiple inheritance mixins - var PanelAttachable, - Billboardable; + function generateOverlayClass(superclass, type, properties) { + var that; + if (type == ABSTRACT) { + that = function(type, params) { + superclass.call(this, type, params); + }; + } else { + that = function(params) { + superclass.call(this, type, params); + }; + overlayTypes[type] = that; + } + that.prototype = new superclass(); + that.prototype.constructor = that; + + properties.forEach(function(prop) { + Object.defineProperty(that.prototype, prop, { + get: function() { + return Overlays.getProperty(this._id, prop); + }, + set: function(newValue) { + var keyValuePair = {}; + keyValuePair[prop] = newValue; + this.setProperties(keyValuePair); + }, + configurable: false + }); + }); + + return that; + } // // Create a new JavaScript object for an overlay of given ID. @@ -153,249 +160,131 @@ } - // - // Perform global scoped operations on overlays, such as finding by ray intersection. - // - OverlayManager = { - findOnRay: function(pickRay, knownOverlaysOnly, searchList) { - var rayPickResult = Overlays.findRayIntersection(pickRay); - if (rayPickResult.intersects) { - return findOverlay(rayPickResult.overlayID, knownOverlaysOnly, searchList); - } - return null; - }, - findAtPoint: function(point, knownOverlaysOnly, searchList) { - var foundID = Overlays.getOverlayAtPoint(point); - if (foundID) { - return findOverlay(foundID, knownOverlaysOnly, searchList); + var Overlay = (function() { + var that = function(type, params) { + if (type && params) { + this._id = Overlays.addOverlay(type, params); + overlays[this._id] = this; } else { - var pickRay = Camera.computePickRay(point.x, point.y); - return OverlayManager.findOnRay(pickRay, knownOverlaysOnly, searchList); + this._id = 0; } - }, - makeSearchList: function(array) { - var searchList = {}; - array.forEach(function(object) { - searchList[object._id] = object; - }); - return searchList; - } - }; + }; + that.prototype.constructor = that; - // - // Object oriented abstraction layer for overlays. - // - // Usage: - // // Create an overlay - // var billboard = new Image3DOverlay({ - // visible: true, - // isFacingAvatar: true, - // ignoreRayIntersections: false - // }); - // - // // Get a property - // var isVisible = billboard.visible; - // - // // Set a single property - // billboard.position = { x: 1, y: 3, z: 2 }; - // - // // Set multiple properties at the same time - // billboard.setProperties({ - // url: "http://images.com/overlayImage.jpg", - // dimensions: { x: 2, y: 2 } - // }); - // - // // Clone an overlay - // var clonedBillboard = billboard.clone(); - // - // // Remove an overlay from the world - // billboard.destroy(); - // - // // Remember, there is a poor orphaned JavaScript object left behind. You should - // // remove any references to it so you don't accidentally try to modify an overlay - // // that isn't there. - // billboard = undefined; - // - (function() { - var ABSTRACT = null; - overlayTypes = {}; - - function generateOverlayClass(superclass, type, properties) { - var that; - if (type == ABSTRACT) { - that = function(type, params) { - superclass.call(this, type, params); - }; - } else { - that = function(params) { - superclass.call(this, type, params); - }; - overlayTypes[type] = that; + Object.defineProperty(that.prototype, "isLoaded", { + get: function() { + return Overlays.isLoaded(this._id); } + }); - that.prototype = new superclass(); - that.prototype.constructor = that; + Object.defineProperty(that.prototype, "parentPanel", { + get: function() { + return findPanel(Overlays.getParentPanel(this._id)); + } + }); - properties.forEach(function(prop) { - Object.defineProperty(that.prototype, prop, { - get: function() { - return Overlays.getProperty(this._id, prop); - }, - set: function(newValue) { - var keyValuePair = {}; - keyValuePair[prop] = newValue; - this.setProperties(keyValuePair); - }, - configurable: false - }); - }); + that.prototype.getTextSize = function(text) { + return Overlays.textSize(this._id, text); + }; - return that; - } + that.prototype.setProperties = function(properties) { + Overlays.editOverlay(this._id, properties); + }; - Overlay = (function() { - var that = function(type, params) { - if (type && params) { - this._id = Overlays.addOverlay(type, params); - overlays[this._id] = this; - } else { - this._id = 0; - } - }; + that.prototype.clone = function() { + return makeOverlayFromId(Overlays.cloneOverlay(this._id)); + }; - that.prototype.constructor = that; + that.prototype.destroy = function() { + Overlays.deleteOverlay(this._id); + }; - Object.defineProperty(that.prototype, "isLoaded", { - get: function() { - return Overlays.isLoaded(this._id); - } - }); + that.prototype.isPanelAttachable = function() { + return false; + }; - Object.defineProperty(that.prototype, "parentPanel", { - get: function() { - return findPanel(Overlays.getParentPanel(this._id)); - } - }); - - that.prototype.getTextSize = function(text) { - return Overlays.textSize(this._id, text); - }; - - that.prototype.setProperties = function(properties) { - Overlays.editOverlay(this._id, properties); - }; - - that.prototype.clone = function() { - return makeOverlayFromId(Overlays.cloneOverlay(this._id)); - }; - - that.prototype.destroy = function() { - Overlays.deleteOverlay(this._id); - }; - - that.prototype.isPanelAttachable = function() { - return false; - }; - - return generateOverlayClass(that, ABSTRACT, [ - "alpha", "glowLevel", "pulseMax", "pulseMin", "pulsePeriod", "glowLevelPulse", - "alphaPulse", "colorPulse", "visible", "anchor" - ]); - })(); - - // 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" - ]); - - Base3DOverlay = generateOverlayClass(Overlay, ABSTRACT, [ - "position", "lineWidth", "rotation", "isSolid", "isFilled", "isWire", "isDashedLine", - "ignoreRayIntersection", "drawInFront", "drawOnHUD" - ]); - - Planar3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [ - "dimensions" - ]); - - Billboard3DOverlay = generateOverlayClass(Planar3DOverlay, ABSTRACT, [ - ].concat(PanelAttachable).concat(Billboardable)); - Billboard3DOverlay.prototype.isPanelAttachable = function() { return true; }; - - Volume3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [ - "dimensions" - ]); - - generateOverlayClass(Overlay2D, "image", [ - "subImage", "imageURL" - ]); - - generateOverlayClass(Billboard3DOverlay, "image3d", [ - "url", "subImage" - ]); - - generateOverlayClass(Overlay2D, "text", [ - "font", "text", "backgroundColor", "backgroundAlpha", "leftMargin", "topMargin" - ]); - - generateOverlayClass(Billboard3DOverlay, "text3d", [ - "text", "backgroundColor", "backgroundAlpha", "lineHeight", "leftMargin", "topMargin", - "rightMargin", "bottomMargin" - ]); - - generateOverlayClass(Volume3DOverlay, "cube", [ - "borderSize" - ]); - - generateOverlayClass(Volume3DOverlay, "sphere", [ - ]); - - generateOverlayClass(Planar3DOverlay, "circle3d", [ - "startAt", "endAt", "outerRadius", "innerRadius", "hasTickMarks", - "majorTickMarksAngle", "minorTickMarksAngle", "majorTickMarksLength", - "minorTickMarksLength", "majorTickMarksColor", "minorTickMarksColor" - ]); - - generateOverlayClass(Planar3DOverlay, "rectangle3d", [ - ]); - - generateOverlayClass(Base3DOverlay, "line3d", [ - "start", "end" - ]); - - generateOverlayClass(Planar3DOverlay, "grid", [ - "minorGridWidth", "majorGridEvery" - ]); - - generateOverlayClass(Volume3DOverlay, "localmodels", [ - ]); - - generateOverlayClass(Volume3DOverlay, "model", [ - "url", "dimensions", "textures" + return generateOverlayClass(that, ABSTRACT, [ + "alpha", "glowLevel", "pulseMax", "pulseMin", "pulsePeriod", "glowLevelPulse", + "alphaPulse", "colorPulse", "visible", "anchor" ]); })(); - ImageOverlay = overlayTypes["image"]; - Image3DOverlay = overlayTypes["image3d"]; - TextOverlay = overlayTypes["text"]; - Text3DOverlay = overlayTypes["text3d"]; - Cube3DOverlay = overlayTypes["cube"]; - Sphere3DOverlay = overlayTypes["sphere"]; - Circle3DOverlay = overlayTypes["circle3d"]; - Rectangle3DOverlay = overlayTypes["rectangle3d"]; - Line3DOverlay = overlayTypes["line3d"]; - Grid3DOverlay = overlayTypes["grid"]; - LocalModelsOverlay = overlayTypes["localmodels"]; - ModelOverlay = overlayTypes["model"]; + // Supports multiple inheritance of properties. Just `concat` them onto the end of the + // properties list. + var PanelAttachable = ["offsetPosition", "offsetRotation", "offsetScale"]; + var Billboardable = ["isFacingAvatar"]; + + var Overlay2D = generateOverlayClass(Overlay, ABSTRACT, [ + "bounds", "x", "y", "width", "height" + ]); + + var Base3DOverlay = generateOverlayClass(Overlay, ABSTRACT, [ + "position", "lineWidth", "rotation", "isSolid", "isFilled", "isWire", "isDashedLine", + "ignoreRayIntersection", "drawInFront", "drawOnHUD" + ]); + + var Planar3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [ + "dimensions" + ]); + + var Billboard3DOverlay = generateOverlayClass(Planar3DOverlay, ABSTRACT, [ + ].concat(PanelAttachable).concat(Billboardable)); + Billboard3DOverlay.prototype.isPanelAttachable = function() { return true; }; + + var Volume3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [ + "dimensions" + ]); + + ImageOverlay = generateOverlayClass(Overlay2D, "image", [ + "subImage", "imageURL" + ]); + + Image3DOverlay = generateOverlayClass(Billboard3DOverlay, "image3d", [ + "url", "subImage" + ]); + + TextOverlay = generateOverlayClass(Overlay2D, "text", [ + "font", "text", "backgroundColor", "backgroundAlpha", "leftMargin", "topMargin" + ]); + + Text3DOverlay = generateOverlayClass(Billboard3DOverlay, "text3d", [ + "text", "backgroundColor", "backgroundAlpha", "lineHeight", "leftMargin", "topMargin", + "rightMargin", "bottomMargin" + ]); + + Cube3DOverlay = generateOverlayClass(Volume3DOverlay, "cube", [ + "borderSize" + ]); + + Sphere3DOverlay = generateOverlayClass(Volume3DOverlay, "sphere", [ + ]); + + Circle3DOverlay = generateOverlayClass(Planar3DOverlay, "circle3d", [ + "startAt", "endAt", "outerRadius", "innerRadius", "hasTickMarks", + "majorTickMarksAngle", "minorTickMarksAngle", "majorTickMarksLength", + "minorTickMarksLength", "majorTickMarksColor", "minorTickMarksColor" + ]); + + Rectangle3DOverlay = generateOverlayClass(Planar3DOverlay, "rectangle3d", [ + ]); + + Line3DOverlay = generateOverlayClass(Base3DOverlay, "line3d", [ + "start", "end" + ]); + + Grid3DOverlay = generateOverlayClass(Planar3DOverlay, "grid", [ + "minorGridWidth", "majorGridEvery" + ]); + + LocalModelsOverlay = generateOverlayClass(Volume3DOverlay, "localmodels", [ + ]); + + ModelOverlay = generateOverlayClass(Volume3DOverlay, "model", [ + "url", "dimensions", "textures" + ]); - // - // Object oriented abstraction layer for panels. - // OverlayPanel = (function() { var that = function(params) { this._id = Overlays.addPanel(params); @@ -471,6 +360,35 @@ })(); + OverlayManager = { + findOnRay: function(pickRay, knownOverlaysOnly, searchList) { + var rayPickResult = Overlays.findRayIntersection(pickRay); + if (rayPickResult.intersects) { + return findOverlay(rayPickResult.overlayID, knownOverlaysOnly, searchList); + } + return null; + }, + findAtPoint: function(point, knownOverlaysOnly, searchList) { + var foundID = Overlays.getOverlayAtPoint(point); + if (foundID) { + return findOverlay(foundID, knownOverlaysOnly, searchList); + } else { + var pickRay = Camera.computePickRay(point.x, point.y); + return OverlayManager.findOnRay(pickRay, knownOverlaysOnly, searchList); + } + }, + makeSearchList: function(array) { + var searchList = {}; + array.forEach(function(object) { + searchList[object._id] = object; + }); + return searchList; + } + }; + + + // Threadsafe cleanup of JavaScript objects. + function onOverlayDeleted(id) { if (id in overlays) { if (overlays[id].parentPanel) {