Merge branch 'master' of https://github.com/highfidelity/hifi into punk

This commit is contained in:
samcake 2015-08-08 16:44:19 -07:00
commit f9cbafdd39
44 changed files with 993 additions and 724 deletions

View file

@ -5,7 +5,7 @@
// Created by Zander Otavka on 7/15/15. // Created by Zander Otavka on 7/15/15.
// Copyright 2015 High Fidelity, Inc. // 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. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // 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 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 ADDRESS_BAR_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/tools/address-bar-toggle.svg";
var panel = new FloatingUIPanel({ var panel = new OverlayPanel({
anchorPosition: { anchorPositionBinding: { avatar: "MyAvatar" },
bind: "myAvatar" offsetPosition: { x: 0, y: 0.4, z: -1 },
}, visible: false
offsetPosition: { x: 0, y: 0.4, z: 1 }
}); });
var background = new BillboardOverlay({ var background = new Image3DOverlay({
url: BG_IMAGE_URL, url: BG_IMAGE_URL,
dimensions: { dimensions: {
x: 0.5, x: 0.5,
@ -37,11 +36,12 @@ var background = new BillboardOverlay({
}, },
isFacingAvatar: false, isFacingAvatar: false,
alpha: 1.0, alpha: 1.0,
ignoreRayIntersection: false ignoreRayIntersection: false,
visible: false
}); });
panel.addChild(background); panel.addChild(background);
var closeButton = new BillboardOverlay({ var closeButton = new Image3DOverlay({
url: CLOSE_IMAGE_URL, url: CLOSE_IMAGE_URL,
dimensions: { dimensions: {
x: 0.15, x: 0.15,
@ -51,17 +51,18 @@ var closeButton = new BillboardOverlay({
alpha: 1.0, alpha: 1.0,
ignoreRayIntersection: false, ignoreRayIntersection: false,
offsetPosition: { offsetPosition: {
x: -0.1, x: 0.1,
y: 0.1, y: 0.1,
z: -0.001 z: 0.001
} },
visible: false
}); });
closeButton.onClick = function(event) { closeButton.onClick = function(event) {
panel.visible = false; panel.visible = false;
}; };
panel.addChild(closeButton); panel.addChild(closeButton);
var micMuteButton = new BillboardOverlay({ var micMuteButton = new Image3DOverlay({
url: MIC_IMAGE_URL, url: MIC_IMAGE_URL,
subImage: { subImage: {
x: 0, x: 0,
@ -77,17 +78,18 @@ var micMuteButton = new BillboardOverlay({
alpha: 1.0, alpha: 1.0,
ignoreRayIntersection: false, ignoreRayIntersection: false,
offsetPosition: { offsetPosition: {
x: 0.1, x: -0.1,
y: 0.1, y: 0.1,
z: -0.001 z: 0.001
} },
visible: false
}); });
micMuteButton.onClick = function(event) { micMuteButton.onClick = function(event) {
AudioDevice.toggleMute(); AudioDevice.toggleMute();
}; };
panel.addChild(micMuteButton); panel.addChild(micMuteButton);
var faceMuteButton = new BillboardOverlay({ var faceMuteButton = new Image3DOverlay({
url: FACE_IMAGE_URL, url: FACE_IMAGE_URL,
subImage: { subImage: {
x: 0, x: 0,
@ -102,43 +104,47 @@ var faceMuteButton = new BillboardOverlay({
isFacingAvatar: false, isFacingAvatar: false,
alpha: 1.0, alpha: 1.0,
ignoreRayIntersection: false, 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: { offsetPosition: {
x: -0.1, x: -0.1,
y: -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) { addressBarButton.onClick = function(event) {
DialogsManager.toggleAddressBar(); DialogsManager.toggleAddressBar();
}; };
panel.addChild(addressBarButton); panel.addChild(addressBarButton);
panel.setChildrenVisible();
function onMicMuteToggled() { function onMicMuteToggled() {
var offset; var offset;
@ -181,6 +187,16 @@ function onMouseDown(event) {
if (event.isRightButton) { if (event.isRightButton) {
mouseDown.pos = { x: event.x, y: event.y }; 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) { function onMouseUp(event) {
@ -190,13 +206,10 @@ function onMouseUp(event) {
overlay.onClick(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({ panel.setProperties({
visible: !panel.visible, visible: !panel.visible,
offsetRotation: { anchorRotation: MyAvatar.orientation
bind: "quat",
value: Quat.multiply(MyAvatar.orientation, { x: 0, y: 1, z: 0, w: 0 })
}
}); });
} }
@ -208,6 +221,7 @@ function onScriptEnd(event) {
} }
Controller.mousePressEvent.connect(onMouseDown); Controller.mousePressEvent.connect(onMouseDown);
Controller.mouseMoveEvent.connect(onMouseMove);
Controller.mouseReleaseEvent.connect(onMouseUp); Controller.mouseReleaseEvent.connect(onMouseUp);
AudioDevice.muteToggled.connect(onMicMuteToggled); AudioDevice.muteToggled.connect(onMicMuteToggled);
FaceTracker.muteToggled.connect(onFaceMuteToggled); FaceTracker.muteToggled.connect(onFaceMuteToggled);

View file

@ -178,7 +178,7 @@
modelProperties.sittingPoints[seatIndex].rotation); modelProperties.sittingPoints[seatIndex].rotation);
this.scale = MyAvatar.scale / 3; this.scale = MyAvatar.scale / 3;
this.sphere = Overlays.addOverlay("billboard", { this.sphere = Overlays.addOverlay("image3d", {
subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight},
url: buttonImageUrl, url: buttonImageUrl,
position: this.position, position: this.position,

View file

@ -252,7 +252,7 @@ function SpriteBillboard(sprite_properties, overlay) {
} }
var christmastree_loader = null; var christmastree_loader = null;
christmastree_loader = new OverlayPreloader("billboard", christmastree_loader = new OverlayPreloader("image3d",
{url: CHRISTMAS_TREE_SPRITES_URL, alpha: 0}, function() { {url: CHRISTMAS_TREE_SPRITES_URL, alpha: 0}, function() {
for (var i = 0; i < NUM_OF_TREES; i++) { for (var i = 0; i < NUM_OF_TREES; i++) {
var clonedOverlay = Overlays.cloneOverlay(christmastree_loader.overlay); var clonedOverlay = Overlays.cloneOverlay(christmastree_loader.overlay);
@ -269,7 +269,7 @@ christmastree_loader = new OverlayPreloader("billboard",
); );
var santa_loader = null; var santa_loader = null;
santa_loader = new OverlayPreloader("billboard", santa_loader = new OverlayPreloader("image3d",
{url: SANTA_SPRITES_URL, alpha: 0}, function() { {url: SANTA_SPRITES_URL, alpha: 0}, function() {
for (var i = 0; i < NUM_OF_SANTAS; i++) { for (var i = 0; i < NUM_OF_SANTAS; i++) {
var clonedOverlay = Overlays.cloneOverlay(santa_loader.overlay); var clonedOverlay = Overlays.cloneOverlay(santa_loader.overlay);

View file

@ -1,5 +1,5 @@
// //
// floatingUI.js // overlayPanelExample.js
// examples/example/ui // examples/example/ui
// //
// Created by Alexander Otavka // 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 RED_DOT_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/red-dot.svg";
var BLUE_SQUARE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/blue-square.svg"; var BLUE_SQUARE_IMAGE_URL = HIFI_PUBLIC_BUCKET + "images/blue-square.svg";
var mainPanel = new FloatingUIPanel({ var mainPanel = new OverlayPanel({
offsetRotation: { anchorPositionBinding: { avatar: "MyAvatar" },
bind: "quat", offsetPosition: { x: 0, y: 0.4, z: -1 },
value: { w: 1, x: 0, y: 0, z: 0 } isFacingAvatar: false
},
offsetPosition: { x: 0, y: 0.4, z: 1 }
}); });
var bluePanel = mainPanel.addChild(new FloatingUIPanel ({ var bluePanel = mainPanel.addChild(new OverlayPanel ({
offsetPosition: { x: 0.1, y: 0.1, z: -0.2 } offsetPosition: { x: 0.1, y: 0.1, z: 0.2 },
offsetScale: 0.5
})); }));
var mainPanelBackground = new BillboardOverlay({ var mainPanelBackground = new Image3DOverlay({
url: BG_IMAGE_URL, url: BG_IMAGE_URL,
dimensions: { dimensions: {
x: 0.5, x: 0.5,
@ -42,20 +41,44 @@ var mainPanelBackground = new BillboardOverlay({
offsetPosition: { offsetPosition: {
x: 0, x: 0,
y: 0, y: 0,
z: 0.001 z: -0.001
} }
}); });
var bluePanelBackground = mainPanelBackground.clone(); var bluePanelBackground = mainPanelBackground.clone();
bluePanelBackground.dimensions = {
x: 0.3,
y: 0.3
};
mainPanel.addChild(mainPanelBackground); mainPanel.addChild(mainPanelBackground);
bluePanel.addChild(bluePanelBackground); 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, url: RED_DOT_IMAGE_URL,
dimensions: { dimensions: {
x: 0.1, 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, url: RED_DOT_IMAGE_URL,
dimensions: { dimensions: {
x: 0.1, 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, url: BLUE_SQUARE_IMAGE_URL,
dimensions: { dimensions: {
x: 0.1, x: 0.15,
y: 0.1, y: 0.15,
}, },
isFacingAvatar: false, isFacingAvatar: false,
alpha: 1.0, alpha: 1.0,
ignoreRayIntersection: false, ignoreRayIntersection: false,
offsetPosition: { offsetPosition: {
x: 0.055, x: 0.09,
y: -0.055, y: -0.09,
z: 0 z: 0
} }
})); }));
var blueSquare2 = bluePanel.addChild(new BillboardOverlay({ var blueSquare2 = bluePanel.addChild(new Image3DOverlay({
url: BLUE_SQUARE_IMAGE_URL, url: BLUE_SQUARE_IMAGE_URL,
dimensions: { dimensions: {
x: 0.1, x: 0.15,
y: 0.1, y: 0.15,
}, },
isFacingAvatar: false, isFacingAvatar: false,
alpha: 1.0, alpha: 1.0,
ignoreRayIntersection: false, ignoreRayIntersection: false,
offsetPosition: { offsetPosition: {
x: 0.055, x: 0.09,
y: 0.055, y: 0.09,
z: 0 z: 0
} }
})); }));
var blueSquare3 = blueSquare2.clone(); var blueSquare3 = blueSquare2.clone();
blueSquare3.offsetPosition = { blueSquare3.offsetPosition = {
x: -0.055, x: -0.09,
y: 0.055, y: 0.09,
z: 0 z: 0
}; };
var mouseDown = {}; var mouseDown = {};
function onMouseDown(event) { function onMouseDown(event) {
@ -136,26 +158,30 @@ function onMouseDown(event) {
if (event.isRightButton) { if (event.isRightButton) {
mouseDown.pos = { x: event.x, y: event.y }; 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) { function onMouseUp(event) {
if (event.isLeftButton) { if (event.isLeftButton) {
var overlay = OverlayManager.findAtPoint({ x: event.x, y: event.y }); var overlay = OverlayManager.findAtPoint({ x: event.x, y: event.y });
if (overlay === mouseDown.overlay) { if (overlay && overlay === mouseDown.overlay) {
if (overlay.attachedPanel === bluePanel) { if (overlay.parentPanel === bluePanel) {
overlay.destroy(); overlay.destroy();
} else if (overlay) { } else {
var oldPos = overlay.offsetPosition; overlay.offsetPosition = Vec3.sum(overlay.offsetPosition, { x: 0, y: 0, z: -0.1 });
var newPos = {
x: Number(oldPos.x),
y: Number(oldPos.y),
z: Number(oldPos.z) + 0.1
};
overlay.offsetPosition = newPos;
} }
} }
} }
if (event.isRightButton && Vec3.distance(mouseDown.pos, { x: event.x, y: event.y }) < 5) { if (event.isRightButton && mouseDown.maxDistance < 10) {
mainPanel.visible = !mainPanel.visible; mainPanel.visible = !mainPanel.visible;
} }
} }
@ -165,5 +191,6 @@ function onScriptEnd() {
} }
Controller.mousePressEvent.connect(onMouseDown); Controller.mousePressEvent.connect(onMouseDown);
Controller.mouseMoveEvent.connect(onMouseMove);
Controller.mouseReleaseEvent.connect(onMouseUp); Controller.mouseReleaseEvent.connect(onMouseUp);
Script.scriptEnding.connect(onScriptEnd); Script.scriptEnding.connect(onScriptEnd);

View file

@ -340,7 +340,7 @@ SelectionDisplay = (function () {
leftMargin: 0, leftMargin: 0,
}); });
var grabberMoveUp = Overlays.addOverlay("billboard", { var grabberMoveUp = Overlays.addOverlay("image3d", {
url: HIFI_PUBLIC_BUCKET + "images/up-arrow.svg", url: HIFI_PUBLIC_BUCKET + "images/up-arrow.svg",
position: { x:0, y: 0, z: 0}, position: { x:0, y: 0, z: 0},
color: handleColor, color: handleColor,
@ -609,7 +609,7 @@ SelectionDisplay = (function () {
minorTickMarksColor: { red: 0, green: 0, blue: 0 }, minorTickMarksColor: { red: 0, green: 0, blue: 0 },
}); });
var yawHandle = Overlays.addOverlay("billboard", { var yawHandle = Overlays.addOverlay("image3d", {
url: ROTATE_ARROW_WEST_NORTH_URL, url: ROTATE_ARROW_WEST_NORTH_URL,
position: { x:0, y: 0, z: 0}, position: { x:0, y: 0, z: 0},
color: handleColor, color: handleColor,
@ -622,7 +622,7 @@ SelectionDisplay = (function () {
}); });
var pitchHandle = Overlays.addOverlay("billboard", { var pitchHandle = Overlays.addOverlay("image3d", {
url: ROTATE_ARROW_WEST_NORTH_URL, url: ROTATE_ARROW_WEST_NORTH_URL,
position: { x:0, y: 0, z: 0}, position: { x:0, y: 0, z: 0},
color: handleColor, color: handleColor,
@ -635,7 +635,7 @@ SelectionDisplay = (function () {
}); });
var rollHandle = Overlays.addOverlay("billboard", { var rollHandle = Overlays.addOverlay("image3d", {
url: ROTATE_ARROW_WEST_NORTH_URL, url: ROTATE_ARROW_WEST_NORTH_URL,
position: { x:0, y: 0, z: 0}, position: { x:0, y: 0, z: 0},
color: handleColor, color: handleColor,

View file

@ -61,7 +61,7 @@ LightOverlayManager = function() {
// Allocate or get an unused overlay // Allocate or get an unused overlay
function getOverlay() { function getOverlay() {
if (unusedOverlays.length == 0) { if (unusedOverlays.length == 0) {
var overlay = Overlays.addOverlay("billboard", { var overlay = Overlays.addOverlay("image3d", {
}); });
allOverlays.push(overlay); allOverlays.push(overlay);
} else { } else {

View file

@ -8,7 +8,7 @@
// Manage overlays with object oriented goodness, instead of ugly `Overlays.h` methods. // Manage overlays with object oriented goodness, instead of ugly `Overlays.h` methods.
// Instead of: // Instead of:
// //
// var billboard = Overlays.addOverlay("billboard", { visible: false }); // var billboard = Overlays.addOverlay("image3d", { visible: false });
// ... // ...
// Overlays.editOverlay(billboard, { visible: true }); // Overlays.editOverlay(billboard, { visible: true });
// ... // ...
@ -16,7 +16,7 @@
// //
// You can now do: // You can now do:
// //
// var billboard = new BillboardOverlay({ visible: false }); // var billboard = new Image3DOverlay({ visible: false });
// ... // ...
// billboard.visible = true; // billboard.visible = true;
// ... // ...
@ -42,7 +42,18 @@
var panels = {}; var panels = {};
var overlayTypes; 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](); var overlay = new overlayTypes[type]();
overlay._id = id; overlay._id = id;
var panelID = Overlays.getAttachedPanel(id)
if (panelID && panelID in panels) {
panels[panelID].addChild(overlay);
}
overlays[id] = overlay; overlays[id] = overlay;
return overlay; return overlay;
} }
@ -74,7 +81,7 @@
// //
function findOverlay(id, knownOverlaysOnly, searchList) { function findOverlay(id, knownOverlaysOnly, searchList) {
if (id > 0) { if (id > 0) {
knownOverlaysOnly = Boolean(knownOverlaysOnly) || Boolean(searchList); knownOverlaysOnly = Boolean(knownOverlaysOnly);
searchList = searchList || overlays; searchList = searchList || overlays;
var foundOverlay = searchList[id]; var foundOverlay = searchList[id];
if (foundOverlay) { if (foundOverlay) {
@ -87,6 +94,48 @@
return null; 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. // Perform global scoped operations on overlays, such as finding by ray intersection.
@ -94,7 +143,6 @@
OverlayManager = { OverlayManager = {
findOnRay: function(pickRay, knownOverlaysOnly, searchList) { findOnRay: function(pickRay, knownOverlaysOnly, searchList) {
var rayPickResult = Overlays.findRayIntersection(pickRay); var rayPickResult = Overlays.findRayIntersection(pickRay);
print("raypick " + rayPickResult.overlayID);
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
return findOverlay(rayPickResult.overlayID, knownOverlaysOnly, searchList); return findOverlay(rayPickResult.overlayID, knownOverlaysOnly, searchList);
} }
@ -102,7 +150,6 @@
}, },
findAtPoint: function(point, knownOverlaysOnly, searchList) { findAtPoint: function(point, knownOverlaysOnly, searchList) {
var foundID = Overlays.getOverlayAtPoint(point); var foundID = Overlays.getOverlayAtPoint(point);
print("at point " + foundID);
if (foundID) { if (foundID) {
return findOverlay(foundID, knownOverlaysOnly, searchList); return findOverlay(foundID, knownOverlaysOnly, searchList);
} else { } else {
@ -110,10 +157,10 @@
return OverlayManager.findOnRay(pickRay, knownOverlaysOnly, searchList); return OverlayManager.findOnRay(pickRay, knownOverlaysOnly, searchList);
} }
}, },
makeSearchList: function(overlayArray) { makeSearchList: function(array) {
var searchList = {}; var searchList = {};
overlayArray.forEach(function(overlay){ array.forEach(function(object) {
searchList[overlay._id] = overlay; searchList[object._id] = object;
}); });
return searchList; return searchList;
} }
@ -125,7 +172,7 @@
// //
// Usage: // Usage:
// // Create an overlay // // Create an overlay
// var billboard = new BillboardOverlay({ // var billboard = new Image3DOverlay({
// visible: true, // visible: true,
// isFacingAvatar: true, // isFacingAvatar: true,
// ignoreRayIntersections: false // ignoreRayIntersections: false
@ -191,10 +238,6 @@
return that; 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() { Overlay = (function() {
var that = function(type, params) { var that = function(type, params) {
if (type && params) { if (type && params) {
@ -203,7 +246,6 @@
} else { } else {
this._id = 0; this._id = 0;
} }
this._attachedPanelPointer = null;
}; };
that.prototype.constructor = that; that.prototype.constructor = that;
@ -214,9 +256,9 @@
} }
}); });
Object.defineProperty(that.prototype, "attachedPanel", { Object.defineProperty(that.prototype, "parentPanel", {
get: function() { get: function() {
return this._attachedPanelPointer; return findPanel(Overlays.getParentPanel(this._id));
} }
}); });
@ -236,12 +278,21 @@
Overlays.deleteOverlay(this._id); Overlays.deleteOverlay(this._id);
}; };
that.prototype.isPanelAttachable = function() {
return false;
};
return generateOverlayClass(that, ABSTRACT, [ return generateOverlayClass(that, ABSTRACT, [
"alpha", "glowLevel", "pulseMax", "pulseMin", "pulsePeriod", "glowLevelPulse", "alpha", "glowLevel", "pulseMax", "pulseMin", "pulsePeriod", "glowLevelPulse",
"alphaPulse", "colorPulse", "visible", "anchor" "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, [ Overlay2D = generateOverlayClass(Overlay, ABSTRACT, [
"bounds", "x", "y", "width", "height" "bounds", "x", "y", "width", "height"
]); ]);
@ -255,6 +306,10 @@
"dimensions" "dimensions"
]); ]);
Billboard3DOverlay = generateOverlayClass(Planar3DOverlay, ABSTRACT, [
].concat(PanelAttachable).concat(Billboardable));
Billboard3DOverlay.prototype.isPanelAttachable = function() { return true; };
Volume3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [ Volume3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [
"dimensions" "dimensions"
]); ]);
@ -263,13 +318,17 @@
"subImage", "imageURL" "subImage", "imageURL"
]); ]);
generateOverlayClass(Billboard3DOverlay, "image3d", [
"url", "subImage"
]);
generateOverlayClass(Overlay2D, "text", [ generateOverlayClass(Overlay2D, "text", [
"font", "text", "backgroundColor", "backgroundAlpha", "leftMargin", "topMargin" "font", "text", "backgroundColor", "backgroundAlpha", "leftMargin", "topMargin"
]); ]);
generateOverlayClass(Planar3DOverlay, "text3d", [ generateOverlayClass(Billboard3DOverlay, "text3d", [
"text", "backgroundColor", "backgroundAlpha", "lineHeight", "leftMargin", "topMargin", "text", "backgroundColor", "backgroundAlpha", "lineHeight", "leftMargin", "topMargin",
"rightMargin", "bottomMargin", "isFacingAvatar" "rightMargin", "bottomMargin"
]); ]);
generateOverlayClass(Volume3DOverlay, "cube", [ generateOverlayClass(Volume3DOverlay, "cube", [
@ -302,13 +361,10 @@
generateOverlayClass(Volume3DOverlay, "model", [ generateOverlayClass(Volume3DOverlay, "model", [
"url", "dimensions", "textures" "url", "dimensions", "textures"
]); ]);
generateOverlayClass(Planar3DOverlay, "billboard", [
"url", "subImage", "isFacingAvatar"
].concat(PANEL_ATTACHABLE_FIELDS));
})(); })();
ImageOverlay = overlayTypes["image"]; ImageOverlay = overlayTypes["image"];
Image3DOverlay = overlayTypes["image3d"];
TextOverlay = overlayTypes["text"]; TextOverlay = overlayTypes["text"];
Text3DOverlay = overlayTypes["text3d"]; Text3DOverlay = overlayTypes["text3d"];
Cube3DOverlay = overlayTypes["cube"]; Cube3DOverlay = overlayTypes["cube"];
@ -319,25 +375,24 @@
Grid3DOverlay = overlayTypes["grid"]; Grid3DOverlay = overlayTypes["grid"];
LocalModelsOverlay = overlayTypes["localmodels"]; LocalModelsOverlay = overlayTypes["localmodels"];
ModelOverlay = overlayTypes["model"]; ModelOverlay = overlayTypes["model"];
BillboardOverlay = overlayTypes["billboard"];
// //
// Object oriented abstraction layer for panels. // Object oriented abstraction layer for panels.
// //
FloatingUIPanel = (function() { OverlayPanel = (function() {
var that = function(params) { var that = function(params) {
this._id = Overlays.addPanel(params); this._id = Overlays.addPanel(params);
this._children = [];
this._visible = Boolean(params.visible);
panels[this._id] = this; panels[this._id] = this;
this._attachedPanelPointer = null;
}; };
that.prototype.constructor = that; that.prototype.constructor = that;
var FIELDS = ["offsetPosition", "offsetRotation", "facingRotation"]; var props = [
FIELDS.forEach(function(prop) { "anchorPosition", "anchorPositionBinding", "anchorRotation", "anchorRotationBinding", "anchorScale", "visible"
].concat(PanelAttachable).concat(Billboardable)
props.forEach(function(prop) {
Object.defineProperty(that.prototype, prop, { Object.defineProperty(that.prototype, prop, {
get: function() { get: function() {
return Overlays.getPanelProperty(this._id, prop); return Overlays.getPanelProperty(this._id, prop);
@ -351,78 +406,47 @@
}); });
}); });
var PSEUDO_FIELDS = []; Object.defineProperty(that.prototype, "parentPanel", {
PSEUDO_FIELDS.push("children");
Object.defineProperty(that.prototype, "children", {
get: function() { get: function() {
return this._children.slice(); return findPanel(Overlays.getParentPanel(this._id));
} }
}); });
PSEUDO_FIELDS.push("visible"); Object.defineProperty(that.prototype, "children", {
Object.defineProperty(that.prototype, "visible", {
get: function() { get: function() {
return this._visible; var idArray = Overlays.getPanelProperty(this._id, "children");
}, var objArray = [];
set: function(visible) { for (var i = 0; i < idArray.length; i++) {
this._visible = visible; objArray[i] = findOverlayOrPanel(idArray[i]);
this._children.forEach(function(child) { }
child.visible = visible; return objArray;
});
} }
}); });
that.prototype.addChild = function(child) { that.prototype.addChild = function(child) {
if (child instanceof Overlay) { Overlays.setParentPanel(child._id, this._id);
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);
return child; return child;
}; };
that.prototype.removeChild = function(child) { that.prototype.removeChild = function(child) {
var i = this._children.indexOf(child); if (child.parentPanel === this) {
if (i >= 0) { Overlays.setParentPanel(child._id, 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);
} }
}; };
that.prototype.setProperties = function(properties) { 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); 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() { that.prototype.destroy = function() {
Overlays.deletePanel(this._id); Overlays.deletePanel(this._id);
}; };
@ -433,8 +457,8 @@
function onOverlayDeleted(id) { function onOverlayDeleted(id) {
if (id in overlays) { if (id in overlays) {
if (overlays[id]._attachedPanelPointer) { if (overlays[id].parentPanel) {
overlays[id]._attachedPanelPointer.removeChild(overlays[id]); overlays[id].parentPanel.removeChild(overlays[id]);
} }
delete overlays[id]; delete overlays[id];
} }
@ -442,10 +466,9 @@
function onPanelDeleted(id) { function onPanelDeleted(id) {
if (id in panels) { if (id in panels) {
panels[id]._children.forEach(function(child) { if (panels[id].parentPanel) {
print(JSON.stringify(child.destroy)); panels[id].parentPanel.removeChild(panels[id]);
child.destroy(); }
});
delete panels[id]; delete panels[id];
} }
} }

View file

@ -148,7 +148,7 @@ KeyboardKey = (function(keyboard, keyProperties) {
}; };
for (var i = 0; i < this.bounds.length; i++) { for (var i = 0; i < this.bounds.length; i++) {
if (THREE_D_MODE) { if (THREE_D_MODE) {
this.overlays.push(Overlays.addOverlay("billboard", { this.overlays.push(Overlays.addOverlay("image3d", {
scale: 1, scale: 1,
rotation: MyAvatar.rotation, rotation: MyAvatar.rotation,
isFacingAvatar: false, isFacingAvatar: false,
@ -202,7 +202,7 @@ Keyboard = (function(params) {
return windowDimensions.y - this.height(); return windowDimensions.y - this.height();
}; };
if (THREE_D_MODE) { if (THREE_D_MODE) {
this.background = Overlays.addOverlay("billboard", { this.background = Overlays.addOverlay("image3d", {
scale: 1, scale: 1,
position: MyAvatar.position, position: MyAvatar.position,
rotation: MyAvatar.rotation, rotation: MyAvatar.rotation,

View file

@ -260,7 +260,7 @@ function notify(notice, button, height) {
positions = calculate3DOverlayPositions(noticeWidth, noticeHeight, notice.y); positions = calculate3DOverlayPositions(noticeWidth, noticeHeight, notice.y);
notifications.push((Overlays.addOverlay("text3d", notice))); notifications.push((Overlays.addOverlay("text3d", notice)));
buttons.push((Overlays.addOverlay("billboard", button))); buttons.push((Overlays.addOverlay("image3d", button)));
overlay3DDetails.push({ overlay3DDetails.push({
notificationOrientation: positions.notificationOrientation, notificationOrientation: positions.notificationOrientation,
notificationPosition: positions.notificationPosition, notificationPosition: positions.notificationPosition,

View file

@ -117,7 +117,7 @@
visible: false, visible: false,
ignoreRayIntersection: true ignoreRayIntersection: true
}); });
bar3D.overlay = Overlays.addOverlay("billboard", { bar3D.overlay = Overlays.addOverlay("image3d", {
url: BAR_URL, url: BAR_URL,
subImage: { x: BAR_WIDTH, y: 0, width: BAR_WIDTH, height: BAR_HEIGHT }, subImage: { x: BAR_WIDTH, y: 0, width: BAR_WIDTH, height: BAR_HEIGHT },
scale: SCALE_3D * BAR_WIDTH, scale: SCALE_3D * BAR_WIDTH,

View file

@ -175,7 +175,7 @@ function SeatIndicator(modelProperties, seatIndex) {
modelProperties.sittingPoints[seatIndex].rotation); modelProperties.sittingPoints[seatIndex].rotation);
this.scale = MyAvatar.scale / 12; this.scale = MyAvatar.scale / 12;
this.sphere = Overlays.addOverlay("billboard", { this.sphere = Overlays.addOverlay("image3d", {
subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight},
url: buttonImageUrl, url: buttonImageUrl,
position: this.position, position: this.position,

View file

@ -3335,16 +3335,6 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom
} }
} }
bool Application::getShadowsEnabled() {
Menu* menubar = Menu::getInstance();
return menubar->isOptionChecked(MenuOption::SimpleShadows) ||
menubar->isOptionChecked(MenuOption::CascadedShadows);
}
bool Application::getCascadeShadowsEnabled() {
return Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows);
}
glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) {
float horizontalScale = _glWidget->getDeviceWidth() / 2.0f; float horizontalScale = _glWidget->getDeviceWidth() / 2.0f;
float verticalScale = _glWidget->getDeviceHeight() / 2.0f; float verticalScale = _glWidget->getDeviceHeight() / 2.0f;

View file

@ -268,8 +268,6 @@ public:
float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); } virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); }
virtual bool getShadowsEnabled();
virtual bool getCascadeShadowsEnabled();
virtual QThread* getMainThread() { return thread(); } virtual QThread* getMainThread() { return thread(); }
virtual float getSizeScale() const; virtual float getSizeScale() const;
virtual int getBoundaryLevelAdjust() const; virtual int getBoundaryLevelAdjust() const;

View file

@ -346,12 +346,6 @@ Menu::Menu() {
ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight8, 0, false)); ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight8, 0, false));
ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight9, 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); MenuWrapper* framerateMenu = renderOptionsMenu->addMenu(MenuOption::RenderTargetFramerate);
QActionGroup* framerateGroup = new QActionGroup(framerateMenu); QActionGroup* framerateGroup = new QActionGroup(framerateMenu);

View file

@ -154,7 +154,6 @@ namespace MenuOption {
const QString BlueSpeechSphere = "Blue Sphere While Speaking"; const QString BlueSpeechSphere = "Blue Sphere While Speaking";
const QString BookmarkLocation = "Bookmark Location"; const QString BookmarkLocation = "Bookmark Location";
const QString Bookmarks = "Bookmarks"; const QString Bookmarks = "Bookmarks";
const QString CascadedShadows = "Cascaded";
const QString CachesSize = "RAM Caches Size"; const QString CachesSize = "RAM Caches Size";
const QString CalibrateCamera = "Calibrate Camera"; const QString CalibrateCamera = "Calibrate Camera";
const QString CenterPlayerInView = "Center Player In View"; const QString CenterPlayerInView = "Center Player In View";
@ -271,7 +270,6 @@ namespace MenuOption {
const QString ShowIKConstraints = "Show IK Constraints"; const QString ShowIKConstraints = "Show IK Constraints";
const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats"; const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats";
const QString ShowWhosLookingAtMe = "Show Who's Looking at Me"; const QString ShowWhosLookingAtMe = "Show Who's Looking at Me";
const QString SimpleShadows = "Simple";
const QString SixenseEnabled = "Enable Hydra Support"; const QString SixenseEnabled = "Enable Hydra Support";
const QString SixenseMouseInput = "Enable Sixense Mouse Input"; const QString SixenseMouseInput = "Enable Sixense Mouse Input";
const QString Stars = "Stars"; const QString Stars = "Stars";

View file

@ -717,6 +717,29 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, floa
// Compute correct scale to apply // Compute correct scale to apply
float scale = DESIRED_HIGHT_ON_SCREEN / (fontSize * pixelHeight) * devicePixelRatio; 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 // Compute pixel alignment offset
float clipToPix = 0.5f * windowSizeY / p1.w; // Got from clip to pixel coordinates float clipToPix = 0.5f * windowSizeY / p1.w; // Got from clip to pixel coordinates

View file

@ -115,6 +115,8 @@ void LodToolsDialog::reject() {
void LodToolsDialog::closeEvent(QCloseEvent* event) { void LodToolsDialog::closeEvent(QCloseEvent* event) {
this->QDialog::closeEvent(event); this->QDialog::closeEvent(event);
emit closed(); emit closed();
#if RESET_TO_AUTOMATIC_WHEN_YOU_CLOSE_THE_DIALOG_BOX
auto lodManager = DependencyManager::get<LODManager>(); auto lodManager = DependencyManager::get<LODManager>();
// always revert back to automatic LOD adjustment when closed // 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) { if (lodManager->getOctreeSizeScale() > DEFAULT_OCTREE_SIZE_SCALE) {
lodManager->setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE); lodManager->setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE);
} }
#endif
} }

View file

@ -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());
}
}

View file

@ -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

View file

@ -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 <Application.h>
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);
}
}

View file

@ -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 <QScriptValue>
#include <QScriptEngine>
#include <Transform.h>
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

View file

@ -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 <QVariant>
#include <RegisteredMetaTypes.h>
#include <DependencyManager.h>
#include "avatar/AvatarManager.h"
#include "avatar/MyAvatar.h"
#include "Application.h"
#include "Base3DOverlay.h"
std::function<glm::vec3()> const FloatingUIPanel::AVATAR_POSITION = []() -> glm::vec3 {
return DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition();
};
std::function<glm::quat()> const FloatingUIPanel::AVATAR_ORIENTATION = []() -> glm::quat {
return DependencyManager::get<AvatarManager>()->getMyAvatar()->getOrientation() *
glm::angleAxis(glm::pi<float>(), 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<Base3DOverlay>(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<Base3DOverlay>(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);
}
}
}

View file

@ -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 <functional>
#include <memory>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QScriptValue>
class FloatingUIPanel : public QObject {
Q_OBJECT
public:
typedef std::shared_ptr<FloatingUIPanel> 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<glm::vec3()>& func) { _anchorPosition = func; }
void setAnchorPosition(const glm::vec3& position);
void setOffsetRotation(const std::function<glm::quat()>& 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<unsigned int>& 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<glm::vec3()> const AVATAR_POSITION;
static std::function<glm::quat()> const AVATAR_ORIENTATION;
std::function<glm::vec3()> _anchorPosition{AVATAR_POSITION};
std::function<glm::quat()> _offsetRotation{AVATAR_ORIENTATION};
glm::vec3 _offsetPosition{0, 0, 0};
glm::quat _facingRotation{1, 0, 0, 0};
QScriptEngine* _scriptEngine;
QList<unsigned int> _children;
};
#endif // hifi_FloatingUIPanel_h

View file

@ -1,15 +1,16 @@
// //
// BillboardOverlay.cpp // Image3DOverlay.cpp
// //
// //
// Created by Clement on 7/1/14. // Created by Clement on 7/1/14.
// Modified and renamed by Zander Otavka on 8/4/15
// Copyright 2014 High Fidelity, Inc. // Copyright 2014 High Fidelity, Inc.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "BillboardOverlay.h" #include "Image3DOverlay.h"
#include <QScriptValue> #include <QScriptValue>
@ -17,53 +18,41 @@
#include <DependencyManager.h> #include <DependencyManager.h>
#include <GeometryCache.h> #include <GeometryCache.h>
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include <GLMHelpers.h>
#include "Application.h" #include "Application.h"
#include "GeometryUtil.h" #include "GeometryUtil.h"
QString const BillboardOverlay::TYPE = "billboard"; QString const Image3DOverlay::TYPE = "image3d";
BillboardOverlay::BillboardOverlay() { Image3DOverlay::Image3DOverlay() {
_isLoaded = false; _isLoaded = false;
} }
BillboardOverlay::BillboardOverlay(const BillboardOverlay* billboardOverlay) : Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) :
Planar3DOverlay(billboardOverlay), Billboard3DOverlay(image3DOverlay),
PanelAttachable(billboardOverlay), _url(image3DOverlay->_url),
_url(billboardOverlay->_url), _texture(image3DOverlay->_texture),
_texture(billboardOverlay->_texture), _fromImage(image3DOverlay->_fromImage)
_fromImage(billboardOverlay->_fromImage),
_isFacingAvatar(billboardOverlay->_isFacingAvatar)
{ {
} }
void BillboardOverlay::setTransforms(Transform& transform) { void Image3DOverlay::update(float deltatime) {
PanelAttachable::setTransforms(transform); applyTransformTo(_transform);
if (_isFacingAvatar) {
glm::quat rotation = Application::getInstance()->getCamera()->getOrientation();
rotation *= glm::angleAxis(glm::pi<float>(), IDENTITY_UP);
setRotation(rotation);
}
} }
void BillboardOverlay::update(float deltatime) { void Image3DOverlay::render(RenderArgs* args) {
setTransforms(_transform);
}
void BillboardOverlay::render(RenderArgs* args) {
if (!_texture) { if (!_texture) {
_isLoaded = true; _isLoaded = true;
_texture = DependencyManager::get<TextureCache>()->getTexture(_url); _texture = DependencyManager::get<TextureCache>()->getTexture(_url);
} }
if (!_visible || !_texture || !_texture->isLoaded()) { if (!_visible || !getParentVisible() || !_texture || !_texture->isLoaded()) {
return; return;
} }
Q_ASSERT(args->_batch); Q_ASSERT(args->_batch);
auto batch = args->_batch; gpu::Batch* batch = args->_batch;
float imageWidth = _texture->getWidth(); float imageWidth = _texture->getWidth();
float imageHeight = _texture->getHeight(); float imageHeight = _texture->getHeight();
@ -98,9 +87,10 @@ void BillboardOverlay::render(RenderArgs* args) {
xColor color = getColor(); xColor color = getColor();
float alpha = getAlpha(); float alpha = getAlpha();
setTransforms(_transform); applyTransformTo(_transform, true);
Transform transform = _transform; Transform transform = _transform;
transform.postScale(glm::vec3(getDimensions(), 1.0f)); transform.postScale(glm::vec3(getDimensions(), 1.0f));
transform.postRotate(glm::angleAxis(glm::pi<float>(), IDENTITY_UP));
batch->setModelTransform(transform); batch->setModelTransform(transform);
batch->setResourceTexture(0, _texture->getGPUTexture()); 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 batch->setResourceTexture(0, args->_whiteTexture); // restore default white color after me
} }
void BillboardOverlay::setProperties(const QScriptValue &properties) { void Image3DOverlay::setProperties(const QScriptValue &properties) {
Planar3DOverlay::setProperties(properties); Billboard3DOverlay::setProperties(properties);
PanelAttachable::setProperties(properties);
QScriptValue urlValue = properties.property("url"); QScriptValue urlValue = properties.property("url");
if (urlValue.isValid()) { if (urlValue.isValid()) {
QString newURL = urlValue.toVariant().toString(); QString newURL = urlValue.toVariant().toString();
if (newURL != _url) { if (newURL != _url) {
setBillboardURL(newURL); setURL(newURL);
} }
} }
@ -156,50 +145,34 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
setClipFromSource(subImageRect); 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") { if (property == "url") {
return _url; return _url;
} }
if (property == "subImage") { if (property == "subImage") {
return qRectToScriptValue(_scriptEngine, _fromImage); return qRectToScriptValue(_scriptEngine, _fromImage);
} }
if (property == "isFacingAvatar") {
return _isFacingAvatar;
}
if (property == "offsetPosition") { if (property == "offsetPosition") {
return vec3toScriptValue(_scriptEngine, getOffsetPosition()); return vec3toScriptValue(_scriptEngine, getOffsetPosition());
} }
QScriptValue value = PanelAttachable::getProperty(_scriptEngine, property); return Billboard3DOverlay::getProperty(property);
if (value.isValid()) {
return value;
}
return Planar3DOverlay::getProperty(property);
} }
void BillboardOverlay::setURL(const QString& url) { void Image3DOverlay::setURL(const QString& url) {
setBillboardURL(url);
}
void BillboardOverlay::setBillboardURL(const QString& url) {
_url = url; _url = url;
_isLoaded = false; _isLoaded = false;
} }
bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face) { float& distance, BoxFace& face) {
if (_texture && _texture->isLoaded()) { if (_texture && _texture->isLoaded()) {
// Make sure position and rotation is updated. // 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(); bool isNull = _fromImage.isNull();
float width = isNull ? _texture->getWidth() : _fromImage.width(); float width = isNull ? _texture->getWidth() : _fromImage.width();
float height = isNull ? _texture->getHeight() : _fromImage.height(); float height = isNull ? _texture->getHeight() : _fromImage.height();
@ -212,6 +185,6 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v
return false; return false;
} }
BillboardOverlay* BillboardOverlay::createClone() const { Image3DOverlay* Image3DOverlay::createClone() const {
return new BillboardOverlay(this); return new Image3DOverlay(this);
} }

View file

@ -1,30 +1,31 @@
// //
// BillboardOverlay.h // Image3DOverlay.h
// //
// //
// Created by Clement on 7/1/14. // Created by Clement on 7/1/14.
// Modified and renamed by Zander Otavka on 8/4/15
// Copyright 2014 High Fidelity, Inc. // Copyright 2014 High Fidelity, Inc.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#ifndef hifi_BillboardOverlay_h #ifndef hifi_Image3DOverlay_h
#define hifi_BillboardOverlay_h #define hifi_Image3DOverlay_h
#include <TextureCache.h> #include <TextureCache.h>
#include "Planar3DOverlay.h" #include "Billboard3DOverlay.h"
#include "PanelAttachable.h"
class BillboardOverlay : public Planar3DOverlay, public PanelAttachable { class Image3DOverlay : public Billboard3DOverlay {
Q_OBJECT Q_OBJECT
public: public:
static QString const TYPE; static QString const TYPE;
virtual QString getType() const { return TYPE; } virtual QString getType() const { return TYPE; }
BillboardOverlay(); Image3DOverlay();
BillboardOverlay(const BillboardOverlay* billboardOverlay); Image3DOverlay(const Image3DOverlay* image3DOverlay);
virtual void render(RenderArgs* args); virtual void render(RenderArgs* args);
@ -32,28 +33,20 @@ public:
// setters // setters
void setURL(const QString& url); void setURL(const QString& url);
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } void setClipFromSource(const QRect& bounds) { _fromImage = bounds; }
virtual void setProperties(const QScriptValue& properties); virtual void setProperties(const QScriptValue& properties);
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; }
virtual QScriptValue getProperty(const QString& property); virtual QScriptValue getProperty(const QString& property);
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
virtual BillboardOverlay* createClone() const;
protected: virtual Image3DOverlay* createClone() const;
virtual void setTransforms(Transform& transform);
private: private:
void setBillboardURL(const QString& url);
QString _url; QString _url;
NetworkTexturePointer _texture; 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

View file

@ -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 <QVariant>
#include <RegisteredMetaTypes.h>
#include <DependencyManager.h>
#include <EntityScriptingInterface.h>
#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<AvatarManager>()->getMyAvatar()
->getPosition());
} else if (!_anchorPositionBindEntity.isNull()) {
transform.setTranslation(DependencyManager::get<EntityScriptingInterface>()
->getEntityTree()->findEntityByID(_anchorPositionBindEntity)
->getPosition());
} else {
transform.setTranslation(getAnchorPosition());
}
if (_anchorRotationBindMyAvatar) {
transform.setRotation(DependencyManager::get<AvatarManager>()->getMyAvatar()
->getOrientation());
} else if (!_anchorRotationBindEntity.isNull()) {
transform.setRotation(DependencyManager::get<EntityScriptingInterface>()
->getEntityTree()->findEntityByID(_anchorRotationBindEntity)
->getRotation());
} else {
transform.setRotation(getAnchorRotation());
}
transform.setScale(getAnchorScale());
transform.postTranslate(getOffsetPosition());
transform.postRotate(getOffsetRotation());
transform.postScale(getOffsetScale());
}
pointTransformAtCamera(transform, getOffsetRotation());
}
}

View file

@ -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 <memory>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QScriptValue>
#include <QUuid>
#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<OverlayPanel> 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<unsigned int>& 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<unsigned int> _children;
QScriptEngine* _scriptEngine;
};
#endif // hifi_OverlayPanel_h

View file

@ -18,7 +18,7 @@
#include <RegisteredMetaTypes.h> #include <RegisteredMetaTypes.h>
#include "Application.h" #include "Application.h"
#include "BillboardOverlay.h" #include "Image3DOverlay.h"
#include "Circle3DOverlay.h" #include "Circle3DOverlay.h"
#include "Cube3DOverlay.h" #include "Cube3DOverlay.h"
#include "ImageOverlay.h" #include "ImageOverlay.h"
@ -138,6 +138,8 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope
if (type == ImageOverlay::TYPE) { if (type == ImageOverlay::TYPE) {
thisOverlay = std::make_shared<ImageOverlay>(); thisOverlay = std::make_shared<ImageOverlay>();
} else if (type == Image3DOverlay::TYPE || type == "billboard") { // "billboard" for backwards compatibility
thisOverlay = std::make_shared<Image3DOverlay>();
} else if (type == TextOverlay::TYPE) { } else if (type == TextOverlay::TYPE) {
thisOverlay = std::make_shared<TextOverlay>(); thisOverlay = std::make_shared<TextOverlay>();
} else if (type == Text3DOverlay::TYPE) { } else if (type == Text3DOverlay::TYPE) {
@ -158,8 +160,6 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope
thisOverlay = std::make_shared<LocalModelsOverlay>(Application::getInstance()->getEntityClipboardRenderer()); thisOverlay = std::make_shared<LocalModelsOverlay>(Application::getInstance()->getEntityClipboardRenderer());
} else if (type == ModelOverlay::TYPE) { } else if (type == ModelOverlay::TYPE) {
thisOverlay = std::make_shared<ModelOverlay>(); thisOverlay = std::make_shared<ModelOverlay>();
} else if (type == BillboardOverlay::TYPE) {
thisOverlay = std::make_shared<BillboardOverlay>();
} }
if (thisOverlay) { if (thisOverlay) {
@ -200,7 +200,12 @@ unsigned int Overlays::cloneOverlay(unsigned int id) {
Overlay::Pointer thisOverlay = getOverlay(id); Overlay::Pointer thisOverlay = getOverlay(id);
if (thisOverlay) { if (thisOverlay) {
return addOverlay(Overlay::Pointer(thisOverlay->createClone())); unsigned int cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone()));
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(thisOverlay);
if (attachable && attachable->getParentPanel()) {
attachable->getParentPanel()->addChild(cloneId);
}
return cloneId;
} }
return 0; // Not found return 0; // Not found
@ -251,9 +256,9 @@ void Overlays::deleteOverlay(unsigned int id) {
} }
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlayToDelete); auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlayToDelete);
if (attachable && attachable->getAttachedPanel()) { if (attachable && attachable->getParentPanel()) {
attachable->getAttachedPanel()->removeChild(id); attachable->getParentPanel()->removeChild(id);
attachable->setAttachedPanel(nullptr); attachable->setParentPanel(nullptr);
} }
QWriteLocker lock(&_deleteLock); QWriteLocker lock(&_deleteLock);
@ -270,28 +275,42 @@ QString Overlays::getOverlayType(unsigned int overlayId) const {
return ""; return "";
} }
unsigned int Overlays::getAttachedPanel(unsigned int childId) const { unsigned int Overlays::getParentPanel(unsigned int childId) const {
Overlay::Pointer overlay = getOverlay(childId); Overlay::Pointer overlay = getOverlay(childId);
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlay); auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlay);
if (attachable) { 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; return 0;
} }
void Overlays::setAttachedPanel(unsigned int childId, unsigned int panelId) { void Overlays::setParentPanel(unsigned int childId, unsigned int panelId) {
Overlay::Pointer overlay = getOverlay(childId); auto attachable = std::dynamic_pointer_cast<PanelAttachable>(getOverlay(childId));
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlay);
if (attachable) { if (attachable) {
if (_panels.contains(panelId)) { if (_panels.contains(panelId)) {
auto panel = _panels[panelId]; auto panel = getPanel(panelId);
panel->addChild(childId); panel->addChild(childId);
attachable->setAttachedPanel(panel); attachable->setParentPanel(panel);
} else { } else {
auto panel = attachable->getAttachedPanel(); auto panel = attachable->getParentPanel();
if (panel) { if (panel) {
panel->removeChild(childId); 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);
} }
} }
} }
@ -510,7 +529,7 @@ QSizeF Overlays::textSize(unsigned int id, const QString& text) const {
return QSizeF(0.0f, 0.0f); return QSizeF(0.0f, 0.0f);
} }
unsigned int Overlays::addPanel(FloatingUIPanel::Pointer panel) { unsigned int Overlays::addPanel(OverlayPanel::Pointer panel) {
QWriteLocker lock(&_lock); QWriteLocker lock(&_lock);
unsigned int thisID = _nextOverlayID; unsigned int thisID = _nextOverlayID;
@ -521,7 +540,7 @@ unsigned int Overlays::addPanel(FloatingUIPanel::Pointer panel) {
} }
unsigned int Overlays::addPanel(const QScriptValue& properties) { unsigned int Overlays::addPanel(const QScriptValue& properties) {
FloatingUIPanel::Pointer panel = std::make_shared<FloatingUIPanel>(); OverlayPanel::Pointer panel = std::make_shared<OverlayPanel>();
panel->init(_scriptEngine); panel->init(_scriptEngine);
panel->setProperties(properties); panel->setProperties(properties);
return addPanel(panel); return addPanel(panel);
@ -536,7 +555,7 @@ void Overlays::editPanel(unsigned int panelId, const QScriptValue& properties) {
OverlayPropertyResult Overlays::getPanelProperty(unsigned int panelId, const QString& property) { OverlayPropertyResult Overlays::getPanelProperty(unsigned int panelId, const QString& property) {
OverlayPropertyResult result; OverlayPropertyResult result;
if (_panels.contains(panelId)) { if (_panels.contains(panelId)) {
FloatingUIPanel::Pointer thisPanel = _panels[panelId]; OverlayPanel::Pointer thisPanel = getPanel(panelId);
QReadLocker lock(&_lock); QReadLocker lock(&_lock);
result.value = thisPanel->getProperty(property); result.value = thisPanel->getProperty(property);
} }
@ -545,7 +564,7 @@ OverlayPropertyResult Overlays::getPanelProperty(unsigned int panelId, const QSt
void Overlays::deletePanel(unsigned int panelId) { void Overlays::deletePanel(unsigned int panelId) {
FloatingUIPanel::Pointer panelToDelete; OverlayPanel::Pointer panelToDelete;
{ {
QWriteLocker lock(&_lock); QWriteLocker lock(&_lock);
@ -557,8 +576,14 @@ void Overlays::deletePanel(unsigned int panelId) {
} }
while (!panelToDelete->getChildren().isEmpty()) { while (!panelToDelete->getChildren().isEmpty()) {
deleteOverlay(panelToDelete->popLastChild()); unsigned int childId = panelToDelete->popLastChild();
deleteOverlay(childId);
deletePanel(childId);
} }
emit panelDeleted(panelId); emit panelDeleted(panelId);
} }
bool Overlays::isAddedOverlay(unsigned int id) {
return _overlaysHUD.contains(id) || _overlaysWorld.contains(id);
}

View file

@ -5,7 +5,7 @@
// Modified by Zander Otavka on 7/15/15 // Modified by Zander Otavka on 7/15/15
// Copyright 2014 High Fidelity, Inc. // 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 // 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`. // object oriented abstraction layer found in `examples/libraries/overlayUtils.js`.
@ -22,7 +22,7 @@
#include "Overlay.h" #include "Overlay.h"
#include "FloatingUIPanel.h" #include "OverlayPanel.h"
#include "PanelAttachable.h" #include "PanelAttachable.h"
class PickRay; class PickRay;
@ -67,7 +67,7 @@ public:
void renderHUD(RenderArgs* renderArgs); void renderHUD(RenderArgs* renderArgs);
Overlay::Pointer getOverlay(unsigned int id) const; 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: public slots:
/// adds an overlay with the specific properties /// adds an overlay with the specific properties
@ -90,8 +90,8 @@ public slots:
/// get the string type of the overlay used in addOverlay /// get the string type of the overlay used in addOverlay
QString getOverlayType(unsigned int overlayId) const; QString getOverlayType(unsigned int overlayId) const;
unsigned int getAttachedPanel(unsigned int childId) const; unsigned int getParentPanel(unsigned int childId) const;
void setAttachedPanel(unsigned int childId, unsigned int panelId); 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 /// 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); unsigned int getOverlayAtPoint(const glm::vec2& point);
@ -111,7 +111,7 @@ public slots:
/// adds a panel that has already been created /// 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 /// creates and adds a panel based on a set of properties
unsigned int addPanel(const QScriptValue& properties); unsigned int addPanel(const QScriptValue& properties);
@ -125,6 +125,12 @@ public slots:
/// deletes a panel and all child overlays /// deletes a panel and all child overlays
void deletePanel(unsigned int panelId); 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: signals:
void overlayDeleted(unsigned int id); void overlayDeleted(unsigned int id);
void panelDeleted(unsigned int id); void panelDeleted(unsigned int id);
@ -134,7 +140,7 @@ private:
QMap<unsigned int, Overlay::Pointer> _overlaysHUD; QMap<unsigned int, Overlay::Pointer> _overlaysHUD;
QMap<unsigned int, Overlay::Pointer> _overlaysWorld; QMap<unsigned int, Overlay::Pointer> _overlaysWorld;
QMap<unsigned int, FloatingUIPanel::Pointer> _panels; QMap<unsigned int, OverlayPanel::Pointer> _panels;
QList<Overlay::Pointer> _overlaysToDelete; QList<Overlay::Pointer> _overlaysToDelete;
unsigned int _nextOverlayID; unsigned int _nextOverlayID;

View file

@ -18,7 +18,7 @@
#include <LODManager.h> #include <LODManager.h>
#include <render/Scene.h> #include <render/Scene.h>
#include "BillboardOverlay.h" #include "Image3DOverlay.h"
#include "Circle3DOverlay.h" #include "Circle3DOverlay.h"
#include "Cube3DOverlay.h" #include "Cube3DOverlay.h"
#include "ImageOverlay.h" #include "ImageOverlay.h"

View file

@ -13,25 +13,13 @@
#include <RegisteredMetaTypes.h> #include <RegisteredMetaTypes.h>
PanelAttachable::PanelAttachable() : #include "OverlayPanel.h"
_attachedPanel(nullptr),
_facingRotation(1, 0, 0, 0)
{
}
PanelAttachable::PanelAttachable(const PanelAttachable* panelAttachable) : bool PanelAttachable::getParentVisible() const {
_attachedPanel(panelAttachable->_attachedPanel), if (getParentPanel()) {
_offsetPosition(panelAttachable->_offsetPosition), return getParentPanel()->getVisible() && getParentPanel()->getParentVisible();
_facingRotation(panelAttachable->_facingRotation) } else {
{ return true;
}
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());
} }
} }
@ -39,42 +27,60 @@ QScriptValue PanelAttachable::getProperty(QScriptEngine* scriptEngine, const QSt
if (property == "offsetPosition") { if (property == "offsetPosition") {
return vec3toScriptValue(scriptEngine, getOffsetPosition()); return vec3toScriptValue(scriptEngine, getOffsetPosition());
} }
if (property == "facingRotation") { if (property == "offsetRotation") {
return quatToScriptValue(scriptEngine, getFacingRotation()); return quatToScriptValue(scriptEngine, getOffsetRotation());
}
if (property == "offsetScale") {
return vec3toScriptValue(scriptEngine, getOffsetScale());
} }
return QScriptValue(); return QScriptValue();
} }
void PanelAttachable::setProperties(const QScriptValue &properties) { void PanelAttachable::setProperties(const QScriptValue &properties) {
QScriptValue offsetPosition = properties.property("offsetPosition"); QScriptValue offsetPosition = properties.property("offsetPosition");
if (offsetPosition.isValid()) { if (offsetPosition.isValid() &&
QScriptValue x = offsetPosition.property("x"); offsetPosition.property("x").isValid() &&
QScriptValue y = offsetPosition.property("y"); offsetPosition.property("y").isValid() &&
QScriptValue z = offsetPosition.property("z"); offsetPosition.property("z").isValid()) {
glm::vec3 newPosition;
if (x.isValid() && y.isValid() && z.isValid()) { vec3FromScriptValue(offsetPosition, newPosition);
glm::vec3 newPosition; setOffsetPosition(newPosition);
newPosition.x = x.toVariant().toFloat();
newPosition.y = y.toVariant().toFloat();
newPosition.z = z.toVariant().toFloat();
setOffsetPosition(newPosition);
}
} }
QScriptValue facingRotation = properties.property("facingRotation"); QScriptValue offsetRotation = properties.property("offsetRotation");
if (facingRotation.isValid()) { if (offsetRotation.isValid() &&
QScriptValue x = facingRotation.property("x"); offsetRotation.property("x").isValid() &&
QScriptValue y = facingRotation.property("y"); offsetRotation.property("y").isValid() &&
QScriptValue z = facingRotation.property("z"); offsetRotation.property("z").isValid() &&
QScriptValue w = facingRotation.property("w"); offsetRotation.property("w").isValid()) {
glm::quat newRotation;
quatFromScriptValue(offsetRotation, newRotation);
setOffsetRotation(newRotation);
}
if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { QScriptValue offsetScale = properties.property("offsetScale");
glm::quat newRotation; if (offsetScale.isValid()) {
newRotation.x = x.toVariant().toFloat(); if (offsetScale.property("x").isValid() &&
newRotation.y = y.toVariant().toFloat(); offsetScale.property("y").isValid() &&
newRotation.z = z.toVariant().toFloat(); offsetScale.property("z").isValid()) {
newRotation.w = w.toVariant().toFloat(); glm::vec3 newScale;
setFacingRotation(newRotation); 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());
} }
} }
} }

View file

@ -12,34 +12,42 @@
#ifndef hifi_PanelAttachable_h #ifndef hifi_PanelAttachable_h
#define hifi_PanelAttachable_h #define hifi_PanelAttachable_h
#include "FloatingUIPanel.h" #include <memory>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <Transform.h> #include <Transform.h>
#include <QScriptValue>
#include <QScriptEngine>
#include <QUuid>
class OverlayPanel;
class PanelAttachable { class PanelAttachable {
public: public:
PanelAttachable(); // getters
PanelAttachable(const PanelAttachable* panelAttachable); std::shared_ptr<OverlayPanel> 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; } // setters
glm::vec3 getOffsetPosition() const { return _offsetPosition; } void setParentPanel(std::shared_ptr<OverlayPanel> panel) { _parentPanel = panel; }
glm::quat getFacingRotation() const { return _facingRotation; } void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); }
void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); }
void setAttachedPanel(FloatingUIPanel::Pointer panel) { _attachedPanel = panel; } void setOffsetScale(float scale) { _offset.setScale(scale); }
void setOffsetPosition(const glm::vec3& position) { _offsetPosition = position; } void setOffsetScale(const glm::vec3& scale) { _offset.setScale(scale); }
void setFacingRotation(const glm::quat& rotation) { _facingRotation = rotation; }
protected:
QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property); QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property);
void setProperties(const QScriptValue& properties); void setProperties(const QScriptValue& properties);
protected: virtual void applyTransformTo(Transform& transform, bool force = false);
virtual void setTransforms(Transform& transform); quint64 _transformExpiry = 0;
private: private:
FloatingUIPanel::Pointer _attachedPanel; std::shared_ptr<OverlayPanel> _parentPanel = nullptr;
glm::vec3 _offsetPosition; Transform _offset;
glm::quat _facingRotation;
}; };
#endif // hifi_PanelAttachable_h #endif // hifi_PanelAttachable_h

View file

@ -32,14 +32,13 @@ Text3DOverlay::Text3DOverlay() :
_leftMargin(DEFAULT_MARGIN), _leftMargin(DEFAULT_MARGIN),
_topMargin(DEFAULT_MARGIN), _topMargin(DEFAULT_MARGIN),
_rightMargin(DEFAULT_MARGIN), _rightMargin(DEFAULT_MARGIN),
_bottomMargin(DEFAULT_MARGIN), _bottomMargin(DEFAULT_MARGIN)
_isFacingAvatar(false)
{ {
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
} }
Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
Planar3DOverlay(text3DOverlay), Billboard3DOverlay(text3DOverlay),
_text(text3DOverlay->_text), _text(text3DOverlay->_text),
_backgroundColor(text3DOverlay->_backgroundColor), _backgroundColor(text3DOverlay->_backgroundColor),
_backgroundAlpha(text3DOverlay->_backgroundAlpha), _backgroundAlpha(text3DOverlay->_backgroundAlpha),
@ -47,8 +46,7 @@ Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
_leftMargin(text3DOverlay->_leftMargin), _leftMargin(text3DOverlay->_leftMargin),
_topMargin(text3DOverlay->_topMargin), _topMargin(text3DOverlay->_topMargin),
_rightMargin(text3DOverlay->_rightMargin), _rightMargin(text3DOverlay->_rightMargin),
_bottomMargin(text3DOverlay->_bottomMargin), _bottomMargin(text3DOverlay->_bottomMargin)
_isFacingAvatar(text3DOverlay->_isFacingAvatar)
{ {
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
} }
@ -76,41 +74,30 @@ xColor Text3DOverlay::getBackgroundColor() {
return result; return result;
} }
void Text3DOverlay::update(float deltatime) {
applyTransformTo(_transform);
}
void Text3DOverlay::render(RenderArgs* args) { void Text3DOverlay::render(RenderArgs* args) {
if (!_visible) { if (!_visible || !getParentVisible()) {
return; // do nothing if we're not visible return; // do nothing if we're not visible
} }
Q_ASSERT(args->_batch); Q_ASSERT(args->_batch);
auto& batch = *args->_batch; auto& batch = *args->_batch;
glm::quat rotation; applyTransformTo(_transform, true);
batch.setModelTransform(_transform);
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);
const float MAX_COLOR = 255.0f; const float MAX_COLOR = 255.0f;
xColor backgroundColor = getBackgroundColor(); xColor backgroundColor = getBackgroundColor();
glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR,
getBackgroundAlpha()); backgroundColor.blue / MAX_COLOR, getBackgroundAlpha());
glm::vec2 dimensions = getDimensions(); glm::vec2 dimensions = getDimensions();
glm::vec2 halfDimensions = dimensions * 0.5f; 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 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
glm::vec3 bottomRight(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 clipMinimum(0.0f, 0.0f);
glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor,
(dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor);
transform.setTranslation(getPosition()); Transform transform = _transform;
transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin) , halfDimensions.y - _topMargin, 0.01f)); transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin),
halfDimensions.y - _topMargin, 0.001f));
transform.setScale(scaleFactor); transform.setScale(scaleFactor);
batch.setModelTransform(transform); 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); _textRenderer->draw(batch, 0, 0, _text, textColor);
batch.setPipeline(DrawOverlay3D::getOpaquePipeline());
} }
void Text3DOverlay::setProperties(const QScriptValue& properties) { void Text3DOverlay::setProperties(const QScriptValue& properties) {
Planar3DOverlay::setProperties(properties); Billboard3DOverlay::setProperties(properties);
QScriptValue text = properties.property("text"); QScriptValue text = properties.property("text");
if (text.isValid()) { if (text.isValid()) {
@ -180,12 +167,6 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) {
if (properties.property("bottomMargin").isValid()) { if (properties.property("bottomMargin").isValid()) {
setBottomMargin(properties.property("bottomMargin").toVariant().toFloat()); setBottomMargin(properties.property("bottomMargin").toVariant().toFloat());
} }
QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar");
if (isFacingAvatarValue.isValid()) {
_isFacingAvatar = isFacingAvatarValue.toVariant().toBool();
}
} }
QScriptValue Text3DOverlay::getProperty(const QString& property) { QScriptValue Text3DOverlay::getProperty(const QString& property) {
@ -213,10 +194,8 @@ QScriptValue Text3DOverlay::getProperty(const QString& property) {
if (property == "bottomMargin") { if (property == "bottomMargin") {
return _bottomMargin; return _bottomMargin;
} }
if (property == "isFacingAvatar") {
return _isFacingAvatar; return Billboard3DOverlay::getProperty(property);
}
return Planar3DOverlay::getProperty(property);
} }
Text3DOverlay* Text3DOverlay::createClone() const { Text3DOverlay* Text3DOverlay::createClone() const {
@ -232,3 +211,7 @@ QSizeF Text3DOverlay::textSize(const QString& text) const {
return QSizeF(extents.x, extents.y) * pointToWorldScale; 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);
}

View file

@ -13,11 +13,11 @@
#include <QString> #include <QString>
#include "Planar3DOverlay.h" #include "Billboard3DOverlay.h"
class TextRenderer3D; class TextRenderer3D;
class Text3DOverlay : public Planar3DOverlay { class Text3DOverlay : public Billboard3DOverlay {
Q_OBJECT Q_OBJECT
public: public:
@ -29,6 +29,8 @@ public:
~Text3DOverlay(); ~Text3DOverlay();
virtual void render(RenderArgs* args); virtual void render(RenderArgs* args);
virtual void update(float deltatime);
// getters // getters
const QString& getText() const { return _text; } const QString& getText() const { return _text; }
float getLineHeight() const { return _lineHeight; } float getLineHeight() const { return _lineHeight; }
@ -36,7 +38,6 @@ public:
float getTopMargin() const { return _topMargin; } float getTopMargin() const { return _topMargin; }
float getRightMargin() const { return _rightMargin; } float getRightMargin() const { return _rightMargin; }
float getBottomMargin() const { return _bottomMargin; } float getBottomMargin() const { return _bottomMargin; }
bool getIsFacingAvatar() const { return _isFacingAvatar; }
xColor getBackgroundColor(); xColor getBackgroundColor();
float getBackgroundAlpha() const { return _backgroundAlpha; } float getBackgroundAlpha() const { return _backgroundAlpha; }
@ -47,13 +48,14 @@ public:
void setTopMargin(float margin) { _topMargin = margin; } void setTopMargin(float margin) { _topMargin = margin; }
void setRightMargin(float margin) { _rightMargin = margin; } void setRightMargin(float margin) { _rightMargin = margin; }
void setBottomMargin(float margin) { _bottomMargin = margin; } void setBottomMargin(float margin) { _bottomMargin = margin; }
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
virtual void setProperties(const QScriptValue& properties); virtual void setProperties(const QScriptValue& properties);
virtual QScriptValue getProperty(const QString& property); virtual QScriptValue getProperty(const QString& property);
QSizeF textSize(const QString& test) const; // Meters 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; virtual Text3DOverlay* createClone() const;
private: private:
@ -67,7 +69,6 @@ private:
float _topMargin; float _topMargin;
float _rightMargin; float _rightMargin;
float _bottomMargin; float _bottomMargin;
bool _isFacingAvatar;
}; };

View file

@ -91,6 +91,10 @@ QVector<FBXAnimationFrame> Animation::getFrames() const {
return _geometry.animationFrames; return _geometry.animationFrames;
} }
const QVector<FBXAnimationFrame>& Animation::getFramesReference() const {
return _geometry.animationFrames;
}
void Animation::setGeometry(const FBXGeometry& geometry) { void Animation::setGeometry(const FBXGeometry& geometry) {
_geometry = geometry; _geometry = geometry;
finishedLoading(true); finishedLoading(true);

View file

@ -57,6 +57,8 @@ public:
Q_INVOKABLE QStringList getJointNames() const; Q_INVOKABLE QStringList getJointNames() const;
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const; Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
const QVector<FBXAnimationFrame>& getFramesReference() const;
protected: protected:

View file

@ -227,24 +227,30 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
if (hasModel()) { if (hasModel()) {
if (_model) { if (_model) {
if (QUrl(getModelURL()) != _model->getURL()) { if (getModelURL() != _model->getURLAsString()) {
qDebug() << "Updating model URL: " << getModelURL(); qDebug() << "Updating model URL: " << getModelURL();
_model->setURL(getModelURL()); _model->setURL(getModelURL());
} }
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
// check to see if when we added our models to the scene they were ready, if they were not ready, then // check to see if when we added our models to the scene they were ready, if they were not ready, then
// fix them up in the scene // fix them up in the scene
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
render::PendingChanges pendingChanges;
if (_model->needsFixupInScene()) { if (_model->needsFixupInScene()) {
render::PendingChanges pendingChanges;
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, pendingChanges);
render::Item::Status::Getters statusGetters; render::Item::Status::Getters statusGetters;
makeEntityItemStatusGetters(this, statusGetters); makeEntityItemStatusGetters(this, statusGetters);
_model->addToScene(scene, pendingChanges, statusGetters); _model->addToScene(scene, pendingChanges, statusGetters);
}
scene->enqueuePendingChanges(pendingChanges);
scene->enqueuePendingChanges(pendingChanges);
}
// FIXME: this seems like it could be optimized if we tracked our last known visible state in
// the renderable item. As it stands now the model checks it's visible/invisible state
// so most of the time we don't do anything in this function.
_model->setVisibleInScene(getVisible(), scene); _model->setVisibleInScene(getVisible(), scene);
} }
@ -269,7 +275,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
} }
if (jointsMapped()) { if (jointsMapped()) {
QVector<glm::quat> frameData = getAnimationFrame(); auto frameData = getAnimationFrame();
for (int i = 0; i < frameData.size(); i++) { for (int i = 0; i < frameData.size(); i++) {
_model->setJointState(i, true, frameData[i]); _model->setJointState(i, true, frameData[i]);
} }

View file

@ -60,7 +60,7 @@ public:
virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); } virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); }
void setEntityTree(EntityTree* modelTree); void setEntityTree(EntityTree* modelTree);
EntityTree* getEntityTree(EntityTree*) { return _entityTree; } EntityTree* getEntityTree() { return _entityTree; }
public slots: public slots:

View file

@ -39,6 +39,7 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityI
setProperties(properties); setProperties(properties);
_lastAnimated = usecTimestampNow(); _lastAnimated = usecTimestampNow();
_jointMappingCompleted = false; _jointMappingCompleted = false;
_lastKnownFrameIndex = -1;
_color[0] = _color[1] = _color[2] = 0; _color[0] = _color[1] = _color[2] = 0;
} }
@ -217,15 +218,17 @@ void ModelEntityItem::mapJoints(const QStringList& modelJointNames) {
} }
} }
QVector<glm::quat> ModelEntityItem::getAnimationFrame() { const QVector<glm::quat>& ModelEntityItem::getAnimationFrame() {
QVector<glm::quat> frameData;
if (!hasAnimation() || !_jointMappingCompleted) { if (!hasAnimation() || !_jointMappingCompleted) {
return frameData; return _lastKnownFrameData;
} }
AnimationPointer myAnimation = getAnimation(_animationURL); AnimationPointer myAnimation = getAnimation(_animationURL); // FIXME: this could be optimized
if (myAnimation && myAnimation->isLoaded()) { if (myAnimation && myAnimation->isLoaded()) {
QVector<FBXAnimationFrame> frames = myAnimation->getFrames();
const QVector<FBXAnimationFrame>& frames = myAnimation->getFramesReference(); // NOTE: getFrames() is too heavy
int frameCount = frames.size(); int frameCount = frames.size();
if (frameCount > 0) { if (frameCount > 0) {
int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount; int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount;
@ -233,18 +236,22 @@ QVector<glm::quat> ModelEntityItem::getAnimationFrame() {
animationFrameIndex = 0; animationFrameIndex = 0;
} }
QVector<glm::quat> rotations = frames[animationFrameIndex].rotations; if (animationFrameIndex != _lastKnownFrameIndex) {
_lastKnownFrameIndex = animationFrameIndex;
const QVector<glm::quat>& rotations = frames[animationFrameIndex].rotations;
frameData.resize(_jointMapping.size()); _lastKnownFrameData.resize(_jointMapping.size());
for (int j = 0; j < _jointMapping.size(); j++) { for (int j = 0; j < _jointMapping.size(); j++) {
int rotationIndex = _jointMapping[j]; int rotationIndex = _jointMapping[j];
if (rotationIndex != -1 && rotationIndex < rotations.size()) { if (rotationIndex != -1 && rotationIndex < rotations.size()) {
frameData[j] = rotations[rotationIndex]; _lastKnownFrameData[j] = rotations[rotationIndex];
}
} }
} }
} }
} }
return frameData; return _lastKnownFrameData;
} }
bool ModelEntityItem::isAnimatingSomething() const { bool ModelEntityItem::isAnimatingSomething() const {

View file

@ -106,7 +106,7 @@ public:
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
void mapJoints(const QStringList& modelJointNames); void mapJoints(const QStringList& modelJointNames);
QVector<glm::quat> getAnimationFrame(); const QVector<glm::quat>& getAnimationFrame();
bool jointsMapped() const { return _jointMappingCompleted; } bool jointsMapped() const { return _jointMappingCompleted; }
bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); } bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); }
@ -123,6 +123,9 @@ public:
static void cleanupLoadedAnimations(); static void cleanupLoadedAnimations();
protected: protected:
QVector<glm::quat> _lastKnownFrameData;
int _lastKnownFrameIndex;
bool isAnimatingSomething() const; bool isAnimatingSomething() const;

View file

@ -47,9 +47,6 @@ public:
/// gets the shadow view frustum for rendering the view state /// gets the shadow view frustum for rendering the view state
virtual ViewFrustum* getShadowViewFrustum() = 0; virtual ViewFrustum* getShadowViewFrustum() = 0;
virtual bool getShadowsEnabled() = 0;
virtual bool getCascadeShadowsEnabled() = 0;
virtual QThread* getMainThread() = 0; virtual QThread* getMainThread() = 0;
virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera) = 0; virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera) = 0;

View file

@ -277,13 +277,19 @@ void DeferredLightingEffect::render(RenderArgs* args) {
auto& program = _directionalLight; auto& program = _directionalLight;
const LightLocations* locations = &_directionalLightLocations; 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) { if (shadowsEnabled) {
batch.setResourceTexture(4, framebufferCache->getShadowFramebuffer()->getDepthStencilBuffer()); batch.setResourceTexture(4, framebufferCache->getShadowFramebuffer()->getDepthStencilBuffer());
program = _directionalLightShadowMap; program = _directionalLightShadowMap;
locations = &_directionalLightShadowMapLocations; locations = &_directionalLightShadowMapLocations;
if (_viewState->getCascadeShadowsEnabled()) { if (cascadeShadowsEnabled) {
program = _directionalLightCascadedShadowMap; program = _directionalLightCascadedShadowMap;
locations = &_directionalLightCascadedShadowMapLocations; locations = &_directionalLightCascadedShadowMapLocations;
if (useSkyboxCubemap) { if (useSkyboxCubemap) {

View file

@ -54,6 +54,7 @@ static int modelPointerTypeId = qRegisterMetaType<QPointer<Model> >();
static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >(); static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >();
static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >(); static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();
float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f;
#define HTTP_INVALID_COM "http://invalid.com"
Model::Model(RigPointer rig, QObject* parent) : Model::Model(RigPointer rig, QObject* parent) :
QObject(parent), QObject(parent),
@ -67,7 +68,8 @@ Model::Model(RigPointer rig, QObject* parent) :
_cauterizeBones(false), _cauterizeBones(false),
_lodDistance(0.0f), _lodDistance(0.0f),
_pupilDilation(0.0f), _pupilDilation(0.0f),
_url("http://invalid.com"), _url(HTTP_INVALID_COM),
_urlAsString(HTTP_INVALID_COM),
_isVisible(true), _isVisible(true),
_blendNumber(0), _blendNumber(0),
_appliedBlendNumber(0), _appliedBlendNumber(0),
@ -181,17 +183,12 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model:
locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices");
locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");
locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");
locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap");
locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); locations.specularTextureUnit = program->getTextures().findLocation("specularMap");
locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer");
locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer");
locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices"); locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices");
locations.clusterIndices = program->getInputs().findLocation("inSkinClusterIndex"); locations.clusterIndices = program->getInputs().findLocation("inSkinClusterIndex");
locations.clusterWeights = program->getInputs().findLocation("inSkinClusterWeight"); locations.clusterWeights = program->getInputs().findLocation("inSkinClusterWeight");
} }
@ -1083,6 +1080,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo
invalidCalculatedMeshBoxes(); invalidCalculatedMeshBoxes();
_url = url; _url = url;
_urlAsString = _url.toString();
onInvalidate(); onInvalidate();
@ -1866,8 +1864,9 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
batch._glUniform1f(locations->glowIntensity, DEFAULT_GLOW_INTENSITY); batch._glUniform1f(locations->glowIntensity, DEFAULT_GLOW_INTENSITY);
} }
if ((locations->normalFittingMapUnit > -1)) { if ((locations->normalFittingMapUnit > -1)) {
batch.setResourceTexture(locations->normalFittingMapUnit, DependencyManager::get<TextureCache>()->getNormalFittingTexture()); batch.setResourceTexture(locations->normalFittingMapUnit,
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
} }
} }

View file

@ -74,6 +74,7 @@ public:
Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl(), Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl(),
bool retainCurrent = false, bool delayLoad = false); bool retainCurrent = false, bool delayLoad = false);
const QUrl& getURL() const { return _url; } const QUrl& getURL() const { return _url; }
const QString& getURLAsString() const { return _urlAsString; }
// new Scene/Engine rendering support // new Scene/Engine rendering support
void setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scene); void setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scene);
@ -328,6 +329,7 @@ private:
QVector<float> _blendshapeCoefficients; QVector<float> _blendshapeCoefficients;
QUrl _url; QUrl _url;
QString _urlAsString;
QUrl _collisionUrl; QUrl _collisionUrl;
bool _isVisible; bool _isVisible;