mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 04:08:13 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into fix/qml-thread
This commit is contained in:
commit
d3d0f229aa
33 changed files with 690 additions and 299 deletions
|
@ -151,7 +151,7 @@
|
||||||
data.properties[group][property] = {
|
data.properties[group][property] = {
|
||||||
x: elX.value,
|
x: elX.value,
|
||||||
y: elY.value,
|
y: elY.value,
|
||||||
z: elZ.value,
|
z: elZ ? elZ.value : 0,
|
||||||
};
|
};
|
||||||
EventBridge.emitWebEvent(JSON.stringify(data));
|
EventBridge.emitWebEvent(JSON.stringify(data));
|
||||||
}
|
}
|
||||||
|
@ -683,7 +683,6 @@
|
||||||
elZoneKeyLightAmbientIntensity.value = properties.keyLight.ambientIntensity.toFixed(2);
|
elZoneKeyLightAmbientIntensity.value = properties.keyLight.ambientIntensity.toFixed(2);
|
||||||
elZoneKeyLightDirectionX.value = properties.keyLight.direction.x.toFixed(2);
|
elZoneKeyLightDirectionX.value = properties.keyLight.direction.x.toFixed(2);
|
||||||
elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2);
|
elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2);
|
||||||
elZoneKeyLightDirectionZ.value = properties.keyLight.direction.z.toFixed(2);
|
|
||||||
elZoneKeyLightAmbientURL.value = properties.keyLight.ambientURL;
|
elZoneKeyLightAmbientURL.value = properties.keyLight.ambientURL;
|
||||||
|
|
||||||
|
|
||||||
|
@ -937,12 +936,11 @@
|
||||||
elZoneKeyLightColorBlue.addEventListener('change', zoneKeyLightColorChangeFunction);
|
elZoneKeyLightColorBlue.addEventListener('change', zoneKeyLightColorChangeFunction);
|
||||||
elZoneKeyLightIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','intensity'));
|
elZoneKeyLightIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','intensity'));
|
||||||
elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','ambientIntensity'));
|
elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','ambientIntensity'));
|
||||||
var zoneKeyLightDirectionChangeFunction = createEmitGroupVec3PropertyUpdateFunction('keyLight','direction', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY, elZoneKeyLightDirectionZ);
|
elZoneKeyLightAmbientURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('keyLight','ambientURL'));
|
||||||
|
var zoneKeyLightDirectionChangeFunction = createEmitGroupVec3PropertyUpdateFunction('keyLight','direction', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY);
|
||||||
elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction);
|
elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction);
|
||||||
elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction);
|
elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction);
|
||||||
elZoneKeyLightDirectionZ.addEventListener('change', zoneKeyLightDirectionChangeFunction);
|
|
||||||
elZoneKeyLightAmbientURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('keyLight','ambientURL'));
|
|
||||||
|
|
||||||
elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','latitude'));
|
elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','latitude'));
|
||||||
elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','longitude'));
|
elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','longitude'));
|
||||||
elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','altitude'));
|
elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','altitude'));
|
||||||
|
@ -1170,9 +1168,8 @@
|
||||||
<div class="zone-section keyLight-section property">
|
<div class="zone-section keyLight-section property">
|
||||||
<div class="label">Light Direction</div>
|
<div class="label">Light Direction</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<div class="input-area">Pitch <input class="coord" type="number" id="property-zone-key-light-direction-x"></div>
|
<div class="input-area">Altitude <input class="coord" type="number" id="property-zone-key-light-direction-x"></div>
|
||||||
<div class="input-area">Yaw <input class="coord" type="number" id="property-zone-key-light-direction-y"></div>
|
<div class="input-area">Azimuth <input class="coord" type="number" id="property-zone-key-light-direction-y"></div>
|
||||||
<div class="input-area">Roll <input class="coord" type="number" id="property-zone-key-light-direction-z"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ var deletingVoxels = false;
|
||||||
var addingSpheres = false;
|
var addingSpheres = false;
|
||||||
var deletingSpheres = false;
|
var deletingSpheres = false;
|
||||||
|
|
||||||
var offAlpha = 0.5;
|
var offAlpha = 0.8;
|
||||||
var onAlpha = 0.9;
|
var onAlpha = 1.0;
|
||||||
var editSphereRadius = 4;
|
var editSphereRadius = 4;
|
||||||
|
|
||||||
function floorVector(v) {
|
function floorVector(v) {
|
||||||
|
@ -48,52 +48,47 @@ var toolBar = (function () {
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: onAlpha,
|
alpha: onAlpha,
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
}, false);
|
||||||
|
|
||||||
addVoxelButton = toolBar.addTool({
|
addVoxelButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "voxel-add.svg",
|
imageURL: toolIconUrl + "voxel-add.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: offAlpha,
|
alpha: offAlpha,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
}, false);
|
||||||
|
|
||||||
deleteVoxelButton = toolBar.addTool({
|
deleteVoxelButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "voxel-delete.svg",
|
imageURL: toolIconUrl + "voxel-delete.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: offAlpha,
|
alpha: offAlpha,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
}, false);
|
||||||
|
|
||||||
addSphereButton = toolBar.addTool({
|
addSphereButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "sphere-add.svg",
|
imageURL: toolIconUrl + "sphere-add.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: offAlpha,
|
alpha: offAlpha,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
}, false);
|
||||||
|
|
||||||
deleteSphereButton = toolBar.addTool({
|
deleteSphereButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "sphere-delete.svg",
|
imageURL: toolIconUrl + "sphere-delete.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: offAlpha,
|
alpha: offAlpha,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
}, false);
|
||||||
|
|
||||||
addTerrainButton = toolBar.addTool({
|
addTerrainButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "voxel-terrain.svg",
|
imageURL: toolIconUrl + "voxel-terrain.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: onAlpha,
|
alpha: onAlpha,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
}, false);
|
||||||
|
|
||||||
that.setActive(false);
|
that.setActive(false);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +188,6 @@ var toolBar = (function () {
|
||||||
|
|
||||||
that.cleanup = function () {
|
that.cleanup = function () {
|
||||||
toolBar.cleanup();
|
toolBar.cleanup();
|
||||||
// Overlays.deleteOverlay(activeButton);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -237,7 +231,6 @@ function grabLowestJointY() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function addTerrainBlock() {
|
function addTerrainBlock() {
|
||||||
var baseLocation = getTerrainAlignedLocation(Vec3.sum(MyAvatar.position, {x:8, y:8, z:8}));
|
var baseLocation = getTerrainAlignedLocation(Vec3.sum(MyAvatar.position, {x:8, y:8, z:8}));
|
||||||
if (baseLocation.y > MyAvatar.position.y) {
|
if (baseLocation.y > MyAvatar.position.y) {
|
||||||
|
@ -253,10 +246,26 @@ function addTerrainBlock() {
|
||||||
baseLocation = getTerrainAlignedLocation(facingPosition);
|
baseLocation = getTerrainAlignedLocation(facingPosition);
|
||||||
alreadyThere = lookupTerrainForLocation(baseLocation);
|
alreadyThere = lookupTerrainForLocation(baseLocation);
|
||||||
if (alreadyThere) {
|
if (alreadyThere) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var polyVoxID = addTerrainBlockNearLocation(baseLocation);
|
||||||
|
|
||||||
|
if (polyVoxID) {
|
||||||
|
var AvatarPositionInVoxelCoords = Entities.worldCoordsToVoxelCoords(polyVoxID, MyAvatar.position);
|
||||||
|
// TODO -- how to find the avatar's feet?
|
||||||
|
var topY = Math.round(AvatarPositionInVoxelCoords.y) - 4;
|
||||||
|
Entities.setVoxelsInCuboid(polyVoxID, {x:0, y:0, z:0}, {x:16, y:topY, z:16}, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTerrainBlockNearLocation(baseLocation) {
|
||||||
|
var alreadyThere = lookupTerrainForLocation(baseLocation);
|
||||||
|
if (alreadyThere) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var polyVoxID = Entities.addEntity({
|
var polyVoxID = Entities.addEntity({
|
||||||
type: "PolyVox",
|
type: "PolyVox",
|
||||||
name: "terrain",
|
name: "terrain",
|
||||||
|
@ -269,12 +278,6 @@ function addTerrainBlock() {
|
||||||
zTextureURL: "http://headache.hungry.com/~seth/hifi/dirt.jpeg"
|
zTextureURL: "http://headache.hungry.com/~seth/hifi/dirt.jpeg"
|
||||||
});
|
});
|
||||||
|
|
||||||
var AvatarPositionInVoxelCoords = Entities.worldCoordsToVoxelCoords(polyVoxID, MyAvatar.position);
|
|
||||||
// TODO -- how to find the avatar's feet?
|
|
||||||
var topY = Math.round(AvatarPositionInVoxelCoords.y) - 4;
|
|
||||||
Entities.setVoxelsInCuboid(polyVoxID, {x:0, y:0, z:0}, {x:16, y:topY, z:16}, 255);
|
|
||||||
|
|
||||||
|
|
||||||
//////////
|
//////////
|
||||||
// stitch together the terrain with x/y/z NeighorID properties
|
// stitch together the terrain with x/y/z NeighorID properties
|
||||||
//////////
|
//////////
|
||||||
|
@ -330,7 +333,7 @@ function addTerrainBlock() {
|
||||||
properties.zPNeighborID = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:16}));
|
properties.zPNeighborID = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:16}));
|
||||||
Entities.editEntity(polyVoxID, properties);
|
Entities.editEntity(polyVoxID, properties);
|
||||||
|
|
||||||
return true;
|
return polyVoxID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -456,9 +459,6 @@ function keyReleaseEvent(event) {
|
||||||
|
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
for (var i = 0; i < overlays.length; i++) {
|
|
||||||
Overlays.deleteOverlay(overlays[i]);
|
|
||||||
}
|
|
||||||
toolBar.cleanup();
|
toolBar.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,28 @@ Item {
|
||||||
text: "Downloads: " + root.downloads + "/" + root.downloadLimit +
|
text: "Downloads: " + root.downloads + "/" + root.downloadLimit +
|
||||||
", Pending: " + root.downloadsPending;
|
", Pending: " + root.downloadsPending;
|
||||||
}
|
}
|
||||||
|
Text {
|
||||||
|
color: root.fontColor;
|
||||||
|
font.pixelSize: root.fontSize
|
||||||
|
visible: root.expanded && root.downloadUrls.length > 0;
|
||||||
|
text: "Download URLs:"
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
width: geoCol.width
|
||||||
|
height: root.downloadUrls.length * 15
|
||||||
|
|
||||||
|
visible: root.expanded && root.downloadUrls.length > 0;
|
||||||
|
|
||||||
|
model: root.downloadUrls
|
||||||
|
delegate: Text {
|
||||||
|
color: root.fontColor;
|
||||||
|
font.pixelSize: root.fontSize
|
||||||
|
visible: root.expanded;
|
||||||
|
text: modelData.length > 30
|
||||||
|
? modelData.substring(0, 5) + "..." + modelData.substring(modelData.length - 22)
|
||||||
|
: modelData
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
171
interface/resources/qml/controls-uit/AttachmentsTable.qml
Normal file
171
interface/resources/qml/controls-uit/AttachmentsTable.qml
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
//
|
||||||
|
// AttachmentsTable.qml
|
||||||
|
//
|
||||||
|
// Created by David Rowe on 18 Feb 2016
|
||||||
|
// Copyright 2016 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
|
||||||
|
//
|
||||||
|
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import QtQuick.XmlListModel 2.0
|
||||||
|
|
||||||
|
import "../styles-uit"
|
||||||
|
import "../controls-uit" as HifiControls
|
||||||
|
import "../windows-uit"
|
||||||
|
import "../hifi/models"
|
||||||
|
|
||||||
|
TableView {
|
||||||
|
id: tableView
|
||||||
|
|
||||||
|
// property var tableModel: ListModel { }
|
||||||
|
property int colorScheme: hifi.colorSchemes.light
|
||||||
|
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||||
|
|
||||||
|
model: S3Model{}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
visible: tableView.model.status !== XmlListModel.Ready
|
||||||
|
color: hifi.colors.darkGray0
|
||||||
|
BusyIndicator {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 48; height: 48
|
||||||
|
running: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
headerDelegate: Rectangle {
|
||||||
|
height: hifi.dimensions.tableHeaderHeight
|
||||||
|
color: hifi.colors.darkGray
|
||||||
|
border.width: 0.5
|
||||||
|
border.color: hifi.colors.baseGrayHighlight
|
||||||
|
|
||||||
|
RalewayRegular {
|
||||||
|
id: textHeader
|
||||||
|
size: hifi.fontSizes.tableText
|
||||||
|
color: hifi.colors.lightGrayText
|
||||||
|
text: styleData.value
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use rectangle to draw border with rounded corners.
|
||||||
|
Rectangle {
|
||||||
|
color: "#00000000"
|
||||||
|
anchors { fill: parent; margins: -2 }
|
||||||
|
radius: hifi.dimensions.borderRadius
|
||||||
|
border.color: hifi.colors.baseGrayHighlight
|
||||||
|
border.width: 3
|
||||||
|
}
|
||||||
|
anchors.margins: 2 // Shrink TableView to lie within border.
|
||||||
|
backgroundVisible: true
|
||||||
|
|
||||||
|
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
|
||||||
|
verticalScrollBarPolicy: Qt.ScrollBarAsNeeded
|
||||||
|
|
||||||
|
style: TableViewStyle {
|
||||||
|
// Needed in order for rows to keep displaying rows after end of table entries.
|
||||||
|
backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven
|
||||||
|
alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
|
||||||
|
|
||||||
|
handle: Item {
|
||||||
|
id: scrollbarHandle
|
||||||
|
implicitWidth: 6
|
||||||
|
Rectangle {
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
leftMargin: 2 // Move it right
|
||||||
|
rightMargin: -2 // ""
|
||||||
|
topMargin: 3 // Shrink vertically
|
||||||
|
bottomMargin: 3 // ""
|
||||||
|
}
|
||||||
|
radius: 3
|
||||||
|
color: hifi.colors.tableScrollHandle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollBarBackground: Item {
|
||||||
|
implicitWidth: 10
|
||||||
|
Rectangle {
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
margins: -1 // Expand
|
||||||
|
}
|
||||||
|
color: hifi.colors.baseGrayHighlight
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
margins: 1 // Shrink
|
||||||
|
}
|
||||||
|
radius: 4
|
||||||
|
color: hifi.colors.tableScrollBackground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
incrementControl: Item {
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
|
||||||
|
decrementControl: Item {
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rowDelegate: Rectangle {
|
||||||
|
height: (styleData.selected ? 1.2 : 1) * hifi.dimensions.tableRowHeight
|
||||||
|
color: styleData.selected
|
||||||
|
? hifi.colors.primaryHighlight
|
||||||
|
: tableView.isLightColorScheme
|
||||||
|
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
|
||||||
|
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
|
||||||
|
}
|
||||||
|
|
||||||
|
itemDelegate: Item {
|
||||||
|
anchors {
|
||||||
|
left: parent ? parent.left : undefined
|
||||||
|
leftMargin: hifi.dimensions.tablePadding
|
||||||
|
right: parent ? parent.right : undefined
|
||||||
|
rightMargin: hifi.dimensions.tablePadding
|
||||||
|
}
|
||||||
|
FiraSansSemiBold {
|
||||||
|
id: textItem
|
||||||
|
text: styleData.value
|
||||||
|
size: hifi.fontSizes.tableText
|
||||||
|
color: colorScheme == hifi.colorSchemes.light
|
||||||
|
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
|
||||||
|
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TableViewColumn {
|
||||||
|
role: "name"
|
||||||
|
title: "NAME"
|
||||||
|
width: parent.width *0.3
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
TableViewColumn {
|
||||||
|
role: "size"
|
||||||
|
title: "SIZE"
|
||||||
|
width: parent.width *0.2
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
TableViewColumn {
|
||||||
|
role: "modified"
|
||||||
|
title: "LAST MODIFIED"
|
||||||
|
width: parent.width *0.5
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,8 @@ SpinBox {
|
||||||
property int colorScheme: hifi.colorSchemes.light
|
property int colorScheme: hifi.colorSchemes.light
|
||||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||||
property string label: ""
|
property string label: ""
|
||||||
|
property string labelInside: ""
|
||||||
|
property color colorLabelInside: hifi.colors.white
|
||||||
property real controlHeight: height + (spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0)
|
property real controlHeight: height + (spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0)
|
||||||
|
|
||||||
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||||
|
@ -31,12 +33,14 @@ SpinBox {
|
||||||
y: spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0
|
y: spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0
|
||||||
|
|
||||||
style: SpinBoxStyle {
|
style: SpinBoxStyle {
|
||||||
|
id: spinStyle
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
|
id: backgrondRec
|
||||||
color: isLightColorScheme
|
color: isLightColorScheme
|
||||||
? (spinBox.focus ? hifi.colors.white : hifi.colors.lightGray)
|
? (spinBox.focus ? hifi.colors.white : hifi.colors.lightGray)
|
||||||
: (spinBox.focus ? hifi.colors.black : hifi.colors.baseGrayShadow)
|
: (spinBox.focus ? hifi.colors.black : hifi.colors.baseGrayShadow)
|
||||||
border.color: hifi.colors.primaryHighlight
|
border.color: spinBoxLabelInside.visible ? spinBoxLabelInside.color : hifi.colors.primaryHighlight
|
||||||
border.width: spinBox.focus ? 1 : 0
|
border.width: spinBox.focus ? spinBoxLabelInside.visible ? 2 : 1 : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
textColor: isLightColorScheme
|
textColor: isLightColorScheme
|
||||||
|
@ -46,7 +50,7 @@ SpinBox {
|
||||||
selectionColor: hifi.colors.primaryHighlight
|
selectionColor: hifi.colors.primaryHighlight
|
||||||
|
|
||||||
horizontalAlignment: Qt.AlignLeft
|
horizontalAlignment: Qt.AlignLeft
|
||||||
padding.left: hifi.dimensions.textPadding
|
padding.left: spinBoxLabelInside.visible ? 30 : hifi.dimensions.textPadding
|
||||||
padding.right: hifi.dimensions.spinnerSize
|
padding.right: hifi.dimensions.spinnerSize
|
||||||
|
|
||||||
incrementControl: HiFiGlyphs {
|
incrementControl: HiFiGlyphs {
|
||||||
|
@ -76,4 +80,15 @@ SpinBox {
|
||||||
anchors.bottomMargin: 4
|
anchors.bottomMargin: 4
|
||||||
visible: label != ""
|
visible: label != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HifiControls.Label {
|
||||||
|
id: spinBoxLabelInside
|
||||||
|
text: spinBox.labelInside
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
font.bold: true
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: spinBox.colorLabelInside
|
||||||
|
visible: spinBox.labelInside != ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,29 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||||
import Qt.labs.settings 1.0
|
import Qt.labs.settings 1.0
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
|
||||||
|
//import "../../windows"
|
||||||
|
|
||||||
|
|
||||||
|
import "../../styles-uit"
|
||||||
|
import "../../controls-uit" as HifiControls
|
||||||
|
import "../../windows-uit"
|
||||||
|
|
||||||
import "../../windows"
|
|
||||||
import "attachments"
|
import "attachments"
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
id: root
|
id: root
|
||||||
title: "Edit Attachments"
|
title: "Attachments Dialog"
|
||||||
objectName: "AttachmentsDialog"
|
objectName: "AttachmentsDialog"
|
||||||
width: 600
|
width: 600
|
||||||
height: 600
|
height: 600
|
||||||
resizable: true
|
resizable: true
|
||||||
// User must click OK or cancel to close the window
|
destroyOnInvisible: true
|
||||||
closable: false
|
minSize: Qt.vector2d(400, 500)
|
||||||
|
|
||||||
|
HifiConstants { id: hifi }
|
||||||
|
|
||||||
readonly property var originalAttachments: MyAvatar.getAttachmentsVariant();
|
readonly property var originalAttachments: MyAvatar.getAttachmentsVariant();
|
||||||
property var attachments: [];
|
property var attachments: [];
|
||||||
|
@ -33,90 +43,128 @@ Window {
|
||||||
listView.model.append({});
|
listView.model.append({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Column {
|
||||||
Rectangle {
|
width: pane.contentWidth
|
||||||
anchors.fill: parent
|
|
||||||
radius: 4
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: attachmentsBackground
|
width: parent.width
|
||||||
anchors { left: parent.left; right: parent.right; top: parent.top; bottom: newAttachmentButton.top; margins: 8 }
|
height: root.height
|
||||||
color: "gray"
|
|
||||||
radius: 4
|
radius: 4
|
||||||
|
color: hifi.colors.baseGray
|
||||||
|
|
||||||
ScrollView{
|
Rectangle {
|
||||||
id: scrollView
|
id: attachmentsBackground
|
||||||
anchors.fill: parent
|
anchors { left: parent.left; right: parent.right; top: parent.top; bottom: newAttachmentButton.top; margins: 8 }
|
||||||
anchors.margins: 4
|
color: hifi.colors.lightGrayText
|
||||||
ListView {
|
radius: 4
|
||||||
id: listView
|
|
||||||
model: ListModel {}
|
ScrollView{
|
||||||
delegate: Item {
|
id: scrollView
|
||||||
implicitHeight: attachmentView.height + 8;
|
anchors.fill: parent
|
||||||
implicitWidth: attachmentView.width;
|
anchors.margins: 4
|
||||||
Attachment {
|
style: ScrollViewStyle {
|
||||||
id: attachmentView
|
decrementControl: Item {
|
||||||
width: scrollView.width
|
visible: false
|
||||||
attachment: root.attachments[index]
|
}
|
||||||
onDeleteAttachment: {
|
incrementControl: Item {
|
||||||
attachments.splice(index, 1);
|
visible: false
|
||||||
listView.model.remove(index, 1);
|
}
|
||||||
}
|
scrollBarBackground: Rectangle{
|
||||||
onUpdateAttachment: MyAvatar.setAttachmentsVariant(attachments);
|
implicitWidth: 14
|
||||||
|
color: hifi.colors.baseGray
|
||||||
|
}
|
||||||
|
|
||||||
|
handle:
|
||||||
|
Rectangle {
|
||||||
|
implicitWidth: 8
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 3
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
radius: 3
|
||||||
|
color: hifi.colors.lightGrayText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onCountChanged: MyAvatar.setAttachmentsVariant(attachments);
|
|
||||||
|
ListView {
|
||||||
|
id: listView
|
||||||
|
model: ListModel {}
|
||||||
|
delegate: Item {
|
||||||
|
implicitHeight: attachmentView.height + 8;
|
||||||
|
implicitWidth: attachmentView.width;
|
||||||
|
Attachment {
|
||||||
|
id: attachmentView
|
||||||
|
width: scrollView.width
|
||||||
|
attachment: root.attachments[index]
|
||||||
|
onDeleteAttachment: {
|
||||||
|
attachments.splice(index, 1);
|
||||||
|
listView.model.remove(index, 1);
|
||||||
|
}
|
||||||
|
onUpdateAttachment: MyAvatar.setAttachmentsVariant(attachments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onCountChanged: MyAvatar.setAttachmentsVariant(attachments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
HifiControls.Button {
|
||||||
id: newAttachmentButton
|
id: newAttachmentButton
|
||||||
anchors { left: parent.left; right: parent.right; bottom: buttonRow.top; margins: 8 }
|
anchors { left: parent.left; right: parent.right; bottom: buttonRow.top; margins: 8 }
|
||||||
text: "New Attachment"
|
text: "New Attachment"
|
||||||
|
color: hifi.buttons.black
|
||||||
onClicked: {
|
colorScheme: hifi.colorSchemes.dark
|
||||||
var template = {
|
onClicked: {
|
||||||
modelUrl: "",
|
var template = {
|
||||||
translation: { x: 0, y: 0, z: 0 },
|
modelUrl: "",
|
||||||
rotation: { x: 0, y: 0, z: 0 },
|
translation: { x: 0, y: 0, z: 0 },
|
||||||
scale: 1,
|
rotation: { x: 0, y: 0, z: 0 },
|
||||||
jointName: MyAvatar.jointNames[0],
|
scale: 1,
|
||||||
soft: false
|
jointName: MyAvatar.jointNames[0],
|
||||||
};
|
soft: false
|
||||||
attachments.push(template);
|
};
|
||||||
listView.model.append({});
|
attachments.push(template);
|
||||||
MyAvatar.setAttachmentsVariant(attachments);
|
listView.model.append({});
|
||||||
}
|
MyAvatar.setAttachmentsVariant(attachments);
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: buttonRow
|
|
||||||
spacing: 8
|
|
||||||
anchors { right: parent.right; bottom: parent.bottom; margins: 8 }
|
|
||||||
Button { action: cancelAction }
|
|
||||||
Button { action: okAction }
|
|
||||||
}
|
|
||||||
|
|
||||||
Action {
|
|
||||||
id: cancelAction
|
|
||||||
text: "Cancel"
|
|
||||||
onTriggered: {
|
|
||||||
MyAvatar.setAttachmentsVariant(originalAttachments);
|
|
||||||
root.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Action {
|
|
||||||
id: okAction
|
|
||||||
text: "OK"
|
|
||||||
onTriggered: {
|
|
||||||
for (var i = 0; i < attachments.length; ++i) {
|
|
||||||
console.log("Attachment " + i + ": " + attachments[i]);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MyAvatar.setAttachmentsVariant(attachments);
|
Row {
|
||||||
root.destroy()
|
id: buttonRow
|
||||||
|
spacing: 8
|
||||||
|
anchors { right: parent.right; bottom: parent.bottom; margins: 8 }
|
||||||
|
HifiControls.Button {
|
||||||
|
action: cancelAction
|
||||||
|
color: hifi.buttons.black
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
|
}
|
||||||
|
HifiControls.Button {
|
||||||
|
action: okAction
|
||||||
|
color: hifi.buttons.black
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Action {
|
||||||
|
id: cancelAction
|
||||||
|
text: "Cancel"
|
||||||
|
onTriggered: {
|
||||||
|
MyAvatar.setAttachmentsVariant(originalAttachments);
|
||||||
|
root.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Action {
|
||||||
|
id: okAction
|
||||||
|
text: "OK"
|
||||||
|
onTriggered: {
|
||||||
|
for (var i = 0; i < attachments.length; ++i) {
|
||||||
|
console.log("Attachment " + i + ": " + attachments[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar.setAttachmentsVariant(attachments);
|
||||||
|
root.destroy()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,36 +7,45 @@ import "../../windows"
|
||||||
import "../../js/Utils.js" as Utils
|
import "../../js/Utils.js" as Utils
|
||||||
import "../models"
|
import "../models"
|
||||||
|
|
||||||
ModalWindow {
|
import "../../styles-uit"
|
||||||
|
import "../../controls-uit" as HifiControls
|
||||||
|
import "../../windows-uit"
|
||||||
|
|
||||||
|
Window {
|
||||||
id: root
|
id: root
|
||||||
resizable: true
|
resizable: true
|
||||||
width: 640
|
width: 600
|
||||||
height: 480
|
height: 480
|
||||||
|
closable: false
|
||||||
|
|
||||||
property var result;
|
property var result;
|
||||||
|
|
||||||
signal selected(var modelUrl);
|
signal selected(var modelUrl);
|
||||||
signal canceled();
|
signal canceled();
|
||||||
|
|
||||||
Rectangle {
|
HifiConstants {id: hifi}
|
||||||
anchors.fill: parent
|
|
||||||
color: "white"
|
|
||||||
|
|
||||||
Item {
|
Column {
|
||||||
anchors { fill: parent; margins: 8 }
|
width: pane.contentWidth
|
||||||
|
|
||||||
TextField {
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: root.height
|
||||||
|
radius: 4
|
||||||
|
color: hifi.colors.baseGray
|
||||||
|
|
||||||
|
HifiControls.TextField {
|
||||||
id: filterEdit
|
id: filterEdit
|
||||||
style: TextFieldStyle { renderType: Text.QtRendering }
|
anchors { left: parent.left; right: parent.right; top: parent.top ; margins: 8}
|
||||||
anchors { left: parent.left; right: parent.right; top: parent.top }
|
|
||||||
placeholderText: "filter"
|
placeholderText: "filter"
|
||||||
onTextChanged: tableView.model.filter = text
|
onTextChanged: tableView.model.filter = text
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
}
|
}
|
||||||
|
|
||||||
TableView {
|
HifiControls.AttachmentsTable {
|
||||||
id: tableView
|
id: tableView
|
||||||
anchors { left: parent.left; right: parent.right; top: filterEdit.bottom; topMargin: 8; bottom: buttonRow.top; bottomMargin: 8 }
|
anchors { left: parent.left; right: parent.right; top: filterEdit.bottom; bottom: buttonRow.top; margins: 8; }
|
||||||
model: S3Model{}
|
colorScheme: hifi.colorSchemes.dark
|
||||||
onCurrentRowChanged: {
|
onCurrentRowChanged: {
|
||||||
if (currentRow == -1) {
|
if (currentRow == -1) {
|
||||||
root.result = null;
|
root.result = null;
|
||||||
|
@ -44,60 +53,14 @@ ModalWindow {
|
||||||
}
|
}
|
||||||
result = model.baseUrl + "/" + model.get(tableView.currentRow).key;
|
result = model.baseUrl + "/" + model.get(tableView.currentRow).key;
|
||||||
}
|
}
|
||||||
itemDelegate: Component {
|
|
||||||
Item {
|
|
||||||
clip: true
|
|
||||||
Text {
|
|
||||||
x: 3
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
color: tableView.activeFocus && styleData.row === tableView.currentRow ? "yellow" : styleData.textColor
|
|
||||||
elide: styleData.elideMode
|
|
||||||
text: getText()
|
|
||||||
|
|
||||||
function getText() {
|
|
||||||
switch(styleData.column) {
|
|
||||||
case 1:
|
|
||||||
return Utils.formatSize(styleData.value)
|
|
||||||
default:
|
|
||||||
return styleData.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TableViewColumn {
|
|
||||||
role: "name"
|
|
||||||
title: "Name"
|
|
||||||
width: 200
|
|
||||||
}
|
|
||||||
TableViewColumn {
|
|
||||||
role: "size"
|
|
||||||
title: "Size"
|
|
||||||
width: 100
|
|
||||||
}
|
|
||||||
TableViewColumn {
|
|
||||||
role: "modified"
|
|
||||||
title: "Last Modified"
|
|
||||||
width: 200
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
visible: tableView.model.status !== XmlListModel.Ready
|
|
||||||
color: "#7fffffff"
|
|
||||||
BusyIndicator {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: 48; height: 48
|
|
||||||
running: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: buttonRow
|
id: buttonRow
|
||||||
anchors { right: parent.right; bottom: parent.bottom }
|
spacing: 8
|
||||||
Button { action: acceptAction }
|
anchors { right: parent.right; rightMargin: 8; bottom: parent.bottom; bottomMargin: 8; }
|
||||||
Button { action: cancelAction }
|
HifiControls.Button { action: acceptAction ; color: hifi.buttons.black; colorScheme: hifi.colorSchemes.dark }
|
||||||
|
HifiControls.Button { action: cancelAction ; color: hifi.buttons.black; colorScheme: hifi.colorSchemes.dark }
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action {
|
||||||
|
@ -121,7 +84,6 @@ ModalWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,30 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
import QtQuick.Controls.Styles 1.4
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||||
|
import Qt.labs.settings 1.0
|
||||||
|
|
||||||
import "../../../windows"
|
//import "../../../windows"
|
||||||
import "../../../controls" as VrControls
|
//import "../../../controls" as VrControls
|
||||||
import "."
|
import "."
|
||||||
import ".."
|
import ".."
|
||||||
|
|
||||||
|
import "../../../styles-uit"
|
||||||
|
import "../../../controls-uit" as HifiControls
|
||||||
|
import "../../../windows-uit"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
height: column.height + 2 * 8
|
height: column.height + 2 * 8
|
||||||
|
|
||||||
property var attachment;
|
property var attachment;
|
||||||
|
|
||||||
|
HifiConstants { id: hifi }
|
||||||
|
|
||||||
signal deleteAttachment(var attachment);
|
signal deleteAttachment(var attachment);
|
||||||
signal updateAttachment();
|
signal updateAttachment();
|
||||||
property bool completed: false;
|
property bool completed: false;
|
||||||
|
|
||||||
Rectangle { color: "white"; anchors.fill: parent; radius: 4 }
|
Rectangle { color: hifi.colors.baseGray; anchors.fill: parent; radius: 4 }
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
completed = true;
|
completed = true;
|
||||||
|
@ -29,13 +37,14 @@ Item {
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
height: modelChooserButton.height
|
height: modelChooserButton.height + urlLabel.height
|
||||||
anchors { left: parent.left; right: parent.right; }
|
anchors { left: parent.left; right: parent.right;}
|
||||||
Text { id: urlLabel; text: "Model URL:"; width: 80; anchors.verticalCenter: modelUrl.verticalCenter }
|
Text { id: urlLabel; color: hifi.colors.lightGrayText; text: "Model URL:"; width: 80; anchors.top: parent.top;}
|
||||||
VrControls.TextField {
|
HifiControls.TextField {
|
||||||
id: modelUrl;
|
id: modelUrl;
|
||||||
height: jointChooser.height;
|
height: jointChooser.height;
|
||||||
anchors { left: urlLabel.right; leftMargin: 8; rightMargin: 8; right: modelChooserButton.left }
|
colorScheme: hifi.colorSchemes.dark
|
||||||
|
anchors { bottom: parent.bottom; left: parent.left; rightMargin: 8; right: modelChooserButton.left }
|
||||||
text: attachment ? attachment.modelUrl : ""
|
text: attachment ? attachment.modelUrl : ""
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
if (completed && attachment && attachment.modelUrl !== text) {
|
if (completed && attachment && attachment.modelUrl !== text) {
|
||||||
|
@ -44,9 +53,11 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button {
|
HifiControls.Button {
|
||||||
id: modelChooserButton;
|
id: modelChooserButton;
|
||||||
text: "Choose";
|
text: "Choose";
|
||||||
|
color: hifi.buttons.black
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
anchors { right: parent.right; verticalCenter: modelUrl.verticalCenter }
|
anchors { right: parent.right; verticalCenter: modelUrl.verticalCenter }
|
||||||
Component {
|
Component {
|
||||||
id: modelBrowserBuiler;
|
id: modelBrowserBuiler;
|
||||||
|
@ -63,18 +74,20 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
height: jointChooser.height
|
height: jointChooser.height + jointLabel.height
|
||||||
anchors { left: parent.left; right: parent.right; }
|
anchors { left: parent.left; right: parent.right; }
|
||||||
Text {
|
Text {
|
||||||
id: jointLabel;
|
id: jointLabel;
|
||||||
width: 80;
|
width: 80;
|
||||||
text: "Joint:";
|
text: "Joint:";
|
||||||
anchors.verticalCenter: jointChooser.verticalCenter;
|
color: hifi.colors.lightGrayText;
|
||||||
|
anchors.top: parent.top
|
||||||
}
|
}
|
||||||
VrControls.ComboBox {
|
HifiControls.ComboBox {
|
||||||
id: jointChooser;
|
id: jointChooser;
|
||||||
anchors { left: jointLabel.right; leftMargin: 8; right: parent.right }
|
anchors { bottom: parent.bottom; left: parent.left; right: parent.right }
|
||||||
model: MyAvatar.jointNames
|
model: MyAvatar.jointNames
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
currentIndex: attachment ? model.indexOf(attachment.jointName) : -1
|
currentIndex: attachment ? model.indexOf(attachment.jointName) : -1
|
||||||
onCurrentIndexChanged: {
|
onCurrentIndexChanged: {
|
||||||
if (completed && attachment && currentIndex != -1 && currentText && currentText !== attachment.jointName) {
|
if (completed && attachment && currentIndex != -1 && currentText && currentText !== attachment.jointName) {
|
||||||
|
@ -86,12 +99,12 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
height: translation.height
|
height: translation.height + translationLabel.height
|
||||||
anchors { left: parent.left; right: parent.right; }
|
anchors { left: parent.left; right: parent.right; }
|
||||||
Text { id: translationLabel; width: 80; text: "Translation:"; anchors.verticalCenter: translation.verticalCenter; }
|
Text { id: translationLabel; width: 80; color: hifi.colors.lightGrayText; text: "Translation:"; anchors.top: parent.top; }
|
||||||
Translation {
|
Translation {
|
||||||
id: translation;
|
id: translation;
|
||||||
anchors { left: translationLabel.right; leftMargin: 8; right: parent.right }
|
anchors { left: parent.left; right: parent.right; bottom: parent.bottom}
|
||||||
vector: attachment ? attachment.translation : {x: 0, y: 0, z: 0};
|
vector: attachment ? attachment.translation : {x: 0, y: 0, z: 0};
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
if (completed && attachment) {
|
if (completed && attachment) {
|
||||||
|
@ -103,12 +116,12 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
height: rotation.height
|
height: rotation.height + rotationLabel.height
|
||||||
anchors { left: parent.left; right: parent.right; }
|
anchors { left: parent.left; right: parent.right; }
|
||||||
Text { id: rotationLabel; width: 80; text: "Rotation:"; anchors.verticalCenter: rotation.verticalCenter; }
|
Text { id: rotationLabel; width: 80; color: hifi.colors.lightGrayText; text: "Rotation:"; anchors.top: parent.top; }
|
||||||
Rotation {
|
Rotation {
|
||||||
id: rotation;
|
id: rotation;
|
||||||
anchors { left: rotationLabel.right; leftMargin: 8; right: parent.right }
|
anchors { left: parent.left; right: parent.right; bottom: parent.bottom; }
|
||||||
vector: attachment ? attachment.rotation : {x: 0, y: 0, z: 0};
|
vector: attachment ? attachment.rotation : {x: 0, y: 0, z: 0};
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
if (completed && attachment) {
|
if (completed && attachment) {
|
||||||
|
@ -120,17 +133,18 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
height: scaleSpinner.height
|
height: scaleSpinner.height + scaleLabel.height
|
||||||
anchors { left: parent.left; right: parent.right; }
|
anchors { left: parent.left; right: parent.right; }
|
||||||
Text { id: scaleLabel; width: 80; text: "Scale:"; anchors.verticalCenter: scale.verticalCenter; }
|
Text { id: scaleLabel; width: 80; color: hifi.colors.lightGrayText; text: "Scale:"; anchors.top: parent.top; }
|
||||||
SpinBox {
|
HifiControls.SpinBox {
|
||||||
id: scaleSpinner;
|
id: scaleSpinner;
|
||||||
anchors { left: scaleLabel.right; leftMargin: 8; right: parent.right }
|
anchors { left: parent.left; right: parent.right; bottom: parent.bottom; }
|
||||||
decimals: 1;
|
decimals: 1;
|
||||||
minimumValue: 0.1
|
minimumValue: 0.1
|
||||||
maximumValue: 10
|
maximumValue: 10
|
||||||
stepSize: 0.1;
|
stepSize: 0.1;
|
||||||
value: attachment ? attachment.scale : 1.0
|
value: attachment ? attachment.scale : 1.0
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
if (completed && attachment && attachment.scale !== value) {
|
if (completed && attachment && attachment.scale !== value) {
|
||||||
attachment.scale = value;
|
attachment.scale = value;
|
||||||
|
@ -143,11 +157,12 @@ Item {
|
||||||
Item {
|
Item {
|
||||||
height: soft.height
|
height: soft.height
|
||||||
anchors { left: parent.left; right: parent.right; }
|
anchors { left: parent.left; right: parent.right; }
|
||||||
Text { id: softLabel; width: 80; text: "Is soft:"; anchors.verticalCenter: soft.verticalCenter; }
|
Text { id: softLabel; width: 80; color: hifi.colors.lightGrayText; text: "Is soft"; anchors.left: soft.right; anchors.leftMargin: 8; }
|
||||||
CheckBox {
|
HifiControls.CheckBox {
|
||||||
id: soft;
|
id: soft;
|
||||||
anchors { left: softLabel.right; leftMargin: 8; right: parent.right }
|
anchors { left: parent.left; bottom: parent.bottom;}
|
||||||
checked: attachment ? attachment.soft : false
|
checked: attachment ? attachment.soft : false
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
onCheckedChanged: {
|
onCheckedChanged: {
|
||||||
if (completed && attachment && attachment.soft !== checked) {
|
if (completed && attachment && attachment.soft !== checked) {
|
||||||
attachment.soft = checked;
|
attachment.soft = checked;
|
||||||
|
@ -157,7 +172,9 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
HifiControls.Button {
|
||||||
|
color: hifi.buttons.black
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
anchors { left: parent.left; right: parent.right; }
|
anchors { left: parent.left; right: parent.right; }
|
||||||
text: "Delete"
|
text: "Delete"
|
||||||
onClicked: deleteAttachment(root.attachment);
|
onClicked: deleteAttachment(root.attachment);
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
|
|
||||||
|
import "../../../styles-uit"
|
||||||
|
import "../../../controls-uit" as HifiControls
|
||||||
|
import "../../../windows-uit"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
implicitHeight: xspinner.height
|
implicitHeight: xspinner.height
|
||||||
|
@ -14,12 +18,16 @@ Item {
|
||||||
|
|
||||||
signal valueChanged();
|
signal valueChanged();
|
||||||
|
|
||||||
SpinBox {
|
HifiConstants { id: hifi }
|
||||||
|
|
||||||
|
HifiControls.SpinBox {
|
||||||
id: xspinner
|
id: xspinner
|
||||||
width: root.spinboxWidth
|
width: root.spinboxWidth
|
||||||
anchors { left: parent.left }
|
anchors { left: parent.left }
|
||||||
value: root.vector.x
|
value: root.vector.x
|
||||||
|
labelInside: "X:"
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
|
colorLabelInside: hifi.colors.redHighlight
|
||||||
decimals: root.decimals
|
decimals: root.decimals
|
||||||
stepSize: root.stepSize
|
stepSize: root.stepSize
|
||||||
maximumValue: root.maximumValue
|
maximumValue: root.maximumValue
|
||||||
|
@ -32,12 +40,14 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpinBox {
|
HifiControls.SpinBox {
|
||||||
id: yspinner
|
id: yspinner
|
||||||
width: root.spinboxWidth
|
width: root.spinboxWidth
|
||||||
anchors { horizontalCenter: parent.horizontalCenter }
|
anchors { horizontalCenter: parent.horizontalCenter }
|
||||||
value: root.vector.y
|
value: root.vector.y
|
||||||
|
labelInside: "Y:"
|
||||||
|
colorLabelInside: hifi.colors.greenHighlight
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
decimals: root.decimals
|
decimals: root.decimals
|
||||||
stepSize: root.stepSize
|
stepSize: root.stepSize
|
||||||
maximumValue: root.maximumValue
|
maximumValue: root.maximumValue
|
||||||
|
@ -50,12 +60,14 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpinBox {
|
HifiControls.SpinBox {
|
||||||
id: zspinner
|
id: zspinner
|
||||||
width: root.spinboxWidth
|
width: root.spinboxWidth
|
||||||
anchors { right: parent.right; }
|
anchors { right: parent.right; }
|
||||||
value: root.vector.z
|
value: root.vector.z
|
||||||
|
labelInside: "Z:"
|
||||||
|
colorLabelInside: hifi.colors.primaryHighlight
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
decimals: root.decimals
|
decimals: root.decimals
|
||||||
stepSize: root.stepSize
|
stepSize: root.stepSize
|
||||||
maximumValue: root.maximumValue
|
maximumValue: root.maximumValue
|
||||||
|
|
|
@ -75,6 +75,7 @@ Item {
|
||||||
readonly property color lightGrayText80: "#ccafafaf"
|
readonly property color lightGrayText80: "#ccafafaf"
|
||||||
readonly property color faintGray80: "#cce3e3e3"
|
readonly property color faintGray80: "#cce3e3e3"
|
||||||
readonly property color faintGray50: "#80e3e3e3"
|
readonly property color faintGray50: "#80e3e3e3"
|
||||||
|
readonly property color locked: "#252525"
|
||||||
|
|
||||||
// Other colors
|
// Other colors
|
||||||
readonly property color white: "#ffffff"
|
readonly property color white: "#ffffff"
|
||||||
|
@ -136,6 +137,7 @@ Item {
|
||||||
readonly property real spinnerSize: 42
|
readonly property real spinnerSize: 42
|
||||||
readonly property real tablePadding: 12
|
readonly property real tablePadding: 12
|
||||||
readonly property real tableRowHeight: largeScreen ? 26 : 23
|
readonly property real tableRowHeight: largeScreen ? 26 : 23
|
||||||
|
readonly property real tableHeaderHeight: 40
|
||||||
readonly property vector2d modalDialogMargin: Qt.vector2d(50, 30)
|
readonly property vector2d modalDialogMargin: Qt.vector2d(50, 30)
|
||||||
readonly property real modalDialogTitleHeight: 40
|
readonly property real modalDialogTitleHeight: 40
|
||||||
readonly property real controlLineHeight: 29 // Height of spinbox control on 1920 x 1080 monitor
|
readonly property real controlLineHeight: 29 // Height of spinbox control on 1920 x 1080 monitor
|
||||||
|
|
|
@ -272,11 +272,13 @@ public:
|
||||||
void run() override {
|
void run() override {
|
||||||
while (!_quit) {
|
while (!_quit) {
|
||||||
QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS);
|
QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS);
|
||||||
|
#ifdef NDEBUG
|
||||||
auto now = usecTimestampNow();
|
auto now = usecTimestampNow();
|
||||||
auto lastHeartbeatAge = now - _heartbeat;
|
auto lastHeartbeatAge = now - _heartbeat;
|
||||||
if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) {
|
if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) {
|
||||||
deadlockDetectionCrash();
|
deadlockDetectionCrash();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ bool AvatarUpdate::process() {
|
||||||
deltaMicroseconds = 10000; // 10 ms
|
deltaMicroseconds = 10000; // 10 ms
|
||||||
}
|
}
|
||||||
float deltaSeconds = (float) deltaMicroseconds / (float) USECS_PER_SECOND;
|
float deltaSeconds = (float) deltaMicroseconds / (float) USECS_PER_SECOND;
|
||||||
|
assert(deltaSeconds > 0.0f);
|
||||||
_lastAvatarUpdate = start;
|
_lastAvatarUpdate = start;
|
||||||
qApp->setAvatarSimrateSample(1.0f / deltaSeconds);
|
qApp->setAvatarSimrateSample(1.0f / deltaSeconds);
|
||||||
|
|
||||||
|
|
|
@ -223,21 +223,31 @@ bool ScriptEditorWidget::questionSave() {
|
||||||
void ScriptEditorWidget::onWindowActivated() {
|
void ScriptEditorWidget::onWindowActivated() {
|
||||||
if (!_isReloading) {
|
if (!_isReloading) {
|
||||||
_isReloading = true;
|
_isReloading = true;
|
||||||
|
|
||||||
if (QFileInfo(_currentScript).lastModified() > _currentScriptModified) {
|
QDateTime fileStamp = QFileInfo(_currentScript).lastModified();
|
||||||
if (static_cast<ScriptEditorWindow*>(this->parent()->parent()->parent())->autoReloadScripts()
|
if (fileStamp > _currentScriptModified) {
|
||||||
|
bool doReload = false;
|
||||||
|
auto window = static_cast<ScriptEditorWindow*>(this->parent()->parent()->parent());
|
||||||
|
window->inModalDialog = true;
|
||||||
|
if (window->autoReloadScripts()
|
||||||
|| OffscreenUi::question(this, tr("Reload Script"),
|
|| OffscreenUi::question(this, tr("Reload Script"),
|
||||||
tr("The following file has been modified outside of the Interface editor:") + "\n" + _currentScript + "\n"
|
tr("The following file has been modified outside of the Interface editor:") + "\n" + _currentScript + "\n"
|
||||||
+ (isModified()
|
+ (isModified()
|
||||||
? tr("Do you want to reload it and lose the changes you've made in the Interface editor?")
|
? tr("Do you want to reload it and lose the changes you've made in the Interface editor?")
|
||||||
: tr("Do you want to reload it?")),
|
: tr("Do you want to reload it?")),
|
||||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||||
|
doReload = true;
|
||||||
|
}
|
||||||
|
window->inModalDialog = false;
|
||||||
|
if (doReload) {
|
||||||
loadFile(_currentScript);
|
loadFile(_currentScript);
|
||||||
if (_scriptEditorWidgetUI->onTheFlyCheckBox->isChecked() && isRunning()) {
|
if (_scriptEditorWidgetUI->onTheFlyCheckBox->isChecked() && isRunning()) {
|
||||||
_isRestarting = true;
|
_isRestarting = true;
|
||||||
setRunning(false);
|
setRunning(false);
|
||||||
// Script is restarted once current script instance finishes.
|
// Script is restarted once current script instance finishes.
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
_currentScriptModified = fileStamp; // Asked and answered. Don't ask again until the external file is changed again.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_isReloading = false;
|
_isReloading = false;
|
||||||
|
|
|
@ -171,6 +171,9 @@ void ScriptEditorWindow::tabSwitched(int tabIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEditorWindow::tabCloseRequested(int tabIndex) {
|
void ScriptEditorWindow::tabCloseRequested(int tabIndex) {
|
||||||
|
if (ignoreCloseForModal(nullptr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ScriptEditorWidget* closingScriptWidget = static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget
|
ScriptEditorWidget* closingScriptWidget = static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget
|
||||||
->widget(tabIndex));
|
->widget(tabIndex));
|
||||||
if(closingScriptWidget->questionSave()) {
|
if(closingScriptWidget->questionSave()) {
|
||||||
|
@ -178,7 +181,26 @@ void ScriptEditorWindow::tabCloseRequested(int tabIndex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this operating system window causes a qml overlay modal dialog (which might not even be seen by the user), closing this window
|
||||||
|
// will crash the code that was waiting on the dialog result. So that code whousl set inModalDialog to true while the question is up.
|
||||||
|
// This code will not be necessary when switch out all operating system windows for qml overlays.
|
||||||
|
bool ScriptEditorWindow::ignoreCloseForModal(QCloseEvent* event) {
|
||||||
|
if (!inModalDialog) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Deliberately not using OffscreenUi, so that the dialog is seen.
|
||||||
|
QMessageBox::information(this, tr("Interface"), tr("There is a modal dialog that must be answered before closing."),
|
||||||
|
QMessageBox::Discard, QMessageBox::Discard);
|
||||||
|
if (event) {
|
||||||
|
event->ignore(); // don't close
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptEditorWindow::closeEvent(QCloseEvent *event) {
|
void ScriptEditorWindow::closeEvent(QCloseEvent *event) {
|
||||||
|
if (ignoreCloseForModal(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
bool unsaved_docs_warning = false;
|
bool unsaved_docs_warning = false;
|
||||||
for (int i = 0; i < _ScriptEditorWindowUI->tabWidget->count(); i++){
|
for (int i = 0; i < _ScriptEditorWindowUI->tabWidget->count(); i++){
|
||||||
if(static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget->widget(i))->isModified()){
|
if(static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget->widget(i))->isModified()){
|
||||||
|
|
|
@ -28,6 +28,9 @@ public:
|
||||||
void terminateCurrentTab();
|
void terminateCurrentTab();
|
||||||
bool autoReloadScripts();
|
bool autoReloadScripts();
|
||||||
|
|
||||||
|
bool inModalDialog { false };
|
||||||
|
bool ignoreCloseForModal(QCloseEvent* event);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void windowActivated();
|
void windowActivated();
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,7 @@ void Stats::updateStats(bool force) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// update the entities ping with the average for all connected entity servers
|
// update the entities ping with the average for all connected entity servers
|
||||||
STAT_UPDATE(entitiesPing, octreeServerCount ? totalPingOctree / octreeServerCount : -1);
|
STAT_UPDATE(entitiesPing, octreeServerCount ? totalPingOctree / octreeServerCount : -1);
|
||||||
|
|
||||||
|
@ -192,9 +192,29 @@ void Stats::updateStats(bool force) {
|
||||||
STAT_UPDATE(audioMixerPps, -1);
|
STAT_UPDATE(audioMixerPps, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
STAT_UPDATE(downloads, ResourceCache::getLoadingRequests().size());
|
QList<Resource*> loadingRequests = ResourceCache::getLoadingRequests();
|
||||||
|
STAT_UPDATE(downloads, loadingRequests.size());
|
||||||
STAT_UPDATE(downloadLimit, ResourceCache::getRequestLimit())
|
STAT_UPDATE(downloadLimit, ResourceCache::getRequestLimit())
|
||||||
STAT_UPDATE(downloadsPending, ResourceCache::getPendingRequestCount());
|
STAT_UPDATE(downloadsPending, ResourceCache::getPendingRequestCount());
|
||||||
|
|
||||||
|
// See if the active download urls have changed
|
||||||
|
bool shouldUpdateUrls = _downloads != _downloadUrls.size();
|
||||||
|
if (!shouldUpdateUrls) {
|
||||||
|
for (int i = 0; i < _downloads; i++) {
|
||||||
|
if (loadingRequests[i]->getURL().toString() != _downloadUrls[i]) {
|
||||||
|
shouldUpdateUrls = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the urls have changed, update the list
|
||||||
|
if (shouldUpdateUrls) {
|
||||||
|
_downloadUrls.clear();
|
||||||
|
foreach (Resource* resource, loadingRequests) {
|
||||||
|
_downloadUrls << resource->getURL().toString();
|
||||||
|
}
|
||||||
|
emit downloadUrlsChanged();
|
||||||
|
}
|
||||||
// TODO fix to match original behavior
|
// TODO fix to match original behavior
|
||||||
//stringstream downloads;
|
//stringstream downloads;
|
||||||
//downloads << "Downloads: ";
|
//downloads << "Downloads: ";
|
||||||
|
@ -306,7 +326,7 @@ void Stats::updateStats(bool force) {
|
||||||
// we will also include room for 1 line per timing record and a header of 4 lines
|
// we will also include room for 1 line per timing record and a header of 4 lines
|
||||||
// Timing details...
|
// Timing details...
|
||||||
|
|
||||||
// First iterate all the records, and for the ones that should be included, insert them into
|
// First iterate all the records, and for the ones that should be included, insert them into
|
||||||
// a new Map sorted by average time...
|
// a new Map sorted by average time...
|
||||||
bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen);
|
bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen);
|
||||||
QMap<float, QString> sortedRecords;
|
QMap<float, QString> sortedRecords;
|
||||||
|
@ -366,7 +386,7 @@ void Stats::setRenderDetails(const RenderDetails& details) {
|
||||||
/*
|
/*
|
||||||
// display expanded or contracted stats
|
// display expanded or contracted stats
|
||||||
void Stats::display(
|
void Stats::display(
|
||||||
int voxelPacketsToProcess)
|
int voxelPacketsToProcess)
|
||||||
{
|
{
|
||||||
// iterate all the current voxel stats, and list their sending modes, and total voxel counts
|
// iterate all the current voxel stats, and list their sending modes, and total voxel counts
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
public: \
|
public: \
|
||||||
type name() { return _##name; }; \
|
type name() { return _##name; }; \
|
||||||
private: \
|
private: \
|
||||||
type _##name{ initialValue };
|
type _##name{ initialValue };
|
||||||
|
|
||||||
|
|
||||||
class Stats : public QQuickItem {
|
class Stats : public QQuickItem {
|
||||||
|
@ -58,6 +58,7 @@ class Stats : public QQuickItem {
|
||||||
STATS_PROPERTY(int, downloads, 0)
|
STATS_PROPERTY(int, downloads, 0)
|
||||||
STATS_PROPERTY(int, downloadLimit, 0)
|
STATS_PROPERTY(int, downloadLimit, 0)
|
||||||
STATS_PROPERTY(int, downloadsPending, 0)
|
STATS_PROPERTY(int, downloadsPending, 0)
|
||||||
|
Q_PROPERTY(QStringList downloadUrls READ downloadUrls NOTIFY downloadUrlsChanged)
|
||||||
STATS_PROPERTY(int, triangles, 0)
|
STATS_PROPERTY(int, triangles, 0)
|
||||||
STATS_PROPERTY(int, quads, 0)
|
STATS_PROPERTY(int, quads, 0)
|
||||||
STATS_PROPERTY(int, materialSwitches, 0)
|
STATS_PROPERTY(int, materialSwitches, 0)
|
||||||
|
@ -105,6 +106,8 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList downloadUrls () { return _downloadUrls; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void forceUpdateStats() { updateStats(true); }
|
void forceUpdateStats() { updateStats(true); }
|
||||||
|
|
||||||
|
@ -138,6 +141,7 @@ signals:
|
||||||
void downloadsChanged();
|
void downloadsChanged();
|
||||||
void downloadLimitChanged();
|
void downloadLimitChanged();
|
||||||
void downloadsPendingChanged();
|
void downloadsPendingChanged();
|
||||||
|
void downloadUrlsChanged();
|
||||||
void trianglesChanged();
|
void trianglesChanged();
|
||||||
void quadsChanged();
|
void quadsChanged();
|
||||||
void materialSwitchesChanged();
|
void materialSwitchesChanged();
|
||||||
|
@ -167,6 +171,7 @@ private:
|
||||||
bool _timingExpanded{ false };
|
bool _timingExpanded{ false };
|
||||||
QString _monospaceFont;
|
QString _monospaceFont;
|
||||||
const AudioIOStats* _audioStats;
|
const AudioIOStats* _audioStats;
|
||||||
|
QStringList _downloadUrls = QStringList();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Stats_h
|
#endif // hifi_Stats_h
|
||||||
|
|
|
@ -481,7 +481,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
||||||
|
|
||||||
// smooth transitions by relaxing _hipsOffset toward the new value
|
// smooth transitions by relaxing _hipsOffset toward the new value
|
||||||
const float HIPS_OFFSET_SLAVE_TIMESCALE = 0.15f;
|
const float HIPS_OFFSET_SLAVE_TIMESCALE = 0.15f;
|
||||||
float tau = dt > HIPS_OFFSET_SLAVE_TIMESCALE ? 1.0f : dt / HIPS_OFFSET_SLAVE_TIMESCALE;
|
float tau = dt < HIPS_OFFSET_SLAVE_TIMESCALE ? dt / HIPS_OFFSET_SLAVE_TIMESCALE : 1.0f;
|
||||||
_hipsOffset += (newHipsOffset - _hipsOffset) * tau;
|
_hipsOffset += (newHipsOffset - _hipsOffset) * tau;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,11 +384,20 @@ void SwingTwistConstraint::dynamicallyAdjustLimits(const glm::quat& rotation) {
|
||||||
|
|
||||||
swingTwistDecomposition(postRotation, Vectors::UNIT_Y, swingRotation, twistRotation);
|
swingTwistDecomposition(postRotation, Vectors::UNIT_Y, swingRotation, twistRotation);
|
||||||
|
|
||||||
// adjust swing limits
|
{ // adjust swing limits
|
||||||
glm::vec3 swungY = swingRotation * Vectors::UNIT_Y;
|
glm::vec3 swungY = swingRotation * Vectors::UNIT_Y;
|
||||||
glm::vec3 swingAxis = glm::cross(Vectors::UNIT_Y, swungY);
|
glm::vec3 swingAxis = glm::cross(Vectors::UNIT_Y, swungY);
|
||||||
float theta = atan2f(-swingAxis.z, swingAxis.x);
|
float theta = atan2f(-swingAxis.z, swingAxis.x);
|
||||||
_swingLimitFunction.dynamicallyAdjustMinDots(theta, swungY.y);
|
if (isnan(theta)) {
|
||||||
|
// atan2f() will only return NaN if either of its arguments is NaN, which can only
|
||||||
|
// happen if we've been given a bad rotation. Since a NaN value here could potentially
|
||||||
|
// cause a crash (we use the value of theta to compute indices into a std::vector)
|
||||||
|
// we specifically check for this case.
|
||||||
|
theta = 0.0f;
|
||||||
|
swungY.y = 1.0f;
|
||||||
|
}
|
||||||
|
_swingLimitFunction.dynamicallyAdjustMinDots(theta, swungY.y);
|
||||||
|
}
|
||||||
|
|
||||||
// restore twist limits
|
// restore twist limits
|
||||||
if (_twistAdjusted) {
|
if (_twistAdjusted) {
|
||||||
|
|
|
@ -182,9 +182,10 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(const glm::vec3&
|
||||||
// if this entity is a zone, use this time to determine the bestZone
|
// if this entity is a zone, use this time to determine the bestZone
|
||||||
if (entity->getType() == EntityTypes::Zone) {
|
if (entity->getType() == EntityTypes::Zone) {
|
||||||
if (!entity->getVisible()) {
|
if (!entity->getVisible()) {
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
qCDebug(entitiesrenderer) << "not visible";
|
qCDebug(entitiesrenderer) << "not visible";
|
||||||
}
|
#endif
|
||||||
else {
|
} else {
|
||||||
float entityVolumeEstimate = entity->getVolumeEstimate();
|
float entityVolumeEstimate = entity->getVolumeEstimate();
|
||||||
if (entityVolumeEstimate < _bestZoneVolume) {
|
if (entityVolumeEstimate < _bestZoneVolume) {
|
||||||
_bestZoneVolume = entityVolumeEstimate;
|
_bestZoneVolume = entityVolumeEstimate;
|
||||||
|
|
|
@ -1157,6 +1157,12 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube);
|
||||||
|
|
||||||
|
AACube saveQueryAACube = _queryAACube;
|
||||||
|
checkAndAdjustQueryAACube();
|
||||||
|
if (saveQueryAACube != _queryAACube) {
|
||||||
|
somethingChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (somethingChanged) {
|
if (somethingChanged) {
|
||||||
uint64_t now = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
|
|
|
@ -76,7 +76,9 @@ bool FBXGeometry::convexHullContains(const glm::vec3& point) const {
|
||||||
|
|
||||||
auto checkEachPrimitive = [=](FBXMesh& mesh, QVector<int> indices, int primitiveSize) -> bool {
|
auto checkEachPrimitive = [=](FBXMesh& mesh, QVector<int> indices, int primitiveSize) -> bool {
|
||||||
// Check whether the point is "behind" all the primitives.
|
// Check whether the point is "behind" all the primitives.
|
||||||
for (int j = 0; j < indices.size(); j += primitiveSize) {
|
for (int j = 0;
|
||||||
|
j < indices.size() - 2; // -2 in case the vertices aren't the right size -- we access j + 2 below
|
||||||
|
j += primitiveSize) {
|
||||||
if (!isPointBehindTrianglesPlane(point,
|
if (!isPointBehindTrianglesPlane(point,
|
||||||
mesh.vertices[indices[j]],
|
mesh.vertices[indices[j]],
|
||||||
mesh.vertices[indices[j + 1]],
|
mesh.vertices[indices[j + 1]],
|
||||||
|
|
|
@ -179,7 +179,7 @@ void OBJFace::addFrom(const OBJFace* face, int index) { // add using data from f
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool replyOK(QNetworkReply* netReply, QUrl url) { // This will be reworked when we make things asynchronous
|
static bool replyOK(QNetworkReply* netReply, QUrl url) { // This will be reworked when we make things asynchronous
|
||||||
return (netReply->isFinished() &&
|
return (netReply && netReply->isFinished() &&
|
||||||
(url.toString().startsWith("file", Qt::CaseInsensitive) ? // file urls don't have http status codes
|
(url.toString().startsWith("file", Qt::CaseInsensitive) ? // file urls don't have http status codes
|
||||||
netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString().isEmpty() :
|
netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString().isEmpty() :
|
||||||
(netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200)));
|
(netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200)));
|
||||||
|
@ -191,11 +191,10 @@ bool OBJReader::isValidTexture(const QByteArray &filename) {
|
||||||
}
|
}
|
||||||
QUrl candidateUrl = _url.resolved(QUrl(filename));
|
QUrl candidateUrl = _url.resolved(QUrl(filename));
|
||||||
QNetworkReply *netReply = request(candidateUrl, true);
|
QNetworkReply *netReply = request(candidateUrl, true);
|
||||||
if (!netReply) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool isValid = replyOK(netReply, candidateUrl);
|
bool isValid = replyOK(netReply, candidateUrl);
|
||||||
netReply->deleteLater();
|
if (netReply) {
|
||||||
|
netReply->deleteLater();
|
||||||
|
}
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,20 +263,19 @@ QNetworkReply* OBJReader::request(QUrl& url, bool isTest) {
|
||||||
if (!qApp) {
|
if (!qApp) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
bool aboutToQuit{ false };
|
||||||
|
auto connection = QObject::connect(qApp, &QCoreApplication::aboutToQuit, [&] {
|
||||||
|
aboutToQuit = true;
|
||||||
|
});
|
||||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||||
QNetworkRequest netRequest(url);
|
QNetworkRequest netRequest(url);
|
||||||
QNetworkReply* netReply = isTest ? networkAccessManager.head(netRequest) : networkAccessManager.get(netRequest);
|
QNetworkReply* netReply = isTest ? networkAccessManager.head(netRequest) : networkAccessManager.get(netRequest);
|
||||||
if (!qApp) {
|
if (!qApp || aboutToQuit) {
|
||||||
return netReply;
|
return nullptr;
|
||||||
}
|
}
|
||||||
QEventLoop loop; // Create an event loop that will quit when we get the finished signal
|
QEventLoop loop; // Create an event loop that will quit when we get the finished signal
|
||||||
QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit()));
|
QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||||
loop.exec(); // Nothing is going to happen on this whole run thread until we get this
|
loop.exec(); // Nothing is going to happen on this whole run thread until we get this
|
||||||
|
|
||||||
bool aboutToQuit { false };
|
|
||||||
auto connection = QObject::connect(qApp, &QCoreApplication::aboutToQuit, [&] {
|
|
||||||
aboutToQuit = true;
|
|
||||||
});
|
|
||||||
static const int WAIT_TIMEOUT_MS = 500;
|
static const int WAIT_TIMEOUT_MS = 500;
|
||||||
while (qApp && !aboutToQuit && !netReply->isReadable()) {
|
while (qApp && !aboutToQuit && !netReply->isReadable()) {
|
||||||
netReply->waitForReadyRead(WAIT_TIMEOUT_MS); // so we might as well block this thread waiting for the response, rather than
|
netReply->waitForReadyRead(WAIT_TIMEOUT_MS); // so we might as well block this thread waiting for the response, rather than
|
||||||
|
@ -570,9 +568,11 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping,
|
||||||
parseMaterialLibrary(netReply);
|
parseMaterialLibrary(netReply);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(modelformat) << "OBJ Reader WARNING:" << libraryName << "did not answer. Got"
|
qCDebug(modelformat) << "OBJ Reader WARNING:" << libraryName << "did not answer. Got"
|
||||||
<< netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
|
<< (!netReply ? "aborted" : netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString());
|
||||||
|
}
|
||||||
|
if (netReply) {
|
||||||
|
netReply->deleteLater();
|
||||||
}
|
}
|
||||||
netReply->deleteLater();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,17 +32,25 @@ OffscreenGLCanvas::~OffscreenGLCanvas() {
|
||||||
_context->doneCurrent();
|
_context->doneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
|
bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
|
||||||
if (nullptr != sharedContext) {
|
if (nullptr != sharedContext) {
|
||||||
sharedContext->doneCurrent();
|
sharedContext->doneCurrent();
|
||||||
_context->setShareContext(sharedContext);
|
_context->setShareContext(sharedContext);
|
||||||
}
|
}
|
||||||
_context->setFormat(getDefaultOpenGLSurfaceFormat());
|
_context->setFormat(getDefaultOpenGLSurfaceFormat());
|
||||||
_context->create();
|
if (_context->create()) {
|
||||||
|
_offscreenSurface->setFormat(_context->format());
|
||||||
|
_offscreenSurface->create();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
_offscreenSurface->setFormat(_context->format());
|
qWarning() << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
||||||
_offscreenSurface->create();
|
qWarning() << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||||
|
qWarning() << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
|
||||||
|
qWarning() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
||||||
|
qWarning() << "Failed to create OffscreenGLCanvas";
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OffscreenGLCanvas::makeCurrent() {
|
bool OffscreenGLCanvas::makeCurrent() {
|
||||||
|
|
|
@ -23,7 +23,7 @@ class OffscreenGLCanvas : public QObject {
|
||||||
public:
|
public:
|
||||||
OffscreenGLCanvas();
|
OffscreenGLCanvas();
|
||||||
~OffscreenGLCanvas();
|
~OffscreenGLCanvas();
|
||||||
void create(QOpenGLContext* sharedContext = nullptr);
|
bool create(QOpenGLContext* sharedContext = nullptr);
|
||||||
bool makeCurrent();
|
bool makeCurrent();
|
||||||
void doneCurrent();
|
void doneCurrent();
|
||||||
QOpenGLContext* getContext() {
|
QOpenGLContext* getContext() {
|
||||||
|
|
|
@ -132,7 +132,12 @@ QEvent* OffscreenQmlRenderThread::Queue::take() {
|
||||||
}
|
}
|
||||||
|
|
||||||
OffscreenQmlRenderThread::OffscreenQmlRenderThread(OffscreenQmlSurface* surface, QOpenGLContext* shareContext) : _surface(surface) {
|
OffscreenQmlRenderThread::OffscreenQmlRenderThread(OffscreenQmlSurface* surface, QOpenGLContext* shareContext) : _surface(surface) {
|
||||||
_canvas.create(shareContext);
|
if (!_canvas.create(shareContext)) {
|
||||||
|
static const char* error = "Failed to create OffscreenGLCanvas";
|
||||||
|
qWarning() << error;
|
||||||
|
throw error;
|
||||||
|
};
|
||||||
|
|
||||||
_renderControl = new QMyQuickRenderControl();
|
_renderControl = new QMyQuickRenderControl();
|
||||||
QQuickWindow::setDefaultAlphaBuffer(true);
|
QQuickWindow::setDefaultAlphaBuffer(true);
|
||||||
// Create a QQuickWindow that is associated with our render control.
|
// Create a QQuickWindow that is associated with our render control.
|
||||||
|
|
|
@ -72,11 +72,15 @@ void GeometryReader::run() {
|
||||||
const bool grabLightmaps = true;
|
const bool grabLightmaps = true;
|
||||||
const float lightmapLevel = 1.0f;
|
const float lightmapLevel = 1.0f;
|
||||||
fbxgeo = readFBX(_data, _mapping, _url.path(), grabLightmaps, lightmapLevel);
|
fbxgeo = readFBX(_data, _mapping, _url.path(), grabLightmaps, lightmapLevel);
|
||||||
|
if (fbxgeo->meshes.size() == 0 && fbxgeo->joints.size() == 0) {
|
||||||
|
// empty fbx geometry, indicates error
|
||||||
|
throw QString("empty geometry, possibly due to an unsupported FBX version");
|
||||||
|
}
|
||||||
} else if (_url.path().toLower().endsWith(".obj")) {
|
} else if (_url.path().toLower().endsWith(".obj")) {
|
||||||
fbxgeo = OBJReader().readOBJ(_data, _mapping, _url);
|
fbxgeo = OBJReader().readOBJ(_data, _mapping, _url);
|
||||||
} else {
|
} else {
|
||||||
QString errorStr("unsupported format");
|
QString errorStr("unsupported format");
|
||||||
emit onError(NetworkGeometry::ModelParseError, errorStr);
|
throw errorStr;
|
||||||
}
|
}
|
||||||
emit onSuccess(fbxgeo);
|
emit onSuccess(fbxgeo);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -56,7 +56,7 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con
|
||||||
bool validAlpha = false;
|
bool validAlpha = false;
|
||||||
bool alphaAsMask = true;
|
bool alphaAsMask = true;
|
||||||
const uint8 OPAQUE_ALPHA = 255;
|
const uint8 OPAQUE_ALPHA = 255;
|
||||||
const uint8 TRANSLUCENT_ALPHA = 0;
|
const uint8 TRANSPARENT_ALPHA = 0;
|
||||||
if (image.hasAlphaChannel()) {
|
if (image.hasAlphaChannel()) {
|
||||||
std::map<uint8, uint32> alphaHistogram;
|
std::map<uint8, uint32> alphaHistogram;
|
||||||
|
|
||||||
|
@ -70,10 +70,7 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con
|
||||||
for (int x = 0; x < image.width(); ++x) {
|
for (int x = 0; x < image.width(); ++x) {
|
||||||
auto alpha = qAlpha(data[x]);
|
auto alpha = qAlpha(data[x]);
|
||||||
alphaHistogram[alpha] ++;
|
alphaHistogram[alpha] ++;
|
||||||
if (alpha != OPAQUE_ALPHA) {
|
validAlpha = validAlpha || (alpha != OPAQUE_ALPHA);
|
||||||
validAlpha = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,10 +78,10 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con
|
||||||
if (validAlpha && (alphaHistogram.size() > 1)) {
|
if (validAlpha && (alphaHistogram.size() > 1)) {
|
||||||
auto totalNumPixels = image.height() * image.width();
|
auto totalNumPixels = image.height() * image.width();
|
||||||
auto numOpaques = alphaHistogram[OPAQUE_ALPHA];
|
auto numOpaques = alphaHistogram[OPAQUE_ALPHA];
|
||||||
auto numTranslucents = alphaHistogram[TRANSLUCENT_ALPHA];
|
auto numTransparents = alphaHistogram[TRANSPARENT_ALPHA];
|
||||||
auto numTransparents = totalNumPixels - numOpaques - numTranslucents;
|
auto numTranslucents = totalNumPixels - numOpaques - numTransparents;
|
||||||
|
|
||||||
alphaAsMask = ((numTransparents / (double)totalNumPixels) < 0.05);
|
alphaAsMask = ((numTranslucents / (double)totalNumPixels) < 0.05);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,44 +159,45 @@ void ResourceCache::clearUnusedResource() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceCache::attemptRequest(Resource* resource) {
|
void ResourceCacheSharedItems::appendActiveRequest(Resource* resource) {
|
||||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
Lock lock(_mutex);
|
||||||
|
_loadingRequests.append(resource);
|
||||||
// Disable request limiting for ATP
|
|
||||||
if (resource->getURL().scheme() != URL_SCHEME_ATP) {
|
|
||||||
if (_requestsActive >= _requestLimit) {
|
|
||||||
// wait until a slot becomes available
|
|
||||||
sharedItems->_pendingRequests.append(resource);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
++_requestsActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
sharedItems->_loadingRequests.append(resource);
|
|
||||||
resource->makeRequest();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceCache::requestCompleted(Resource* resource) {
|
void ResourceCacheSharedItems::appendPendingRequest(Resource* resource) {
|
||||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
Lock lock(_mutex);
|
||||||
sharedItems->_loadingRequests.removeOne(resource);
|
_pendingRequests.append(resource);
|
||||||
if (resource->getURL().scheme() != URL_SCHEME_ATP) {
|
|
||||||
--_requestsActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
attemptHighestPriorityRequest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceCache::attemptHighestPriorityRequest() {
|
QList<QPointer<Resource>> ResourceCacheSharedItems::getPendingRequests() const {
|
||||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
Lock lock(_mutex);
|
||||||
|
return _pendingRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ResourceCacheSharedItems::getPendingRequestsCount() const {
|
||||||
|
Lock lock(_mutex);
|
||||||
|
return _pendingRequests.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Resource*> ResourceCacheSharedItems::getLoadingRequests() const {
|
||||||
|
Lock lock(_mutex);
|
||||||
|
return _loadingRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceCacheSharedItems::removeRequest(Resource* resource) {
|
||||||
|
Lock lock(_mutex);
|
||||||
|
_loadingRequests.removeOne(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource* ResourceCacheSharedItems::getHighestPendingRequest() {
|
||||||
|
Lock lock(_mutex);
|
||||||
// look for the highest priority pending request
|
// look for the highest priority pending request
|
||||||
int highestIndex = -1;
|
int highestIndex = -1;
|
||||||
float highestPriority = -FLT_MAX;
|
float highestPriority = -FLT_MAX;
|
||||||
for (int i = 0; i < sharedItems->_pendingRequests.size(); ) {
|
for (int i = 0; i < _pendingRequests.size();) {
|
||||||
Resource* resource = sharedItems->_pendingRequests.at(i).data();
|
Resource* resource = _pendingRequests.at(i).data();
|
||||||
if (!resource) {
|
if (!resource) {
|
||||||
sharedItems->_pendingRequests.removeAt(i);
|
_pendingRequests.removeAt(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
float priority = resource->getLoadPriority();
|
float priority = resource->getLoadPriority();
|
||||||
|
@ -206,7 +207,45 @@ bool ResourceCache::attemptHighestPriorityRequest() {
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return (highestIndex >= 0) && attemptRequest(sharedItems->_pendingRequests.takeAt(highestIndex));
|
if (highestIndex >= 0) {
|
||||||
|
return _pendingRequests.takeAt(highestIndex);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceCache::attemptRequest(Resource* resource) {
|
||||||
|
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||||
|
|
||||||
|
// Disable request limiting for ATP
|
||||||
|
if (resource->getURL().scheme() != URL_SCHEME_ATP) {
|
||||||
|
if (_requestsActive >= _requestLimit) {
|
||||||
|
// wait until a slot becomes available
|
||||||
|
sharedItems->appendPendingRequest(resource);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
++_requestsActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
sharedItems->appendActiveRequest(resource);
|
||||||
|
resource->makeRequest();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceCache::requestCompleted(Resource* resource) {
|
||||||
|
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||||
|
sharedItems->removeRequest(resource);
|
||||||
|
if (resource->getURL().scheme() != URL_SCHEME_ATP) {
|
||||||
|
--_requestsActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
attemptHighestPriorityRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceCache::attemptHighestPriorityRequest() {
|
||||||
|
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||||
|
auto resource = sharedItems->getHighestPendingRequest();
|
||||||
|
return (resource && attemptRequest(resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
const int DEFAULT_REQUEST_LIMIT = 10;
|
const int DEFAULT_REQUEST_LIMIT = 10;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#ifndef hifi_ResourceCache_h
|
#ifndef hifi_ResourceCache_h
|
||||||
#define hifi_ResourceCache_h
|
#define hifi_ResourceCache_h
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
#include <QtCore/QHash>
|
#include <QtCore/QHash>
|
||||||
#include <QtCore/QList>
|
#include <QtCore/QList>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
@ -53,12 +54,25 @@ static const qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES;
|
||||||
// object instead
|
// object instead
|
||||||
class ResourceCacheSharedItems : public Dependency {
|
class ResourceCacheSharedItems : public Dependency {
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
|
using Mutex = std::mutex;
|
||||||
|
using Lock = std::unique_lock<Mutex>;
|
||||||
public:
|
public:
|
||||||
QList<QPointer<Resource>> _pendingRequests;
|
void appendPendingRequest(Resource* newRequest);
|
||||||
QList<Resource*> _loadingRequests;
|
void appendActiveRequest(Resource* newRequest);
|
||||||
|
void removeRequest(Resource* doneRequest);
|
||||||
|
QList<QPointer<Resource>> getPendingRequests() const;
|
||||||
|
uint32_t getPendingRequestsCount() const;
|
||||||
|
QList<Resource*> getLoadingRequests() const;
|
||||||
|
Resource* getHighestPendingRequest();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResourceCacheSharedItems() { }
|
ResourceCacheSharedItems() { }
|
||||||
virtual ~ResourceCacheSharedItems() { }
|
virtual ~ResourceCacheSharedItems() { }
|
||||||
|
|
||||||
|
mutable Mutex _mutex;
|
||||||
|
QList<QPointer<Resource>> _pendingRequests;
|
||||||
|
QList<Resource*> _loadingRequests;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,11 +89,11 @@ public:
|
||||||
void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize);
|
void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize);
|
||||||
qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; }
|
qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; }
|
||||||
|
|
||||||
static const QList<Resource*>& getLoadingRequests()
|
static const QList<Resource*> getLoadingRequests()
|
||||||
{ return DependencyManager::get<ResourceCacheSharedItems>()->_loadingRequests; }
|
{ return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequests(); }
|
||||||
|
|
||||||
static int getPendingRequestCount()
|
static int getPendingRequestCount()
|
||||||
{ return DependencyManager::get<ResourceCacheSharedItems>()->_pendingRequests.size(); }
|
{ return DependencyManager::get<ResourceCacheSharedItems>()->getPendingRequestsCount(); }
|
||||||
|
|
||||||
ResourceCache(QObject* parent = NULL);
|
ResourceCache(QObject* parent = NULL);
|
||||||
virtual ~ResourceCache();
|
virtual ~ResourceCache();
|
||||||
|
|
|
@ -571,6 +571,7 @@ void Model::removeFromScene(std::shared_ptr<render::Scene> scene, render::Pendin
|
||||||
}
|
}
|
||||||
_renderItems.clear();
|
_renderItems.clear();
|
||||||
_renderItemsSet.clear();
|
_renderItemsSet.clear();
|
||||||
|
_meshGroupsKnown = false;
|
||||||
_readyWhenAdded = false;
|
_readyWhenAdded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,6 @@ void SpatiallyNestable::setParentID(const QUuid& parentID) {
|
||||||
_parentKnowsMe = false;
|
_parentKnowsMe = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
checkAndAdjustQueryAACube();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform SpatiallyNestable::getParentTransform(bool& success, int depth) const {
|
Transform SpatiallyNestable::getParentTransform(bool& success, int depth) const {
|
||||||
|
@ -140,7 +139,6 @@ void SpatiallyNestable::forgetChild(SpatiallyNestablePointer newChild) const {
|
||||||
|
|
||||||
void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) {
|
void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) {
|
||||||
_parentJointIndex = parentJointIndex;
|
_parentJointIndex = parentJointIndex;
|
||||||
checkAndAdjustQueryAACube();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position,
|
glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position,
|
||||||
|
@ -754,7 +752,6 @@ void SpatiallyNestable::forEachDescendant(std::function<void(SpatiallyNestablePo
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatiallyNestable::locationChanged() {
|
void SpatiallyNestable::locationChanged() {
|
||||||
checkAndAdjustQueryAACube();
|
|
||||||
forEachChild([&](SpatiallyNestablePointer object) {
|
forEachChild([&](SpatiallyNestablePointer object) {
|
||||||
object->locationChanged();
|
object->locationChanged();
|
||||||
});
|
});
|
||||||
|
@ -781,7 +778,6 @@ void SpatiallyNestable::setQueryAACube(const AACube& queryAACube) {
|
||||||
if (queryAACube.getScale() > 0.0f) {
|
if (queryAACube.getScale() > 0.0f) {
|
||||||
_queryAACubeSet = true;
|
_queryAACubeSet = true;
|
||||||
}
|
}
|
||||||
checkAndAdjustQueryAACube();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpatiallyNestable::queryAABoxNeedsUpdate() const {
|
bool SpatiallyNestable::queryAABoxNeedsUpdate() const {
|
||||||
|
|
|
@ -157,7 +157,7 @@ protected:
|
||||||
mutable QHash<QUuid, SpatiallyNestableWeakPointer> _children;
|
mutable QHash<QUuid, SpatiallyNestableWeakPointer> _children;
|
||||||
|
|
||||||
virtual void locationChanged(); // called when a this object's location has changed
|
virtual void locationChanged(); // called when a this object's location has changed
|
||||||
virtual void dimensionsChanged() { checkAndAdjustQueryAACube(); } // called when a this object's dimensions have changed
|
virtual void dimensionsChanged() { } // called when a this object's dimensions have changed
|
||||||
|
|
||||||
// _queryAACube is used to decide where something lives in the octree
|
// _queryAACube is used to decide where something lives in the octree
|
||||||
mutable AACube _queryAACube;
|
mutable AACube _queryAACube;
|
||||||
|
|
Loading…
Reference in a new issue