diff --git a/examples/controlPanel.js b/examples/controlPanel.js index 59d66fdaf9..76fbd49577 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,14 +22,13 @@ 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({ - anchorPosition: { - bind: "myAvatar" - }, - offsetPosition: { x: 0, y: 0.4, z: 1 } +var panel = new OverlayPanel({ + anchorPositionBinding: { avatar: "MyAvatar" }, + offsetPosition: { x: 0, y: 0.4, z: -1 }, + visible: false }); -var background = new BillboardOverlay({ +var background = new Image3DOverlay({ url: BG_IMAGE_URL, dimensions: { x: 0.5, @@ -37,11 +36,12 @@ var background = new BillboardOverlay({ }, isFacingAvatar: false, alpha: 1.0, - ignoreRayIntersection: false + ignoreRayIntersection: false, + visible: false }); panel.addChild(background); -var closeButton = new BillboardOverlay({ +var closeButton = new Image3DOverlay({ url: CLOSE_IMAGE_URL, dimensions: { x: 0.15, @@ -51,17 +51,18 @@ 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 + }, + visible: false }); closeButton.onClick = function(event) { panel.visible = false; }; panel.addChild(closeButton); -var micMuteButton = new BillboardOverlay({ +var micMuteButton = new Image3DOverlay({ url: MIC_IMAGE_URL, subImage: { x: 0, @@ -77,17 +78,18 @@ 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 + }, + visible: false }); micMuteButton.onClick = function(event) { AudioDevice.toggleMute(); }; panel.addChild(micMuteButton); -var faceMuteButton = new BillboardOverlay({ +var faceMuteButton = new Image3DOverlay({ url: FACE_IMAGE_URL, subImage: { x: 0, @@ -102,43 +104,47 @@ var faceMuteButton = new BillboardOverlay({ isFacingAvatar: false, alpha: 1.0, ignoreRayIntersection: false, - offsetPosition: { - x: 0.1, - y: -0.1, - z: -0.001 - } -}); -faceMuteButton.onClick = function(event) { - FaceTracker.toggleMute(); -}; -panel.addChild(faceMuteButton); - -var addressBarButton = new BillboardOverlay({ - url: ADDRESS_BAR_IMAGE_URL, - subImage: { - x: 0, - y: 0, - width: 45, - height: 45 - }, - dimensions: { - x: 0.15, - y: 0.15, - }, - isFacingAvatar: false, - alpha: 1.0, - ignoreRayIntersection: false, offsetPosition: { x: -0.1, y: -0.1, - z: -0.001 - } + z: 0.001 + }, + visible: false +}); +faceMuteButton.onClick = function(event) { + FaceTracker.toggleMute(); +}; +panel.addChild(faceMuteButton); + +var addressBarButton = new Image3DOverlay({ + url: ADDRESS_BAR_IMAGE_URL, + subImage: { + x: 0, + y: 0, + width: 45, + height: 45 + }, + dimensions: { + x: 0.15, + y: 0.15, + }, + isFacingAvatar: false, + alpha: 1.0, + ignoreRayIntersection: false, + offsetPosition: { + 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; @@ -181,6 +187,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) { @@ -190,13 +206,10 @@ function onMouseUp(event) { overlay.onClick(event); } } - if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 5) { + if (event.isRightButton && mouseDown.maxDistance < 10) { panel.setProperties({ visible: !panel.visible, - offsetRotation: { - bind: "quat", - value: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 }) - } + anchorRotation: MyAvatar.orientation }); } @@ -208,6 +221,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/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/overlayPanelExample.js similarity index 54% rename from examples/example/ui/floatingUIExample.js rename to examples/example/ui/overlayPanelExample.js index 1e957fe6b3..c27123c9ad 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,19 +18,18 @@ 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({ - offsetRotation: { - bind: "quat", - value: { w: 1, x: 0, y: 0, z: 0 } - }, - offsetPosition: { x: 0, y: 0.4, z: 1 } +var mainPanel = new OverlayPanel({ + anchorPositionBinding: { avatar: "MyAvatar" }, + offsetPosition: { x: 0, y: 0.4, z: -1 }, + isFacingAvatar: false }); -var bluePanel = mainPanel.addChild(new FloatingUIPanel ({ - offsetPosition: { x: 0.1, y: 0.1, z: -0.2 } +var bluePanel = mainPanel.addChild(new OverlayPanel ({ + offsetPosition: { x: 0.1, y: 0.1, z: 0.2 }, + offsetScale: 0.5 })); -var mainPanelBackground = new BillboardOverlay({ +var mainPanelBackground = new Image3DOverlay({ url: BG_IMAGE_URL, dimensions: { x: 0.5, @@ -42,20 +41,44 @@ var mainPanelBackground = new BillboardOverlay({ offsetPosition: { x: 0, y: 0, - z: 0.001 + z: -0.001 } }); var bluePanelBackground = mainPanelBackground.clone(); -bluePanelBackground.dimensions = { - x: 0.3, - y: 0.3 -}; mainPanel.addChild(mainPanelBackground); bluePanel.addChild(bluePanelBackground); -var redDot = mainPanel.addChild(new BillboardOverlay({ +var textWidth = .25; +var textHeight = .1; +var numberOfLines = 1; +var textMargin = 0.00625; +var lineHeight = (textHeight - (2 * textMargin)) / numberOfLines; + +var text = mainPanel.addChild(new Text3DOverlay({ + text: "TEXT", + isFacingAvatar: false, + alpha: 1.0, + ignoreRayIntersection: false, + offsetPosition: { + x: 0.1, + y: -0.15, + z: 0.001 + }, + 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 Image3DOverlay({ url: RED_DOT_IMAGE_URL, dimensions: { x: 0.1, @@ -71,7 +94,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, @@ -87,46 +110,45 @@ 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, - 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 blueSquare2 = bluePanel.addChild(new BillboardOverlay({ +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 }; - var mouseDown = {}; function onMouseDown(event) { @@ -136,26 +158,30 @@ 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) { if (event.isLeftButton) { var overlay = OverlayManager.findAtPoint({ x: event.x, y: event.y }); - if (overlay === mouseDown.overlay) { - if (overlay.attachedPanel === bluePanel) { + if (overlay && overlay === mouseDown.overlay) { + if (overlay.parentPanel === bluePanel) { overlay.destroy(); - } else if (overlay) { - var oldPos = overlay.offsetPosition; - var newPos = { - x: Number(oldPos.x), - y: Number(oldPos.y), - z: Number(oldPos.z) + 0.1 - }; - overlay.offsetPosition = newPos; + } else { + overlay.offsetPosition = Vec3.sum(overlay.offsetPosition, { x: 0, y: 0, z: -0.1 }); } } } - if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 5) { + if (event.isRightButton && mouseDown.maxDistance < 10) { mainPanel.visible = !mainPanel.visible; } } @@ -165,5 +191,6 @@ function onScriptEnd() { } Controller.mousePressEvent.connect(onMouseDown); +Controller.mouseMoveEvent.connect(onMouseMove); Controller.mouseReleaseEvent.connect(onMouseUp); -Script.scriptEnding.connect(onScriptEnd); \ No newline at end of file +Script.scriptEnding.connect(onScriptEnd); 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 cd05cd2a52..bf882c3d78 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; // ... @@ -42,7 +42,18 @@ var panels = {}; var overlayTypes; - var Overlay, Overlay2D, Base3DOverlay, Planar3DOverlay, Volume3DOverlay; + + // Abstract overlay types + var Overlay, + Overlay2D, + Base3DOverlay, + Planar3DOverlay, + Billboard3DOverlay, + Volume3DOverlay; + + // Multiple inheritance mixins + var PanelAttachable, + Billboardable; // @@ -55,10 +66,6 @@ } var overlay = new overlayTypes[type](); overlay._id = id; - var panelID = Overlays.getAttachedPanel(id) - if (panelID && panelID in panels) { - panels[panelID].addChild(overlay); - } overlays[id] = overlay; return overlay; } @@ -74,7 +81,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) { @@ -87,6 +94,48 @@ 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 OverlayPanel(); + panel._id = id; + overlays[id] = overlay; + return overlay; + } + + // + // Get or create a panel 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; + } + + 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. @@ -94,7 +143,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 +150,6 @@ }, findAtPoint: function(point, knownOverlaysOnly, searchList) { var foundID = Overlays.getOverlayAtPoint(point); - print("at point " + foundID); if (foundID) { return findOverlay(foundID, knownOverlaysOnly, searchList); } else { @@ -110,10 +157,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; } @@ -125,7 +172,7 @@ // // Usage: // // Create an overlay - // var billboard = new BillboardOverlay({ + // var billboard = new Image3DOverlay({ // visible: true, // isFacingAvatar: true, // ignoreRayIntersections: false @@ -191,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", "facingRotation"]; - Overlay = (function() { var that = function(type, params) { if (type && params) { @@ -203,7 +246,6 @@ } else { this._id = 0; } - this._attachedPanelPointer = null; }; that.prototype.constructor = that; @@ -214,9 +256,9 @@ } }); - Object.defineProperty(that.prototype, "attachedPanel", { + Object.defineProperty(that.prototype, "parentPanel", { get: function() { - return this._attachedPanelPointer; + return findPanel(Overlays.getParentPanel(this._id)); } }); @@ -236,12 +278,21 @@ 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" ]); @@ -255,6 +306,10 @@ "dimensions" ]); + Billboard3DOverlay = generateOverlayClass(Planar3DOverlay, ABSTRACT, [ + ].concat(PanelAttachable).concat(Billboardable)); + Billboard3DOverlay.prototype.isPanelAttachable = function() { return true; }; + Volume3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [ "dimensions" ]); @@ -263,13 +318,17 @@ "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" + "rightMargin", "bottomMargin" ]); generateOverlayClass(Volume3DOverlay, "cube", [ @@ -302,13 +361,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"]; @@ -319,25 +375,24 @@ Grid3DOverlay = overlayTypes["grid"]; LocalModelsOverlay = overlayTypes["localmodels"]; ModelOverlay = overlayTypes["model"]; - BillboardOverlay = overlayTypes["billboard"]; // // Object oriented abstraction layer for panels. // - FloatingUIPanel = (function() { + OverlayPanel = (function() { var that = function(params) { this._id = Overlays.addPanel(params); - this._children = []; - this._visible = Boolean(params.visible); panels[this._id] = this; - this._attachedPanelPointer = null; }; that.prototype.constructor = that; - var FIELDS = ["offsetPosition", "offsetRotation", "facingRotation"]; - FIELDS.forEach(function(prop) { + var props = [ + "anchorPosition", "anchorPositionBinding", "anchorRotation", "anchorRotationBinding", "anchorScale", "visible" + ].concat(PanelAttachable).concat(Billboardable) + + props.forEach(function(prop) { Object.defineProperty(that.prototype, prop, { get: function() { return Overlays.getPanelProperty(this._id, prop); @@ -351,78 +406,47 @@ }); }); - var PSEUDO_FIELDS = []; - - PSEUDO_FIELDS.push("children"); - Object.defineProperty(that.prototype, "children", { + Object.defineProperty(that.prototype, "parentPanel", { get: function() { - return this._children.slice(); + return findPanel(Overlays.getParentPanel(this._id)); } }); - PSEUDO_FIELDS.push("visible"); - Object.defineProperty(that.prototype, "visible", { + Object.defineProperty(that.prototype, "children", { get: function() { - return this._visible; - }, - set: function(visible) { - this._visible = visible; - this._children.forEach(function(child) { - child.visible = visible; - }); + 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) { - 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 - } - }); - } - child._attachedPanelPointer = this; - child.visible = this.visible; - this._children.push(child); + Overlays.setParentPanel(child._id, this._id); return child; }; that.prototype.removeChild = function(child) { - var i = this._children.indexOf(child); - if (i >= 0) { - if (child instanceof Overlay) { - 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); + if (child.parentPanel === this) { + Overlays.setParentPanel(child._id, 0); } }; 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); }; @@ -433,8 +457,8 @@ function onOverlayDeleted(id) { if (id in overlays) { - if (overlays[id]._attachedPanelPointer) { - overlays[id]._attachedPanelPointer.removeChild(overlays[id]); + if (overlays[id].parentPanel) { + overlays[id].parentPanel.removeChild(overlays[id]); } delete overlays[id]; } @@ -442,10 +466,9 @@ function onPanelDeleted(id) { if (id in panels) { - panels[id]._children.forEach(function(child) { - print(JSON.stringify(child.destroy)); - child.destroy(); - }); + if (panels[id].parentPanel) { + panels[id].parentPanel.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 7d58404a7b..b332fb401f 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -259,7 +259,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 349f192f91..0b033a1abf 100644 --- a/examples/progress.js +++ b/examples/progress.js @@ -116,7 +116,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/Application.cpp b/interface/src/Application.cpp index c226016578..4d2739c442 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3361,16 +3361,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se activeRenderingThread = nullptr; } -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); -} - void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) { auto originalViewport = renderArgs->_viewport; // Grab current viewport to reset it at the end diff --git a/interface/src/Application.h b/interface/src/Application.h index 41091df009..6567c72455 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -271,8 +271,6 @@ public: virtual const glm::vec3& getShadowDistances() const { return _shadowDistances; } 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 b75146f9f2..44f336e996 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -339,12 +339,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 2755a99340..23868737d0 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -153,7 +153,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 StandingHMDSensorMode = "Standing HMD Sensor Mode"; const QString Stars = "Stars"; const QString Stats = "Stats"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 1b6a5f7763..8ba58217c3 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 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 } diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp new file mode 100644 index 0000000000..0b27673e18 --- /dev/null +++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp @@ -0,0 +1,46 @@ +// +// 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(const Billboard3DOverlay* billboard3DOverlay) : + Planar3DOverlay(billboard3DOverlay), + PanelAttachable(*billboard3DOverlay), + Billboardable(*billboard3DOverlay) +{ +} + +void Billboard3DOverlay::setProperties(const QScriptValue &properties) { + Planar3DOverlay::setProperties(properties); + PanelAttachable::setProperties(properties); + Billboardable::setProperties(properties); +} + +QScriptValue Billboard3DOverlay::getProperty(const QString &property) { + QScriptValue value; + value = Billboardable::getProperty(_scriptEngine, property); + if (value.isValid()) { + return value; + } + value = PanelAttachable::getProperty(_scriptEngine, property); + if (value.isValid()) { + return value; + } + return Planar3DOverlay::getProperty(property); +} + +void Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) { + if (force || usecTimestampNow() > _transformExpiry) { + PanelAttachable::applyTransformTo(transform, true); + pointTransformAtCamera(transform, getOffsetRotation()); + } +} diff --git a/interface/src/ui/overlays/Billboard3DOverlay.h b/interface/src/ui/overlays/Billboard3DOverlay.h new file mode 100644 index 0000000000..2f5af1068f --- /dev/null +++ b/interface/src/ui/overlays/Billboard3DOverlay.h @@ -0,0 +1,33 @@ +// +// 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" +#include "Billboardable.h" + +class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable, public Billboardable { + Q_OBJECT + +public: + Billboard3DOverlay() {} + Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay); + + virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); + +protected: + virtual void applyTransformTo(Transform& transform, bool force = 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..c6edad501f --- /dev/null +++ b/interface/src/ui/overlays/Billboardable.cpp @@ -0,0 +1,41 @@ +// +// 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::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; + 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(offsetRotation); + } +} diff --git a/interface/src/ui/overlays/Billboardable.h b/interface/src/ui/overlays/Billboardable.h new file mode 100644 index 0000000000..1388f13e60 --- /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 pointTransformAtCamera(Transform& transform, glm::quat offsetRotation = {1, 0, 0, 0}); + +private: + bool _isFacingAvatar = false; +}; + +#endif // hifi_Billboardable_h diff --git a/interface/src/ui/overlays/FloatingUIPanel.cpp b/interface/src/ui/overlays/FloatingUIPanel.cpp deleted file mode 100644 index eedb4bffd1..0000000000 --- a/interface/src/ui/overlays/FloatingUIPanel.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// -// FloatingUIPanel.cpp -// interface/src/ui/overlays -// -// Created by Zander Otavka on 7/2/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 "FloatingUIPanel.h" - -#include -#include -#include - -#include "avatar/AvatarManager.h" -#include "avatar/MyAvatar.h" -#include "Application.h" -#include "Base3DOverlay.h" - -std::function const FloatingUIPanel::AVATAR_POSITION = []() -> glm::vec3 { - return DependencyManager::get()->getMyAvatar()->getPosition(); -}; - -std::function const FloatingUIPanel::AVATAR_ORIENTATION = []() -> glm::quat { - return DependencyManager::get()->getMyAvatar()->getOrientation() * - glm::angleAxis(glm::pi(), IDENTITY_UP); -}; - -glm::vec3 FloatingUIPanel::getPosition() const { - return getOffsetRotation() * getOffsetPosition() + getAnchorPosition(); -} - -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::addChild(unsigned int childId) { - if (!_children.contains(childId)) { - _children.append(childId); - } -} - -void FloatingUIPanel::removeChild(unsigned int childId) { - if (_children.contains(childId)) { - _children.removeOne(childId); - } -} - -QScriptValue FloatingUIPanel::getProperty(const QString &property) { - if (property == "anchorPosition") { - return vec3toScriptValue(_scriptEngine, getAnchorPosition()); - } - if (property == "offsetRotation") { - return quatToScriptValue(_scriptEngine, getOffsetRotation()); - } - if (property == "offsetPosition") { - return vec3toScriptValue(_scriptEngine, getOffsetPosition()); - } - if (property == "facingRotation") { - return quatToScriptValue(_scriptEngine, getFacingRotation()); - } - - return QScriptValue(); -} - -void FloatingUIPanel::setProperties(const QScriptValue &properties) { - QScriptValue anchor = properties.property("anchorPosition"); - if (anchor.isValid()) { - QScriptValue bindType = anchor.property("bind"); - QScriptValue value = anchor.property("value"); - - 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") { - FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays() - .getPanel(value.toVariant().toUInt()); - setAnchorPosition([panel]() -> glm::vec3 { - return panel->getPosition(); - }); - } 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 offsetRotation = properties.property("offsetRotation"); - if (offsetRotation.isValid()) { - QScriptValue bindType = offsetRotation.property("bind"); - QScriptValue value = offsetRotation.property("value"); - - 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") { - FloatingUIPanel::Pointer panel = Application::getInstance()->getOverlays() - .getPanel(value.toVariant().toUInt()); - setOffsetRotation([panel]() -> glm::quat { - return panel->getRotation(); - }); - } 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); - } - } - } - } - } - - 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 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"); - - 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); - } - } -} diff --git a/interface/src/ui/overlays/FloatingUIPanel.h b/interface/src/ui/overlays/FloatingUIPanel.h deleted file mode 100644 index f84ac32fac..0000000000 --- a/interface/src/ui/overlays/FloatingUIPanel.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// FloatingUIPanel.h -// interface/src/ui/overlays -// -// Created by Zander Otavka on 7/2/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_FloatingUIPanel_h -#define hifi_FloatingUIPanel_h - -#include -#include - -#include -#include -#include - -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(); } - glm::vec3 getOffsetPosition() const { return _offsetPosition; } - glm::quat getFacingRotation() const { return _facingRotation; } - glm::vec3 getPosition() const; - glm::quat getRotation() const; - - 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); - void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } - void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; } - - const QList& getChildren() { return _children; } - void addChild(unsigned int childId); - void removeChild(unsigned int childId); - unsigned int popLastChild() { return _children.takeLast(); } - - QScriptValue getProperty(const QString& property); - void setProperties(const QScriptValue& properties); - -private: - static std::function const AVATAR_POSITION; - static std::function const AVATAR_ORIENTATION; - - std::function _anchorPosition{AVATAR_POSITION}; - std::function _offsetRotation{AVATAR_ORIENTATION}; - glm::vec3 _offsetPosition{0, 0, 0}; - glm::quat _facingRotation{1, 0, 0, 0}; - QScriptEngine* _scriptEngine; - QList _children; -}; - -#endif // hifi_FloatingUIPanel_h diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp similarity index 67% rename from interface/src/ui/overlays/BillboardOverlay.cpp rename to interface/src/ui/overlays/Image3DOverlay.cpp index 58790c4722..c13dbbb139 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,53 +18,41 @@ #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(); - rotation *= glm::angleAxis(glm::pi(), IDENTITY_UP); - setRotation(rotation); - } +void Image3DOverlay::update(float deltatime) { + applyTransformTo(_transform); } -void BillboardOverlay::update(float deltatime) { - setTransforms(_transform); -} - -void BillboardOverlay::render(RenderArgs* args) { +void Image3DOverlay::render(RenderArgs* args) { if (!_texture) { _isLoaded = true; _texture = DependencyManager::get()->getTexture(_url); } - if (!_visible || !_texture || !_texture->isLoaded()) { + if (!_visible || !getParentVisible() || !_texture || !_texture->isLoaded()) { return; } Q_ASSERT(args->_batch); - auto batch = args->_batch; + gpu::Batch* batch = args->_batch; float imageWidth = _texture->getWidth(); float imageHeight = _texture->getHeight(); @@ -98,9 +87,10 @@ void BillboardOverlay::render(RenderArgs* args) { xColor color = getColor(); float alpha = getAlpha(); - setTransforms(_transform); + applyTransformTo(_transform, true); 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()); @@ -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); + applyTransformTo(_transform, true); - // 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/OverlayPanel.cpp b/interface/src/ui/overlays/OverlayPanel.cpp new file mode 100644 index 0000000000..db91b7e0e3 --- /dev/null +++ b/interface/src/ui/overlays/OverlayPanel.cpp @@ -0,0 +1,200 @@ +// +// OverlayPanel.cpp +// interface/src/ui/overlays +// +// Created by Zander Otavka on 7/2/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 "OverlayPanel.h" + +#include +#include +#include +#include + +#include "avatar/AvatarManager.h" +#include "avatar/MyAvatar.h" +#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) { + 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); + } +} + +void OverlayPanel::removeChild(unsigned int childId) { + if (_children.contains(childId)) { + _children.removeOne(childId); + } +} + +QScriptValue OverlayPanel::getProperty(const QString &property) { + if (property == "anchorPosition") { + return vec3toScriptValue(_scriptEngine, getAnchorPosition()); + } + if (property == "anchorPositionBinding") { + return propertyBindingToScriptValue(_scriptEngine, + PropertyBinding(_anchorPositionBindMyAvatar ? + "MyAvatar" : "", + _anchorPositionBindEntity)); + } + if (property == "anchorRotation") { + return quatToScriptValue(_scriptEngine, getAnchorRotation()); + } + if (property == "anchorRotationBinding") { + return propertyBindingToScriptValue(_scriptEngine, + PropertyBinding(_anchorRotationBindMyAvatar ? + "MyAvatar" : "", + _anchorRotationBindEntity)); + } + if (property == "anchorScale") { + return vec3toScriptValue(_scriptEngine, getAnchorScale()); + } + 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; + } + + 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 anchorPosition = properties.property("anchorPosition"); + if (anchorPosition.isValid() && + anchorPosition.property("x").isValid() && + anchorPosition.property("y").isValid() && + anchorPosition.property("z").isValid()) { + glm::vec3 newPosition; + vec3FromScriptValue(anchorPosition, newPosition); + setAnchorPosition(newPosition); + } + + QScriptValue anchorPositionBinding = properties.property("anchorPositionBinding"); + if (anchorPositionBinding.isValid()) { + PropertyBinding binding = {}; + propertyBindingFromScriptValue(anchorPositionBinding, binding); + _anchorPositionBindMyAvatar = binding.avatar == "MyAvatar"; + _anchorPositionBindEntity = binding.entity; + } + + 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(anchorRotation, newRotation); + setAnchorRotation(newRotation); + } + + QScriptValue anchorRotationBinding = properties.property("anchorRotationBinding"); + if (anchorRotationBinding.isValid()) { + PropertyBinding binding = {}; + propertyBindingFromScriptValue(anchorPositionBinding, binding); + _anchorRotationBindMyAvatar = binding.avatar == "MyAvatar"; + _anchorRotationBindEntity = binding.entity; + } + + 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(anchorScale, newScale); + setAnchorScale(newScale); + } else { + setAnchorScale(anchorScale.toVariant().toFloat()); + } + } + + QScriptValue visible = properties.property("visible"); + if (visible.isValid()) { + setVisible(visible.toVariant().toBool()); + } +} + +void OverlayPanel::applyTransformTo(Transform& transform, bool force) { + if (force || usecTimestampNow() > _transformExpiry) { + PanelAttachable::applyTransformTo(transform, true); + if (!getParentPanel()) { + 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()); + } + pointTransformAtCamera(transform, getOffsetRotation()); + } +} diff --git a/interface/src/ui/overlays/OverlayPanel.h b/interface/src/ui/overlays/OverlayPanel.h new file mode 100644 index 0000000000..221763fe87 --- /dev/null +++ b/interface/src/ui/overlays/OverlayPanel.h @@ -0,0 +1,83 @@ +// +// OverlayPanel.h +// interface/src/ui/overlays +// +// Created by Zander Otavka on 7/2/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_OverlayPanel_h +#define hifi_OverlayPanel_h + +#include + +#include +#include +#include +#include + +#include "PanelAttachable.h" +#include "Billboardable.h" + +class PropertyBinding { +public: + PropertyBinding() {} + PropertyBinding(QString avatar, QUuid entity); + QString avatar; + QUuid entity; +}; + +QScriptValue propertyBindingToScriptValue(QScriptEngine* engine, const PropertyBinding& value); +void propertyBindingFromScriptValue(const QScriptValue& object, PropertyBinding& value); + + +class OverlayPanel : public QObject, public PanelAttachable, public Billboardable { + Q_OBJECT + +public: + typedef std::shared_ptr Pointer; + + void init(QScriptEngine* scriptEngine) { _scriptEngine = scriptEngine; } + + // getters + 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 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; } + void addChild(unsigned int childId); + void removeChild(unsigned int childId); + unsigned int popLastChild() { return _children.takeLast(); } + + QScriptValue getProperty(const QString& property); + void setProperties(const QScriptValue& properties); + + virtual void applyTransformTo(Transform& transform, bool force = false); + +private: + Transform _anchorTransform; + + bool _anchorPositionBindMyAvatar = false; + QUuid _anchorPositionBindEntity; + + bool _anchorRotationBindMyAvatar = false; + QUuid _anchorRotationBindEntity; + + bool _visible = true; + QList _children; + + QScriptEngine* _scriptEngine; +}; + +#endif // hifi_OverlayPanel_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 33c3c37da9..39b8892f13 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -18,7 +18,7 @@ #include #include "Application.h" -#include "BillboardOverlay.h" +#include "Image3DOverlay.h" #include "Circle3DOverlay.h" #include "Cube3DOverlay.h" #include "ImageOverlay.h" @@ -148,6 +148,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) { @@ -168,8 +170,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 == BillboardOverlay::TYPE) { - thisOverlay = std::make_shared(); } if (thisOverlay) { @@ -210,7 +210,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->getParentPanel()) { + attachable->getParentPanel()->addChild(cloneId); + } + return cloneId; } return 0; // Not found @@ -261,9 +266,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); @@ -280,28 +285,42 @@ 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)->getParentPanel()); } return 0; } -void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) { - Overlay::Pointer overlay = getOverlay(childId); - auto attachable = std::dynamic_pointer_cast(overlay); +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 = _panels[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)) { + OverlayPanel::Pointer child = getPanel(childId); + if (_panels.contains(panelId)) { + auto panel = getPanel(panelId); + panel->addChild(childId); + child->setParentPanel(panel); + } else { + auto panel = child->getParentPanel(); + if (panel) { + panel->removeChild(childId); + child->setParentPanel(0); } } } @@ -523,7 +542,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; @@ -534,7 +553,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); @@ -549,7 +568,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]; + OverlayPanel::Pointer thisPanel = getPanel(panelId); QReadLocker lock(&_lock); result.value = thisPanel->getProperty(property); } @@ -558,7 +577,7 @@ OverlayPropertyResult Overlays::getPanelProperty(unsigned int panelId, const QSt void Overlays::deletePanel(unsigned int panelId) { - FloatingUIPanel::Pointer panelToDelete; + OverlayPanel::Pointer panelToDelete; { QWriteLocker lock(&_lock); @@ -570,8 +589,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 aa5d69bc89..212b7b227d 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; @@ -69,7 +69,7 @@ public: void enable(); 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 @@ -92,8 +92,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); @@ -113,7 +113,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); @@ -127,6 +127,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); @@ -136,7 +142,7 @@ private: QMap _overlaysHUD; QMap _overlaysWorld; - QMap _panels; + QMap _panels; QList _overlaysToDelete; unsigned int _nextOverlayID; 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/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp index ac4730cfe8..91a7525257 100644 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ b/interface/src/ui/overlays/PanelAttachable.cpp @@ -13,25 +13,13 @@ #include -PanelAttachable::PanelAttachable() : - _attachedPanel(nullptr), - _facingRotation(1, 0, 0, 0) -{ -} +#include "OverlayPanel.h" -PanelAttachable::PanelAttachable(const PanelAttachable* panelAttachable) : - _attachedPanel(panelAttachable->_attachedPanel), - _offsetPosition(panelAttachable->_offsetPosition), - _facingRotation(panelAttachable->_facingRotation) -{ -} - -void PanelAttachable::setTransforms(Transform& transform) { - if (getAttachedPanel()) { - transform.setTranslation(getAttachedPanel()->getAnchorPosition()); - transform.setRotation(getAttachedPanel()->getOffsetRotation()); - transform.postTranslate(getOffsetPosition() + getAttachedPanel()->getOffsetPosition()); - transform.postRotate(getFacingRotation() * getAttachedPanel()->getFacingRotation()); +bool PanelAttachable::getParentVisible() const { + if (getParentPanel()) { + return getParentPanel()->getVisible() && getParentPanel()->getParentVisible(); + } else { + return true; } } @@ -39,42 +27,60 @@ QScriptValue PanelAttachable::getProperty(QScriptEngine* scriptEngine, const QSt if (property == "offsetPosition") { return vec3toScriptValue(scriptEngine, getOffsetPosition()); } - if (property == "facingRotation") { - return quatToScriptValue(scriptEngine, getFacingRotation()); + 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 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() && + 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(); - setFacingRotation(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()); + } + } +} + +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()); } } } diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h index 9776ac5ecb..5242450e5d 100644 --- a/interface/src/ui/overlays/PanelAttachable.h +++ b/interface/src/ui/overlays/PanelAttachable.h @@ -12,34 +12,42 @@ #ifndef hifi_PanelAttachable_h #define hifi_PanelAttachable_h -#include "FloatingUIPanel.h" +#include #include #include +#include +#include +#include + +class OverlayPanel; class PanelAttachable { public: - PanelAttachable(); - PanelAttachable(const PanelAttachable* panelAttachable); + // getters + std::shared_ptr getParentPanel() const { return _parentPanel; } + glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); } + glm::quat getOffsetRotation() const { return _offset.getRotation(); } + glm::vec3 getOffsetScale() const { return _offset.getScale(); } + bool getParentVisible() const; - FloatingUIPanel::Pointer getAttachedPanel() const { return _attachedPanel; } - glm::vec3 getOffsetPosition() const { return _offsetPosition; } - 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; } + // setters + void setParentPanel(std::shared_ptr panel) { _parentPanel = panel; } + 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); } +protected: QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); void setProperties(const QScriptValue& properties); -protected: - virtual void setTransforms(Transform& transform); + virtual void applyTransformTo(Transform& transform, bool force = false); + quint64 _transformExpiry = 0; private: - FloatingUIPanel::Pointer _attachedPanel; - glm::vec3 _offsetPosition; - glm::quat _facingRotation; + std::shared_ptr _parentPanel = nullptr; + Transform _offset; }; #endif // hifi_PanelAttachable_h diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 00a7d75090..d4df8553c8 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -32,14 +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), + Billboard3DOverlay(text3DOverlay), _text(text3DOverlay->_text), _backgroundColor(text3DOverlay->_backgroundColor), _backgroundAlpha(text3DOverlay->_backgroundAlpha), @@ -47,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); } @@ -76,41 +74,30 @@ xColor Text3DOverlay::getBackgroundColor() { return result; } +void Text3DOverlay::update(float deltatime) { + applyTransformTo(_transform); +} void Text3DOverlay::render(RenderArgs* args) { - if (!_visible) { + if (!_visible || !getParentVisible()) { 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); - + applyTransformTo(_transform, true); + 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; - 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); @@ -125,20 +112,20 @@ 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.001f)); 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); + Billboard3DOverlay::setProperties(properties); QScriptValue text = properties.property("text"); if (text.isValid()) { @@ -180,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) { @@ -213,10 +194,8 @@ QScriptValue Text3DOverlay::getProperty(const QString& property) { if (property == "bottomMargin") { return _bottomMargin; } - if (property == "isFacingAvatar") { - return _isFacingAvatar; - } - return Planar3DOverlay::getProperty(property); + + return Billboard3DOverlay::getProperty(property); } Text3DOverlay* Text3DOverlay::createClone() const { @@ -232,3 +211,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) { + applyTransformTo(_transform, true); + return Billboard3DOverlay::findRayIntersection(origin, direction, distance, face); +} diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index abd5ef54bd..e5e0ff7b96 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -13,11 +13,11 @@ #include -#include "Planar3DOverlay.h" +#include "Billboard3DOverlay.h" class TextRenderer3D; -class Text3DOverlay : public Planar3DOverlay { +class Text3DOverlay : public Billboard3DOverlay { Q_OBJECT public: @@ -29,6 +29,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; } @@ -36,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; } @@ -47,13 +48,14 @@ 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); 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; private: @@ -67,7 +69,6 @@ private: float _topMargin; float _rightMargin; float _bottomMargin; - bool _isFacingAvatar; }; diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index d3710c6ccc..7e74b3d26c 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -60,7 +60,7 @@ public: virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); } void setEntityTree(EntityTree* modelTree); - EntityTree* getEntityTree(EntityTree*) { return _entityTree; } + EntityTree* getEntityTree() { return _entityTree; } public slots: diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 8bb6b6ca8f..a9cd7db20c 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -43,9 +43,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) {