mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-14 05:26:32 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into supportLargeClockSkew
This commit is contained in:
commit
72c81e2378
25 changed files with 365 additions and 116 deletions
|
@ -201,7 +201,7 @@ var toolBar = (function() {
|
|||
}, true, false);
|
||||
|
||||
newModelButton = toolBar.addTool({
|
||||
imageURL: toolIconUrl + "upload-01.svg",
|
||||
imageURL: toolIconUrl + "model-01.svg",
|
||||
subImage: {
|
||||
x: 0,
|
||||
y: Tool.IMAGE_WIDTH,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
@ -8,67 +9,68 @@ Rectangle {
|
|||
|
||||
signal sendToScript(var message);
|
||||
property var values: [];
|
||||
property var host: AddressManager.hostname
|
||||
property alias destination: addressLine.text
|
||||
readonly property string nullDestination: "169.254.0.1"
|
||||
property bool running: false
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
Window.domainChanged.connect(function(newDomain){
|
||||
if (newDomain !== root.host) {
|
||||
root.host = AddressManager.hostname;
|
||||
}
|
||||
});
|
||||
function statusReport() {
|
||||
console.log("PERF status connected: " + AddressManager.isConnected);
|
||||
}
|
||||
|
||||
onHostChanged: {
|
||||
if (root.running) {
|
||||
if (host !== "Dreaming" && host !== "Playa") {
|
||||
|
||||
Timer {
|
||||
id: readyStateTimer
|
||||
interval: 500
|
||||
repeat: true
|
||||
running: false
|
||||
onTriggered: {
|
||||
if (!root.running) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("PERF new domain " + host)
|
||||
if (host === "Dreaming") {
|
||||
AddressManager.handleLookupString("Playa");
|
||||
if (AddressManager.isConnected) {
|
||||
console.log("PERF already connected, disconnecting");
|
||||
AddressManager.handleLookupString(root.nullDestination);
|
||||
return;
|
||||
}
|
||||
|
||||
stop();
|
||||
console.log("PERF disconnected, moving to target " + root.destination);
|
||||
AddressManager.handleLookupString(root.destination);
|
||||
|
||||
if (host === "Playa") {
|
||||
console.log("PERF starting timers and frame timing");
|
||||
// If we've arrived, start running the test
|
||||
FrameTimings.start();
|
||||
rotationTimer.start();
|
||||
stopTimer.start();
|
||||
}
|
||||
// If we've arrived, start running the test
|
||||
console.log("PERF starting timers and frame timing");
|
||||
FrameTimings.start();
|
||||
rotationTimer.start();
|
||||
stopTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function startTest() {
|
||||
console.log("PERF startTest()");
|
||||
root.running = true
|
||||
console.log("PERF current host: " + AddressManager.hostname)
|
||||
// If we're already in playa, we need to go somewhere else...
|
||||
if ("Playa" === AddressManager.hostname) {
|
||||
console.log("PERF Navigating to dreaming")
|
||||
AddressManager.handleLookupString("Dreaming/0,0,0");
|
||||
} else {
|
||||
console.log("PERF Navigating to playa")
|
||||
AddressManager.handleLookupString("Playa");
|
||||
if (!root.running) {
|
||||
root.running = true
|
||||
readyStateTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
function stopTest() {
|
||||
console.log("PERF stopTest()");
|
||||
root.running = false;
|
||||
stopTimer.stop();
|
||||
rotationTimer.stop();
|
||||
FrameTimings.finish();
|
||||
root.values = FrameTimings.getValues();
|
||||
AddressManager.handleLookupString("Dreaming/0,0,0");
|
||||
resultGraph.requestPaint();
|
||||
console.log("PERF Value Count: " + root.values.length);
|
||||
console.log("PERF Max: " + FrameTimings.max);
|
||||
console.log("PERF Min: " + FrameTimings.min);
|
||||
console.log("PERF Avg: " + FrameTimings.mean);
|
||||
console.log("PERF StdDev: " + FrameTimings.standardDeviation);
|
||||
if (root.running) {
|
||||
root.running = false;
|
||||
stopTimer.stop();
|
||||
rotationTimer.stop();
|
||||
FrameTimings.finish();
|
||||
root.values = FrameTimings.getValues();
|
||||
AddressManager.handleLookupString(root.nullDestination);
|
||||
resultGraph.requestPaint();
|
||||
console.log("PERF Value Count: " + root.values.length);
|
||||
console.log("PERF Max: " + FrameTimings.max);
|
||||
console.log("PERF Min: " + FrameTimings.min);
|
||||
console.log("PERF Avg: " + FrameTimings.mean);
|
||||
console.log("PERF StdDev: " + FrameTimings.standardDeviation);
|
||||
}
|
||||
}
|
||||
|
||||
function yaw(a) {
|
||||
|
@ -82,7 +84,6 @@ Rectangle {
|
|||
MyAvatar.setOrientationVar(yaw(Date.now() / 1000));
|
||||
}
|
||||
|
||||
property bool running: false
|
||||
|
||||
Timer {
|
||||
id: stopTimer
|
||||
|
@ -102,14 +103,43 @@ Rectangle {
|
|||
|
||||
Row {
|
||||
id: row
|
||||
anchors { left: parent.left; right: parent.right; }
|
||||
anchors { left: parent.left; right: parent.right; top: parent.top; margins: 16 }
|
||||
spacing: 8
|
||||
Button {
|
||||
text: root.running ? "Stop" : "Run"
|
||||
onClicked: root.running ? stopTest() : startTest();
|
||||
}
|
||||
Button {
|
||||
text: "Disconnect"
|
||||
onClicked: AddressManager.handleLookupString(root.nullDestination);
|
||||
}
|
||||
Button {
|
||||
text: "Connect"
|
||||
onClicked: AddressManager.handleLookupString(root.destination);
|
||||
}
|
||||
Button {
|
||||
text: "Status"
|
||||
onClicked: statusReport();
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: addressLine
|
||||
focus: true
|
||||
anchors {
|
||||
left: parent.left; right: parent.right;
|
||||
top: row.bottom; margins: 16;
|
||||
}
|
||||
text: "Playa"
|
||||
onTextChanged: console.log("PERF new target " + text);
|
||||
}
|
||||
|
||||
Settings {
|
||||
category: "Qml.Performance.RenderTest"
|
||||
property alias destination: addressLine.text
|
||||
}
|
||||
|
||||
|
||||
// Rectangle {
|
||||
// anchors { left: parent.left; right: parent.right; top: row.bottom; topMargin: 8; bottom: parent.bottom; }
|
||||
// //anchors.fill: parent
|
||||
|
@ -130,7 +160,7 @@ Rectangle {
|
|||
|
||||
Canvas {
|
||||
id: resultGraph
|
||||
anchors { left: parent.left; right: parent.right; top: row.bottom; margins: 16; bottom: parent.bottom; }
|
||||
anchors { left: parent.left; right: parent.right; top: addressLine.bottom; margins: 16; bottom: parent.bottom; }
|
||||
property real maxValue: 200;
|
||||
property real perFrame: 10000;
|
||||
property real k1: (5 / maxValue) * height;
|
||||
|
|
49
examples/utilities/render/rates.qml
Normal file
49
examples/utilities/render/rates.qml
Normal file
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// stats.qml
|
||||
// examples/utilities/cache
|
||||
//
|
||||
// Created by Zach Pomerantz on 4/1/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import "../lib/plotperf"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
|
||||
property var caches: [ ["Present", "present"], ["Present", "present"], ["New", "newFrame"], ["Dropped", "dropped"], ["Simulation", "simulation"], ["Avatar", "avatar"] ]
|
||||
property var colors: [ "#1AC567", "#00B4EF" ]
|
||||
|
||||
Grid {
|
||||
id: grid
|
||||
rows: (root.caches.length / 2); columns: 2; spacing: 8
|
||||
anchors.fill: parent
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
|
||||
model: root.caches
|
||||
|
||||
Row {
|
||||
PlotPerf {
|
||||
title: modelData[0] + " Rate"
|
||||
height: (grid.height - (grid.spacing * ((root.caches.length / 2) + 1))) / (root.caches.length / 2)
|
||||
width: grid.width / 2 - grid.spacing * 1.5
|
||||
object: Rates
|
||||
valueScale: 1
|
||||
valueUnit: "fps"
|
||||
valueNumDigits: "2"
|
||||
plots: [{
|
||||
prop: modelData[1],
|
||||
color: root.colors[index % 2]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
examples/utilities/render/renderRates.js
Normal file
21
examples/utilities/render/renderRates.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// cacheStats.js
|
||||
// examples/utilities/cache
|
||||
//
|
||||
// Zach Pomerantz, created on 4/1/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
|
||||
//
|
||||
|
||||
// Set up the qml ui
|
||||
var qml = Script.resolvePath('rates.qml');
|
||||
var window = new OverlayWindow({
|
||||
title: 'Render Rates',
|
||||
source: qml,
|
||||
width: 300,
|
||||
height: 200
|
||||
});
|
||||
window.setPosition(500, 50);
|
||||
window.closed.connect(function() { Script.stop(); });
|
67
interface/resources/qml/controls-uit/TextAction.qml
Normal file
67
interface/resources/qml/controls-uit/TextAction.qml
Normal file
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// TextField.qml
|
||||
//
|
||||
// Created by David Rowe on 21 Apr 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 "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
||||
Item {
|
||||
property string icon: ""
|
||||
property int iconSize: 30
|
||||
property string text: ""
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
|
||||
signal clicked()
|
||||
|
||||
height: Math.max(glyph.visible ? glyph.height - 4 : 0, string.visible ? string.height : 0)
|
||||
width: glyph.width + string.anchors.leftMargin + string.width
|
||||
|
||||
HiFiGlyphs {
|
||||
id: glyph
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: -2
|
||||
text: parent.icon
|
||||
size: parent.iconSize
|
||||
color: isLightColorScheme
|
||||
? (mouseArea.containsMouse ? hifi.colors.baseGrayHighlight : hifi.colors.lightGray)
|
||||
: (mouseArea.containsMouse ? hifi.colors.faintGray : hifi.colors.lightGrayText)
|
||||
visible: text !== ""
|
||||
width: visible ? implicitWidth : 0
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
id: string
|
||||
anchors {
|
||||
left: glyph.visible ? glyph.right : parent.left
|
||||
leftMargin: visible && glyph.visible ? hifi.dimensions.contentSpacing.x : 0
|
||||
verticalCenter: glyph.visible ? glyph.verticalCenter : undefined
|
||||
}
|
||||
text: parent.text
|
||||
size: hifi.fontSizes.inputLabel
|
||||
color: isLightColorScheme
|
||||
? (mouseArea.containsMouse ? hifi.colors.baseGrayHighlight : hifi.colors.lightGray)
|
||||
: (mouseArea.containsMouse ? hifi.colors.faintGray : hifi.colors.lightGrayText)
|
||||
font.underline: true;
|
||||
visible: text !== ""
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: parent.clicked()
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ Window {
|
|||
resizable: true
|
||||
destroyOnInvisible: true
|
||||
x: 40; y: 40
|
||||
implicitWidth: 400; implicitHeight: 695
|
||||
implicitWidth: 400; implicitHeight: 728
|
||||
minSize: Qt.vector2d(200, 300)
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
@ -236,7 +236,23 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer { }
|
||||
HifiControls.VerticalSpacer {
|
||||
height: hifi.dimensions.controlInterlineHeight - 3
|
||||
}
|
||||
|
||||
HifiControls.TextAction {
|
||||
id: directoryButton
|
||||
icon: hifi.glyphs.script
|
||||
iconSize: 24
|
||||
text: "Reveal Scripts Folder"
|
||||
onClicked: fileDialogHelper.openScriptsDirectory()
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors.left: parent.left
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
height: hifi.dimensions.controlInterlineHeight - 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,6 +131,7 @@
|
|||
#include "scripting/WebWindowClass.h"
|
||||
#include "scripting/WindowScriptingInterface.h"
|
||||
#include "scripting/ControllerScriptingInterface.h"
|
||||
#include "scripting/RatesScriptingInterface.h"
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
#include "SpeechRecognizer.h"
|
||||
#endif
|
||||
|
@ -1384,6 +1385,7 @@ void Application::initializeUi() {
|
|||
rootContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
|
||||
rootContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
rootContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
|
||||
rootContext->setContextProperty("Rates", new RatesScriptingInterface(this));
|
||||
|
||||
rootContext->setContextProperty("TREE_SCALE", TREE_SCALE);
|
||||
rootContext->setContextProperty("Quat", new Quat());
|
||||
|
@ -4439,6 +4441,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
// AvatarManager has some custom types
|
||||
AvatarManager::registerMetaTypes(scriptEngine);
|
||||
|
||||
scriptEngine->registerGlobalObject("Rates", new RatesScriptingInterface(this));
|
||||
|
||||
// hook our avatar and avatar hash map object into this script engine
|
||||
scriptEngine->registerGlobalObject("MyAvatar", getMyAvatar());
|
||||
qScriptRegisterMetaType(scriptEngine, audioListenModeToScriptValue, audioListenModeFromScriptValue);
|
||||
|
|
37
interface/src/scripting/RatesScriptingInterface.h
Normal file
37
interface/src/scripting/RatesScriptingInterface.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// RatesScriptingInterface.h
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Zach Pomerantz on 4/20/16.
|
||||
// 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
|
||||
//
|
||||
|
||||
#ifndef HIFI_RATES_SCRIPTING_INTERFACE_H
|
||||
#define HIFI_RATES_SCRIPTING_INTERFACE_H
|
||||
|
||||
#include <display-plugins/DisplayPlugin.h>
|
||||
|
||||
class RatesScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(float render READ getRenderRate)
|
||||
Q_PROPERTY(float present READ getPresentRate)
|
||||
Q_PROPERTY(float newFrame READ getNewFrameRate)
|
||||
Q_PROPERTY(float dropped READ getDropRate)
|
||||
Q_PROPERTY(float simulation READ getSimulationRate)
|
||||
Q_PROPERTY(float avatar READ getAvatarRate)
|
||||
|
||||
public:
|
||||
RatesScriptingInterface(QObject* parent) : QObject(parent) {}
|
||||
float getRenderRate() { return qApp->getFps(); }
|
||||
float getPresentRate() { return qApp->getActiveDisplayPlugin()->presentRate(); }
|
||||
float getNewFrameRate() { return qApp->getActiveDisplayPlugin()->newFramePresentRate(); }
|
||||
float getDropRate() { return qApp->getActiveDisplayPlugin()->droppedFrameRate(); }
|
||||
float getSimulationRate() { return qApp->getAverageSimsPerSecond(); }
|
||||
float getAvatarRate() { return qApp->getAvatarSimrate(); }
|
||||
};
|
||||
|
||||
#endif // HIFI_INTERFACE_RATES_SCRIPTING_INTERFACE_H
|
|
@ -64,9 +64,9 @@ void AnimationReader::run() {
|
|||
|
||||
if (urlValid) {
|
||||
// Parse the FBX directly from the QNetworkReply
|
||||
FBXGeometry* fbxgeo = nullptr;
|
||||
FBXGeometry::Pointer fbxgeo;
|
||||
if (_url.path().toLower().endsWith(".fbx")) {
|
||||
fbxgeo = readFBX(_data, QVariantHash(), _url.path());
|
||||
fbxgeo.reset(readFBX(_data, QVariantHash(), _url.path()));
|
||||
} else {
|
||||
QString errorStr("usupported format");
|
||||
emit onError(299, errorStr);
|
||||
|
@ -117,16 +117,16 @@ const QVector<FBXAnimationFrame>& Animation::getFramesReference() const {
|
|||
void Animation::downloadFinished(const QByteArray& data) {
|
||||
// parse the animation/fbx file on a background thread.
|
||||
AnimationReader* animationReader = new AnimationReader(_url, data);
|
||||
connect(animationReader, SIGNAL(onSuccess(FBXGeometry*)), SLOT(animationParseSuccess(FBXGeometry*)));
|
||||
connect(animationReader, SIGNAL(onSuccess(FBXGeometry::Pointer)), SLOT(animationParseSuccess(FBXGeometry::Pointer)));
|
||||
connect(animationReader, SIGNAL(onError(int, QString)), SLOT(animationParseError(int, QString)));
|
||||
QThreadPool::globalInstance()->start(animationReader);
|
||||
}
|
||||
|
||||
void Animation::animationParseSuccess(FBXGeometry* geometry) {
|
||||
void Animation::animationParseSuccess(FBXGeometry::Pointer geometry) {
|
||||
|
||||
qCDebug(animation) << "Animation parse success" << _url.toDisplayString();
|
||||
|
||||
_geometry.reset(geometry);
|
||||
_geometry = geometry;
|
||||
finishedLoading(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,12 +68,12 @@ protected:
|
|||
virtual void downloadFinished(const QByteArray& data) override;
|
||||
|
||||
protected slots:
|
||||
void animationParseSuccess(FBXGeometry* geometry);
|
||||
void animationParseSuccess(FBXGeometry::Pointer geometry);
|
||||
void animationParseError(int error, QString str);
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr<FBXGeometry> _geometry;
|
||||
FBXGeometry::Pointer _geometry;
|
||||
};
|
||||
|
||||
/// Reads geometry in a worker thread.
|
||||
|
@ -85,7 +85,7 @@ public:
|
|||
virtual void run();
|
||||
|
||||
signals:
|
||||
void onSuccess(FBXGeometry* geometry);
|
||||
void onSuccess(FBXGeometry::Pointer geometry);
|
||||
void onError(int error, QString str);
|
||||
|
||||
private:
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
static int FBXGeometryPointerMetaTypeId = qRegisterMetaType<FBXGeometry::Pointer>();
|
||||
|
||||
QStringList FBXGeometry::getJointNames() const {
|
||||
QStringList names;
|
||||
foreach (const FBXJoint& joint, joints) {
|
||||
|
|
|
@ -270,6 +270,7 @@ inline bool operator!=(const SittingPoint& lhs, const SittingPoint& rhs)
|
|||
/// A set of meshes extracted from an FBX document.
|
||||
class FBXGeometry {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<FBXGeometry>;
|
||||
|
||||
QString author;
|
||||
QString applicationName; ///< the name of the application that generated the model
|
||||
|
@ -330,6 +331,7 @@ public:
|
|||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FBXGeometry)
|
||||
Q_DECLARE_METATYPE(FBXGeometry::Pointer)
|
||||
|
||||
/// Reads FBX geometry from the supplied model and mapping data.
|
||||
/// \exception QString if an error occurs in parsing
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
using namespace gpu;
|
||||
|
||||
static int TexturePointerMetaTypeId = qRegisterMetaType<TexturePointer>();
|
||||
|
||||
std::atomic<uint32_t> Texture::_textureCPUCount{ 0 };
|
||||
std::atomic<Texture::Size> Texture::_textureCPUMemoryUsage{ 0 };
|
||||
|
@ -857,8 +858,8 @@ void TextureSource::reset(const QUrl& url) {
|
|||
_imageUrl = url;
|
||||
}
|
||||
|
||||
void TextureSource::resetTexture(gpu::Texture* texture) {
|
||||
_gpuTexture.reset(texture);
|
||||
void TextureSource::resetTexture(gpu::TexturePointer texture) {
|
||||
_gpuTexture = texture;
|
||||
}
|
||||
|
||||
bool TextureSource::isDefined() const {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <algorithm> //min max and more
|
||||
#include <bitset>
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QUrl>
|
||||
|
||||
namespace gpu {
|
||||
|
@ -469,7 +470,6 @@ protected:
|
|||
typedef std::shared_ptr<Texture> TexturePointer;
|
||||
typedef std::vector< TexturePointer > Textures;
|
||||
|
||||
|
||||
// TODO: For now TextureView works with Texture as a place holder for the Texture.
|
||||
// The overall logic should be about the same except that the Texture will be a real GL Texture under the hood
|
||||
class TextureView {
|
||||
|
@ -526,7 +526,7 @@ public:
|
|||
|
||||
void reset(const QUrl& url);
|
||||
|
||||
void resetTexture(gpu::Texture* texture);
|
||||
void resetTexture(gpu::TexturePointer texture);
|
||||
|
||||
bool isDefined() const;
|
||||
|
||||
|
@ -538,5 +538,6 @@ typedef std::shared_ptr< TextureSource > TextureSourcePointer;
|
|||
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(gpu::TexturePointer)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -143,40 +143,38 @@ void GeometryReader::run() {
|
|||
QString urlname = _url.path().toLower();
|
||||
if (!urlname.isEmpty() && !_url.path().isEmpty() &&
|
||||
(_url.path().toLower().endsWith(".fbx") || _url.path().toLower().endsWith(".obj"))) {
|
||||
FBXGeometry* fbxGeometry = nullptr;
|
||||
FBXGeometry::Pointer fbxGeometry;
|
||||
|
||||
if (_url.path().toLower().endsWith(".fbx")) {
|
||||
fbxGeometry = readFBX(_data, _mapping, _url.path());
|
||||
fbxGeometry.reset(readFBX(_data, _mapping, _url.path()));
|
||||
if (fbxGeometry->meshes.size() == 0 && fbxGeometry->joints.size() == 0) {
|
||||
throw QString("empty geometry, possibly due to an unsupported FBX version");
|
||||
}
|
||||
} else if (_url.path().toLower().endsWith(".obj")) {
|
||||
fbxGeometry = OBJReader().readOBJ(_data, _mapping, _url);
|
||||
fbxGeometry.reset(OBJReader().readOBJ(_data, _mapping, _url));
|
||||
} else {
|
||||
throw QString("unsupported format");
|
||||
}
|
||||
|
||||
// Ensure the resource has not been deleted, and won't be while invokeMethod is in flight.
|
||||
// Ensure the resource has not been deleted
|
||||
auto resource = _resource.toStrongRef();
|
||||
if (!resource) {
|
||||
qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref";
|
||||
delete fbxGeometry;
|
||||
} else {
|
||||
QMetaObject::invokeMethod(resource.data(), "setGeometryDefinition", Qt::BlockingQueuedConnection, Q_ARG(void*, fbxGeometry));
|
||||
QMetaObject::invokeMethod(resource.data(), "setGeometryDefinition",
|
||||
Q_ARG(FBXGeometry::Pointer, fbxGeometry));
|
||||
}
|
||||
} else {
|
||||
throw QString("url is invalid");
|
||||
}
|
||||
} catch (const QString& error) {
|
||||
|
||||
qCDebug(modelnetworking) << "Error reading " << _url << ": " << error;
|
||||
qCDebug(modelnetworking) << "Error parsing model for" << _url << ":" << error;
|
||||
|
||||
auto resource = _resource.toStrongRef();
|
||||
// Ensure the resoruce has not been deleted, and won't be while invokeMethod is in flight.
|
||||
if (!resource) {
|
||||
qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref";
|
||||
} else {
|
||||
QMetaObject::invokeMethod(resource.data(), "finishedLoading", Qt::BlockingQueuedConnection, Q_ARG(bool, false));
|
||||
if (resource) {
|
||||
QMetaObject::invokeMethod(resource.data(), "finishedLoading",
|
||||
Q_ARG(bool, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +188,7 @@ public:
|
|||
virtual void downloadFinished(const QByteArray& data) override;
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE void setGeometryDefinition(void* fbxGeometry);
|
||||
Q_INVOKABLE void setGeometryDefinition(FBXGeometry::Pointer fbxGeometry);
|
||||
|
||||
private:
|
||||
QVariantHash _mapping;
|
||||
|
@ -200,9 +198,9 @@ void GeometryDefinitionResource::downloadFinished(const QByteArray& data) {
|
|||
QThreadPool::globalInstance()->start(new GeometryReader(_self, _url, _mapping, data));
|
||||
}
|
||||
|
||||
void GeometryDefinitionResource::setGeometryDefinition(void* fbxGeometry) {
|
||||
void GeometryDefinitionResource::setGeometryDefinition(FBXGeometry::Pointer fbxGeometry) {
|
||||
// Assume ownership of the geometry pointer
|
||||
_geometry.reset(static_cast<FBXGeometry*>(fbxGeometry));
|
||||
_geometry = fbxGeometry;
|
||||
|
||||
// Copy materials
|
||||
QHash<QString, size_t> materialIDAtlas;
|
||||
|
|
|
@ -330,7 +330,7 @@ void ImageReader::run() {
|
|||
return;
|
||||
}
|
||||
|
||||
gpu::Texture* texture = nullptr;
|
||||
gpu::TexturePointer texture = nullptr;
|
||||
{
|
||||
// Double-check the resource still exists between long operations.
|
||||
auto resource = _resource.toStrongRef();
|
||||
|
@ -342,36 +342,32 @@ void ImageReader::run() {
|
|||
auto url = _url.toString().toStdString();
|
||||
|
||||
PROFILE_RANGE_EX(__FUNCTION__"::textureLoader", 0xffffff00, nullptr);
|
||||
texture = resource.dynamicCast<NetworkTexture>()->getTextureLoader()(image, url);
|
||||
texture.reset(resource.dynamicCast<NetworkTexture>()->getTextureLoader()(image, url));
|
||||
}
|
||||
|
||||
// Ensure the resource has not been deleted, and won't be while invokeMethod is in flight.
|
||||
// Ensure the resource has not been deleted
|
||||
auto resource = _resource.toStrongRef();
|
||||
if (!resource) {
|
||||
qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref";
|
||||
delete texture;
|
||||
} else {
|
||||
QMetaObject::invokeMethod(resource.data(), "setImage", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(void*, texture),
|
||||
QMetaObject::invokeMethod(resource.data(), "setImage",
|
||||
Q_ARG(gpu::TexturePointer, texture),
|
||||
Q_ARG(int, originalWidth), Q_ARG(int, originalHeight));
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkTexture::setImage(void* voidTexture, int originalWidth,
|
||||
void NetworkTexture::setImage(gpu::TexturePointer texture, int originalWidth,
|
||||
int originalHeight) {
|
||||
_originalWidth = originalWidth;
|
||||
_originalHeight = originalHeight;
|
||||
|
||||
gpu::Texture* texture = static_cast<gpu::Texture*>(voidTexture);
|
||||
|
||||
// Passing ownership
|
||||
_textureSource->resetTexture(texture);
|
||||
auto gpuTexture = _textureSource->getGPUTexture();
|
||||
|
||||
if (gpuTexture) {
|
||||
_width = gpuTexture->getWidth();
|
||||
_height = gpuTexture->getHeight();
|
||||
setSize(gpuTexture->getStoredSize());
|
||||
if (texture) {
|
||||
_width = texture->getWidth();
|
||||
_height = texture->getHeight();
|
||||
setSize(texture->getStoredSize());
|
||||
} else {
|
||||
// FIXME: If !gpuTexture, we failed to load!
|
||||
_width = _height = 0;
|
||||
|
|
|
@ -128,7 +128,6 @@ public:
|
|||
signals:
|
||||
void networkTextureCreated(const QWeakPointer<NetworkTexture>& self);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool isCacheable() const override { return _loaded; }
|
||||
|
@ -136,9 +135,7 @@ protected:
|
|||
virtual void downloadFinished(const QByteArray& data) override;
|
||||
|
||||
Q_INVOKABLE void loadContent(const QByteArray& content);
|
||||
// FIXME: This void* should be a gpu::Texture* but i cannot get it to work for now, moving on...
|
||||
Q_INVOKABLE void setImage(void* texture, int originalWidth, int originalHeight);
|
||||
|
||||
Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight);
|
||||
|
||||
private:
|
||||
TextureType _type;
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
MessageID AssetClient::_currentID = 0;
|
||||
|
||||
AssetClient::AssetClient() {
|
||||
|
||||
setCustomDeleter([](Dependency* dependency){
|
||||
static_cast<AssetClient*>(dependency)->deleteLater();
|
||||
});
|
||||
|
@ -502,7 +501,18 @@ bool AssetClient::cancelGetAssetInfoRequest(MessageID id) {
|
|||
bool AssetClient::cancelGetAssetRequest(MessageID id) {
|
||||
// Search through each pending mapping request for id `id`
|
||||
for (auto& kv : _pendingRequests) {
|
||||
if (kv.second.erase(id)) {
|
||||
auto& messageCallbackMap = kv.second;
|
||||
auto requestIt = messageCallbackMap.find(id);
|
||||
if (requestIt != kv.second.end()) {
|
||||
|
||||
auto& message = requestIt->second.message;
|
||||
if (message) {
|
||||
// disconnect from all signals emitting from the pending message
|
||||
disconnect(message.data(), nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
messageCallbackMap.erase(requestIt);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -606,8 +606,9 @@ void Resource::handleReplyFinished() {
|
|||
const int BASE_DELAY_MS = 1000;
|
||||
if (_attempts++ < MAX_ATTEMPTS) {
|
||||
auto waitTime = BASE_DELAY_MS * (int)pow(2.0, _attempts);
|
||||
qCDebug(networking).nospace() << "Retrying to load the asset in " << waitTime
|
||||
<< "ms, attempt " << _attempts << " of " << MAX_ATTEMPTS;
|
||||
qCDebug(networking) << "Server unavailable for" << _url <<
|
||||
"retrying in " << waitTime << "ms," <<
|
||||
"attempt " << _attempts + 1 << "of" << MAX_ATTEMPTS;
|
||||
QTimer::singleShot(waitTime, this, &Resource::attemptRequest);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
#line __LINE__
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// stars.frag
|
||||
// fragment shader
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define hifi_Shared_RateCounter_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
|
||||
|
@ -20,6 +21,8 @@
|
|||
template <uint32_t INTERVAL = MSECS_PER_SECOND, uint8_t PRECISION = 2>
|
||||
class RateCounter {
|
||||
public:
|
||||
RateCounter() { _rate = 0; } // avoid use of std::atomic copy ctor
|
||||
|
||||
void increment(size_t count = 1) {
|
||||
auto now = usecTimestampNow();
|
||||
float currentIntervalMs = (now - _start) / (float) USECS_PER_MSEC;
|
||||
|
@ -42,8 +45,8 @@ public:
|
|||
private:
|
||||
uint64_t _start { usecTimestampNow() };
|
||||
size_t _count { 0 };
|
||||
float _rate { 0 };
|
||||
const float _scale { powf(10, PRECISION) };
|
||||
std::atomic<float> _rate;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include <QtCore/QFile>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QRegularExpression>
|
||||
#include <QDesktopServices>
|
||||
|
||||
#include "PathUtils.h"
|
||||
|
||||
|
||||
QUrl FileDialogHelper::home() {
|
||||
|
@ -103,3 +106,7 @@ QStringList FileDialogHelper::drives() {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileDialogHelper::openScriptsDirectory() {
|
||||
QDesktopServices::openUrl(defaultScriptsLocation());
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ public:
|
|||
Q_INVOKABLE bool validFolder(const QString& path);
|
||||
Q_INVOKABLE QUrl pathToUrl(const QString& path);
|
||||
Q_INVOKABLE QUrl saveHelper(const QString& saveText, const QUrl& currentFolder, const QStringList& selectionFilters);
|
||||
|
||||
Q_INVOKABLE void openScriptsDirectory();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -64,6 +64,15 @@ void MainWindow::saveGeometry() {
|
|||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent* event) {
|
||||
// It is the job of Application::quit() to shut things down properly when it is finished with its event loop.
|
||||
// But if we don't explicitly ignore this event now, the window and application event loop will close
|
||||
// before we've had a chance to act on the aboutToClose signal. This will leaves a zombie process on all platforms.
|
||||
// To repro:
|
||||
// Open a QML modal dialog (e.g., select an avatar to wear), but don't dismiss it.
|
||||
// Close the application with the operating system window close button (not the menu Quit)
|
||||
// With ignore: App will wait until you accept or dismiss the dialog and log "Normal exit".
|
||||
// Without ignore: App will close immediately, and nothing will log about quitting or exit.
|
||||
event->ignore();
|
||||
qApp->quit();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
exports.searchPaths = function(name, binaryType, releaseType) {
|
||||
function platformExtension(name) {
|
||||
if (name == "Interface" || name == "High Fidelity") {
|
||||
if (process.platform == "darwin") {
|
||||
return ".app/Contents/MacOS/" + name
|
||||
} else if (process.platform == "win32") {
|
||||
return ".exe"
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
function platformExtension(name) {
|
||||
if (name == "Interface") {
|
||||
if (process.platform == "darwin") {
|
||||
return ".app/Contents/MacOS/" + name
|
||||
} else if (process.platform == "win32") {
|
||||
return ".exe"
|
||||
} else {
|
||||
return process.platform == "win32" ? ".exe" : ""
|
||||
return ""
|
||||
}
|
||||
} else {
|
||||
return process.platform == "win32" ? ".exe" : ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exports.searchPaths = function(name, binaryType, releaseType) {
|
||||
var extension = platformExtension(name);
|
||||
var devBasePath = "../build/" + name + "/";
|
||||
|
||||
|
@ -68,6 +69,7 @@ exports.discoveredPath = function (name, binaryType, releaseType) {
|
|||
|
||||
try {
|
||||
var stats = fs.lstatSync(testPath);
|
||||
var extension = platformExtension(name);
|
||||
|
||||
if (stats.isFile() || (stats.isDirectory() && extension == ".app")) {
|
||||
console.log("Found " + name + " at " + testPath);
|
||||
|
@ -81,11 +83,6 @@ exports.discoveredPath = function (name, binaryType, releaseType) {
|
|||
return null;
|
||||
}
|
||||
|
||||
// for a released server console on OS X, assume the name of the interface executable is "High Fidelity"
|
||||
if (releaseType && process.platform == "darwin" && name == "Interface") {
|
||||
name = "High Fidelity";
|
||||
}
|
||||
|
||||
// attempt to find a binary at the usual paths, return null if it doesn't exist
|
||||
return binaryFromPaths(name, this.searchPaths(name, binaryType, releaseType));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue