Merge branch 'master' of github.com:highfidelity/hifi into fix/tex-invoke-method

This commit is contained in:
Zach Pomerantz 2016-04-04 11:00:03 -07:00
commit 2bd53935fc
23 changed files with 670 additions and 610 deletions

View file

@ -16,7 +16,7 @@ Contributing
git checkout -b new_branch_name git checkout -b new_branch_name
``` ```
4. Code 4. Code
* Follow the [coding standard](http://docs.highfidelity.io/v1.0/docs/coding-standard) * Follow the [coding standard](https://readme.highfidelity.com/v1.0/docs/coding-standard)
5. Commit 5. Commit
* Use [well formed commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) * Use [well formed commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
6. Update your branch 6. Update your branch

View file

@ -11,7 +11,7 @@
Script.load("away.js"); Script.load("away.js");
Script.load("progress.js"); Script.load("progress.js");
Script.load("edit.js"); Script.load("edit.js");
Script.load("marketplace.js"); Script.load("examples.js");
Script.load("selectAudioDevice.js"); Script.load("selectAudioDevice.js");
Script.load("notifications.js"); Script.load("notifications.js");
Script.load("users.js"); Script.load("users.js");

View file

@ -1,5 +1,5 @@
// //
// marketplace.js // examples.js
// examples // examples
// //
// Created by Eric Levin on 8 Jan 2016 // Created by Eric Levin on 8 Jan 2016
@ -16,9 +16,9 @@ Script.include([
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; var EXAMPLES_URL = "https://metaverse.highfidelity.com/examples";
var marketplaceWindow = new OverlayWebWindow({ var examplesWindow = new OverlayWebWindow({
title: 'Marketplace', title: 'Examples',
source: "about:blank", source: "about:blank",
width: 900, width: 900,
height: 700, height: 700,
@ -29,43 +29,43 @@ var toolHeight = 50;
var toolWidth = 50; var toolWidth = 50;
function showMarketplace(marketplaceID) { function showExamples(marketplaceID) {
var url = MARKETPLACE_URL; var url = EXAMPLES_URL;
if (marketplaceID) { if (marketplaceID) {
url = url + "/items/" + marketplaceID; url = url + "/items/" + marketplaceID;
} }
print("setting marketplace URL to " + url); print("setting examples URL to " + url);
marketplaceWindow.setURL(url); examplesWindow.setURL(url);
marketplaceWindow.setVisible(true); examplesWindow.setVisible(true);
} }
function hideMarketplace() { function hideExamples() {
marketplaceWindow.setVisible(false); examplesWindow.setVisible(false);
marketplaceWindow.setURL("about:blank"); examplesWindow.setURL("about:blank");
} }
function toggleMarketplace() { function toggleExamples() {
if (marketplaceWindow.visible) { if (examplesWindow.visible) {
hideMarketplace(); hideExamples();
} else { } else {
showMarketplace(); showExamples();
} }
} }
var toolBar = (function() { var toolBar = (function() {
var that = {}, var that = {},
toolBar, toolBar,
browseMarketplaceButton; browseExamplesButton;
function initialize() { function initialize() {
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.marketplace.toolbar", function(windowDimensions, toolbar) { toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.examples.toolbar", function(windowDimensions, toolbar) {
return { return {
x: windowDimensions.x - 8 - toolbar.width, x: windowDimensions.x - 8 - toolbar.width,
y: 135 y: 135
}; };
}); });
browseMarketplaceButton = toolBar.addTool({ browseExamplesButton = toolBar.addTool({
imageURL: toolIconUrl + "market-01.svg", imageURL: toolIconUrl + "examples-01.svg",
subImage: { subImage: {
x: 0, x: 0,
y: Tool.IMAGE_WIDTH, y: Tool.IMAGE_WIDTH,
@ -79,10 +79,10 @@ var toolBar = (function() {
showButtonDown: true showButtonDown: true
}); });
toolBar.showTool(browseMarketplaceButton, true); toolBar.showTool(browseExamplesButton, true);
} }
var browseMarketplaceButtonDown = false; var browseExamplesButtonDown = false;
that.mousePressEvent = function(event) { that.mousePressEvent = function(event) {
var clickedOverlay, var clickedOverlay,
url, url,
@ -98,10 +98,8 @@ var toolBar = (function() {
y: event.y y: event.y
}); });
if (browseExamplesButton === toolBar.clicked(clickedOverlay)) {
toggleExamples();
if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) {
toggleMarketplace();
return true; return true;
} }
@ -112,7 +110,7 @@ var toolBar = (function() {
var handled = false; var handled = false;
if (browseMarketplaceButtonDown) { if (browseExamplesButtonDown) {
var clickedOverlay = Overlays.getOverlayAtPoint({ var clickedOverlay = Overlays.getOverlayAtPoint({
x: event.x, x: event.x,
y: event.y y: event.y
@ -120,7 +118,7 @@ var toolBar = (function() {
} }
newModelButtonDown = false; newModelButtonDown = false;
browseMarketplaceButtonDown = false; browseExamplesButtonDown = false;
return handled; return handled;
} }

View file

@ -62,8 +62,6 @@ bool IceServer::packetVersionMatch(const udt::Packet& packet) {
if (headerVersion == versionForPacketType(headerType)) { if (headerVersion == versionForPacketType(headerType)) {
return true; return true;
} else { } else {
qDebug() << "Packet version mismatch for packet" << headerType << " from" << packet.getSenderSockAddr();
return false; return false;
} }
} }

View file

@ -5,6 +5,8 @@ WebEngineView {
id: root id: root
property var newUrl; property var newUrl;
profile.httpUserAgent: "Mozilla/5.0 Chrome (HighFidelityInterface)"
Component.onCompleted: { Component.onCompleted: {
console.log("Connecting JS messaging to Hifi Logging") console.log("Connecting JS messaging to Hifi Logging")
// Ensure the JS from the web-engine makes it to our logging // Ensure the JS from the web-engine makes it to our logging

View file

@ -18,23 +18,12 @@
#include <glm/gtx/vector_angle.hpp> #include <glm/gtx/vector_angle.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <Qt>
#include <QtCore/QDebug>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QObject>
#include <QtCore/QUrl>
#include <QtCore/QTimer>
#include <QtCore/QAbstractNativeEventFilter> #include <QtCore/QAbstractNativeEventFilter>
#include <QtCore/QMimeData> #include <QtCore/QMimeData>
#include <QtCore/QThreadPool> #include <QtCore/QThreadPool>
#include <QtGui/QScreen> #include <QtGui/QScreen>
#include <QtGui/QImage>
#include <QtGui/QWheelEvent>
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include <QtGui/QKeyEvent>
#include <QtGui/QMouseEvent>
#include <QtGui/QDesktopServices> #include <QtGui/QDesktopServices>
#include <QtNetwork/QLocalSocket> #include <QtNetwork/QLocalSocket>
@ -44,28 +33,18 @@
#include <QtQml/QQmlEngine> #include <QtQml/QQmlEngine>
#include <QtQuick/QQuickWindow> #include <QtQuick/QQuickWindow>
#include <QtWidgets/QActionGroup>
#include <QtWidgets/QDesktopWidget> #include <QtWidgets/QDesktopWidget>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QMessageBox> #include <QtWidgets/QMessageBox>
#include <QtMultimedia/QMediaPlayer> #include <QtMultimedia/QMediaPlayer>
#include <QtNetwork/QNetworkDiskCache>
#include <gl/Config.h>
#include <gl/QOpenGLContextWrapper.h> #include <gl/QOpenGLContextWrapper.h>
#include <shared/JSONHelpers.h>
#include <ResourceScriptingInterface.h> #include <ResourceScriptingInterface.h>
#include <AccountManager.h> #include <AccountManager.h>
#include <AddressManager.h> #include <AddressManager.h>
#include <BuildInfo.h> #include <BuildInfo.h>
#include <AssetClient.h> #include <AssetClient.h>
#include <AssetUpload.h>
#include <AutoUpdater.h> #include <AutoUpdater.h>
#include <AudioInjectorManager.h> #include <AudioInjectorManager.h>
#include <CursorManager.h> #include <CursorManager.h>
@ -110,12 +89,9 @@
#include <ScriptCache.h> #include <ScriptCache.h>
#include <SoundCache.h> #include <SoundCache.h>
#include <ScriptEngines.h> #include <ScriptEngines.h>
#include <TextureCache.h>
#include <Tooltip.h> #include <Tooltip.h>
#include <udt/PacketHeaders.h> #include <udt/PacketHeaders.h>
#include <UserActivityLogger.h> #include <UserActivityLogger.h>
#include <UUID.h>
#include <VrMenu.h>
#include <recording/Deck.h> #include <recording/Deck.h>
#include <recording/Recorder.h> #include <recording/Recorder.h>
#include <QmlWebWindowClass.h> #include <QmlWebWindowClass.h>
@ -137,7 +113,6 @@
#include "InterfaceActionFactory.h" #include "InterfaceActionFactory.h"
#include "InterfaceLogging.h" #include "InterfaceLogging.h"
#include "LODManager.h" #include "LODManager.h"
#include "Menu.h"
#include "ModelPackager.h" #include "ModelPackager.h"
#include "PluginContainerProxy.h" #include "PluginContainerProxy.h"
#include "scripting/AccountScriptingInterface.h" #include "scripting/AccountScriptingInterface.h"
@ -171,7 +146,7 @@
// ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // ON Windows PC, Nvidia Optimus laptop, we want to enable NVIDIA GPU
// FIXME seems to be broken. // FIXME seems to be broken.
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
extern "C" { extern "C" {
@ -254,14 +229,14 @@ public:
}); });
} }
void updateHeartbeat() { static void updateHeartbeat() {
auto now = usecTimestampNow(); auto now = usecTimestampNow();
auto elapsed = now - _heartbeat; auto elapsed = now - _heartbeat;
_movingAverage.addSample(elapsed); _movingAverage.addSample(elapsed);
_heartbeat = now; _heartbeat = now;
} }
void deadlockDetectionCrash() { static void deadlockDetectionCrash() {
uint32_t* crashTrigger = nullptr; uint32_t* crashTrigger = nullptr;
*crashTrigger = 0xDEAD10CC; *crashTrigger = 0xDEAD10CC;
} }
@ -390,7 +365,7 @@ public:
LambdaEvent(std::function<void()> && fun) : LambdaEvent(std::function<void()> && fun) :
QEvent(static_cast<QEvent::Type>(Lambda)), _fun(fun) { QEvent(static_cast<QEvent::Type>(Lambda)), _fun(fun) {
} }
void call() { _fun(); } void call() const { _fun(); }
}; };
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
@ -528,7 +503,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
_maxOctreePPS(maxOctreePacketsPerSecond.get()), _maxOctreePPS(maxOctreePacketsPerSecond.get()),
_lastFaceTrackerUpdate(0) _lastFaceTrackerUpdate(0)
{ {
// FIXME this may be excessivly conservative. On the other hand // FIXME this may be excessively conservative. On the other hand
// maybe I'm used to having an 8-core machine // maybe I'm used to having an 8-core machine
// Perhaps find the ideal thread count and subtract 2 or 3 // Perhaps find the ideal thread count and subtract 2 or 3
// (main thread, present thread, random OS load) // (main thread, present thread, random OS load)
@ -1014,12 +989,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog); connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog);
applicationUpdater->checkForUpdate(); applicationUpdater->checkForUpdate();
// Now that menu is initalized we can sync myAvatar with it's state. // Now that menu is initialized we can sync myAvatar with it's state.
getMyAvatar()->updateMotionBehaviorFromMenu(); getMyAvatar()->updateMotionBehaviorFromMenu();
// FIXME spacemouse code still needs cleanup // FIXME spacemouse code still needs cleanup
#if 0 #if 0
// the 3Dconnexion device wants to be initiliazed after a window is displayed. // the 3Dconnexion device wants to be initialized after a window is displayed.
SpacemouseManager::getInstance().init(); SpacemouseManager::getInstance().init();
#endif #endif
@ -1124,7 +1099,7 @@ void Application::showCursor(const QCursor& cursor) {
_cursorNeedsChanging = true; _cursorNeedsChanging = true;
} }
void Application::updateHeartbeat() { void Application::updateHeartbeat() const {
static_cast<DeadlockWatchdogThread*>(_deadlockWatchdogThread)->updateHeartbeat(); static_cast<DeadlockWatchdogThread*>(_deadlockWatchdogThread)->updateHeartbeat();
} }
@ -1218,12 +1193,12 @@ void Application::cleanupBeforeQuit() {
Application::~Application() { Application::~Application() {
EntityTreePointer tree = getEntities()->getTree(); EntityTreePointer tree = getEntities()->getTree();
tree->setSimulation(NULL); tree->setSimulation(nullptr);
_octreeProcessor.terminate(); _octreeProcessor.terminate();
_entityEditSender.terminate(); _entityEditSender.terminate();
_physicsEngine->setCharacterController(NULL); _physicsEngine->setCharacterController(nullptr);
ModelEntityItem::cleanupLoadedAnimations(); ModelEntityItem::cleanupLoadedAnimations();
@ -1264,7 +1239,7 @@ Application::~Application() {
_window->deleteLater(); _window->deleteLater();
qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages qInstallMessageHandler(nullptr); // NOTE: Do this as late as possible so we continue to get our log messages
} }
void Application::initializeGL() { void Application::initializeGL() {
@ -1744,7 +1719,7 @@ void Application::runTests() {
runUnitTests(); runUnitTests();
} }
void Application::audioMuteToggled() { void Application::audioMuteToggled() const {
QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteAudio); QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteAudio);
Q_CHECK_PTR(muteAction); Q_CHECK_PTR(muteAction);
muteAction->setChecked(DependencyManager::get<AudioClient>()->isMuted()); muteAction->setChecked(DependencyManager::get<AudioClient>()->isMuted());
@ -1826,7 +1801,7 @@ bool Application::event(QEvent* event) {
} }
if ((int)event->type() == (int)Lambda) { if ((int)event->type() == (int)Lambda) {
((LambdaEvent*)event)->call(); static_cast<LambdaEvent*>(event)->call();
return true; return true;
} }
@ -1860,25 +1835,25 @@ bool Application::event(QEvent* event) {
switch (event->type()) { switch (event->type()) {
case QEvent::MouseMove: case QEvent::MouseMove:
mouseMoveEvent((QMouseEvent*)event); mouseMoveEvent(static_cast<QMouseEvent*>(event));
return true; return true;
case QEvent::MouseButtonPress: case QEvent::MouseButtonPress:
mousePressEvent((QMouseEvent*)event); mousePressEvent(static_cast<QMouseEvent*>(event));
return true; return true;
case QEvent::MouseButtonDblClick: case QEvent::MouseButtonDblClick:
mouseDoublePressEvent((QMouseEvent*)event); mouseDoublePressEvent(static_cast<QMouseEvent*>(event));
return true; return true;
case QEvent::MouseButtonRelease: case QEvent::MouseButtonRelease:
mouseReleaseEvent((QMouseEvent*)event); mouseReleaseEvent(static_cast<QMouseEvent*>(event));
return true; return true;
case QEvent::KeyPress: case QEvent::KeyPress:
keyPressEvent((QKeyEvent*)event); keyPressEvent(static_cast<QKeyEvent*>(event));
return true; return true;
case QEvent::KeyRelease: case QEvent::KeyRelease:
keyReleaseEvent((QKeyEvent*)event); keyReleaseEvent(static_cast<QKeyEvent*>(event));
return true; return true;
case QEvent::FocusOut: case QEvent::FocusOut:
focusOutEvent((QFocusEvent*)event); focusOutEvent(static_cast<QFocusEvent*>(event));
return true; return true;
case QEvent::TouchBegin: case QEvent::TouchBegin:
touchBeginEvent(static_cast<QTouchEvent*>(event)); touchBeginEvent(static_cast<QTouchEvent*>(event));
@ -2306,13 +2281,13 @@ void Application::focusOutEvent(QFocusEvent* event) {
// synthesize events for keys currently pressed, since we may not get their release events // synthesize events for keys currently pressed, since we may not get their release events
foreach (int key, _keysPressed) { foreach (int key, _keysPressed) {
QKeyEvent event(QEvent::KeyRelease, key, Qt::NoModifier); QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
keyReleaseEvent(&event); keyReleaseEvent(&keyEvent);
} }
_keysPressed.clear(); _keysPressed.clear();
} }
void Application::maybeToggleMenuVisible(QMouseEvent* event) { void Application::maybeToggleMenuVisible(QMouseEvent* event) const {
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
// If in full screen, and our main windows menu bar is hidden, and we're close to the top of the QMainWindow // If in full screen, and our main windows menu bar is hidden, and we're close to the top of the QMainWindow
// then show the menubar. // then show the menubar.
@ -2428,7 +2403,7 @@ void Application::mousePressEvent(QMouseEvent* event) {
} }
} }
void Application::mouseDoublePressEvent(QMouseEvent* event) { void Application::mouseDoublePressEvent(QMouseEvent* event) const {
// if one of our scripts have asked to capture this event, then stop processing it // if one of our scripts have asked to capture this event, then stop processing it
if (_controllerScriptingInterface->isMouseCaptured()) { if (_controllerScriptingInterface->isMouseCaptured()) {
return; return;
@ -2528,7 +2503,7 @@ void Application::touchEndEvent(QTouchEvent* event) {
// put any application specific touch behavior below here.. // put any application specific touch behavior below here..
} }
void Application::wheelEvent(QWheelEvent* event) { void Application::wheelEvent(QWheelEvent* event) const {
_altPressed = false; _altPressed = false;
_controllerScriptingInterface->emitWheelEvent(event); // send events to any registered scripts _controllerScriptingInterface->emitWheelEvent(event); // send events to any registered scripts
@ -2707,9 +2682,11 @@ float Application::getAverageSimsPerSecond() {
} }
return _simsPerSecondReport; return _simsPerSecondReport;
} }
void Application::setAvatarSimrateSample(float sample) { void Application::setAvatarSimrateSample(float sample) {
_avatarSimsPerSecond.updateAverage(sample); _avatarSimsPerSecond.updateAverage(sample);
} }
float Application::getAvatarSimrate() { float Application::getAvatarSimrate() {
uint64_t now = usecTimestampNow(); uint64_t now = usecTimestampNow();
@ -2724,7 +2701,7 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) {
controller::InputDevice::setLowVelocityFilter(lowVelocityFilter); controller::InputDevice::setLowVelocityFilter(lowVelocityFilter);
} }
ivec2 Application::getMouse() { ivec2 Application::getMouse() const {
auto reticlePosition = getApplicationCompositor().getReticlePosition(); auto reticlePosition = getApplicationCompositor().getReticlePosition();
// in the HMD, the reticlePosition is the mouse position // in the HMD, the reticlePosition is the mouse position
@ -2741,11 +2718,11 @@ FaceTracker* Application::getActiveFaceTracker() {
auto dde = DependencyManager::get<DdeFaceTracker>(); auto dde = DependencyManager::get<DdeFaceTracker>();
return (dde->isActive() ? static_cast<FaceTracker*>(dde.data()) : return (dde->isActive() ? static_cast<FaceTracker*>(dde.data()) :
(faceshift->isActive() ? static_cast<FaceTracker*>(faceshift.data()) : NULL)); (faceshift->isActive() ? static_cast<FaceTracker*>(faceshift.data()) : nullptr));
} }
FaceTracker* Application::getSelectedFaceTracker() { FaceTracker* Application::getSelectedFaceTracker() {
FaceTracker* faceTracker = NULL; FaceTracker* faceTracker = nullptr;
#ifdef HAVE_FACESHIFT #ifdef HAVE_FACESHIFT
if (Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)) { if (Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)) {
faceTracker = DependencyManager::get<Faceshift>().data(); faceTracker = DependencyManager::get<Faceshift>().data();
@ -2759,7 +2736,7 @@ FaceTracker* Application::getSelectedFaceTracker() {
return faceTracker; return faceTracker;
} }
void Application::setActiveFaceTracker() { void Application::setActiveFaceTracker() const {
#if defined(HAVE_FACESHIFT) || defined(HAVE_DDE) #if defined(HAVE_FACESHIFT) || defined(HAVE_DDE)
bool isMuted = Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking); bool isMuted = Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking);
#endif #endif
@ -2816,60 +2793,68 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
auto entityTree = getEntities()->getTree(); auto entityTree = getEntities()->getTree();
auto exportTree = std::make_shared<EntityTree>(); auto exportTree = std::make_shared<EntityTree>();
exportTree->createRootElement(); exportTree->createRootElement();
glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE); glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE);
for (auto entityID : entityIDs) { // Gather entities and properties. bool success = true;
auto entityItem = entityTree->findEntityByEntityItemID(entityID); entityTree->withReadLock([&] {
if (!entityItem) { for (auto entityID : entityIDs) { // Gather entities and properties.
qCWarning(interfaceapp) << "Skipping export of" << entityID << "that is not in scene."; auto entityItem = entityTree->findEntityByEntityItemID(entityID);
continue; if (!entityItem) {
} qCWarning(interfaceapp) << "Skipping export of" << entityID << "that is not in scene.";
continue;
if (!givenOffset) {
EntityItemID parentID = entityItem->getParentID();
if (parentID.isInvalidID() || !entityIDs.contains(parentID) || !entityTree->findEntityByEntityItemID(parentID)) {
auto position = entityItem->getPosition(); // If parent wasn't selected, we want absolute position, which isn't in properties.
root.x = glm::min(root.x, position.x);
root.y = glm::min(root.y, position.y);
root.z = glm::min(root.z, position.z);
} }
if (!givenOffset) {
EntityItemID parentID = entityItem->getParentID();
if (parentID.isInvalidID() || !entityIDs.contains(parentID) || !entityTree->findEntityByEntityItemID(parentID)) {
auto position = entityItem->getPosition(); // If parent wasn't selected, we want absolute position, which isn't in properties.
root.x = glm::min(root.x, position.x);
root.y = glm::min(root.y, position.y);
root.z = glm::min(root.z, position.z);
}
}
entities[entityID] = entityItem;
} }
entities[entityID] = entityItem;
}
if (entities.size() == 0) { if (entities.size() == 0) {
return false; success = false;
} return;
}
if (givenOffset) { if (givenOffset) {
root = *givenOffset; root = *givenOffset;
} }
for (EntityItemPointer& entityDatum : entities) { for (EntityItemPointer& entityDatum : entities) {
auto properties = entityDatum->getProperties(); auto properties = entityDatum->getProperties();
EntityItemID parentID = properties.getParentID(); EntityItemID parentID = properties.getParentID();
if (parentID.isInvalidID()) { if (parentID.isInvalidID()) {
properties.setPosition(properties.getPosition() - root); properties.setPosition(properties.getPosition() - root);
} else if (!entities.contains(parentID)) { }
entityDatum->globalizeProperties(properties, "Parent %3 of %2 %1 is not selected for export.", -root); else if (!entities.contains(parentID)) {
} // else valid parent -- don't offset entityDatum->globalizeProperties(properties, "Parent %3 of %2 %1 is not selected for export.", -root);
exportTree->addEntity(entityDatum->getEntityItemID(), properties); } // else valid parent -- don't offset
} exportTree->addEntity(entityDatum->getEntityItemID(), properties);
}
});
if (success) {
exportTree->writeToJSONFile(filename.toLocal8Bit().constData());
exportTree->writeToJSONFile(filename.toLocal8Bit().constData()); // restore the main window's active state
_window->activateWindow();
// restore the main window's active state }
_window->activateWindow(); return success;
return true;
} }
bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) { bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) {
glm::vec3 offset(x, y, z); glm::vec3 offset(x, y, z);
QVector<EntityItemPointer> entities; QVector<EntityItemPointer> entities;
QVector<EntityItemID> ids; QVector<EntityItemID> ids;
getEntities()->getTree()->findEntities(AACube(offset, scale), entities); auto entityTree = getEntities()->getTree();
foreach(EntityItemPointer entity, entities) { entityTree->withReadLock([&] {
ids << entity->getEntityItemID(); entityTree->findEntities(AACube(offset, scale), entities);
} foreach(EntityItemPointer entity, entities) {
ids << entity->getEntityItemID();
}
});
return exportEntities(filename, ids, &offset); return exportEntities(filename, ids, &offset);
} }
@ -2888,7 +2873,7 @@ void Application::loadSettings() {
_settingsLoaded = true; _settingsLoaded = true;
} }
void Application::saveSettings() { void Application::saveSettings() const {
sessionRunTime.set(_sessionRunTimer.elapsed() / MSECS_PER_SEC); sessionRunTime.set(_sessionRunTimer.elapsed() / MSECS_PER_SEC);
DependencyManager::get<AudioClient>()->saveSettings(); DependencyManager::get<AudioClient>()->saveSettings();
DependencyManager::get<LODManager>()->saveSettings(); DependencyManager::get<LODManager>()->saveSettings();
@ -2899,12 +2884,15 @@ void Application::saveSettings() {
} }
bool Application::importEntities(const QString& urlOrFilename) { bool Application::importEntities(const QString& urlOrFilename) {
_entityClipboard->eraseAllOctreeElements(); bool success = false;
_entityClipboard->withWriteLock([&] {
_entityClipboard->eraseAllOctreeElements();
bool success = _entityClipboard->readFromURL(urlOrFilename); success = _entityClipboard->readFromURL(urlOrFilename);
if (success) { if (success) {
_entityClipboard->reaverageOctreeElements(); _entityClipboard->reaverageOctreeElements();
} }
});
return success; return success;
} }
@ -2975,7 +2963,7 @@ void Application::init() {
connect(getMyAvatar(), &MyAvatar::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound); connect(getMyAvatar(), &MyAvatar::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
} }
void Application::updateLOD() { void Application::updateLOD() const {
PerformanceTimer perfTimer("LOD"); PerformanceTimer perfTimer("LOD");
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
if (!isThrottleRendering()) { if (!isThrottleRendering()) {
@ -3177,13 +3165,13 @@ void Application::reloadResourceCaches() {
getMyAvatar()->resetFullAvatarURL(); getMyAvatar()->resetFullAvatarURL();
} }
void Application::rotationModeChanged() { void Application::rotationModeChanged() const {
if (!Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) { if (!Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
getMyAvatar()->setHeadPitch(0); getMyAvatar()->setHeadPitch(0);
} }
} }
void Application::updateDialogs(float deltaTime) { void Application::updateDialogs(float deltaTime) const {
PerformanceTimer perfTimer("updateDialogs"); PerformanceTimer perfTimer("updateDialogs");
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateDialogs()"); PerformanceWarning warn(showWarnings, "Application::updateDialogs()");
@ -3219,7 +3207,7 @@ void Application::update(float deltaTime) {
if (!_physicsEnabled && _processOctreeStatsCounter > 0) { if (!_physicsEnabled && _processOctreeStatsCounter > 0) {
// process octree stats packets are sent in between full sends of a scene. // process octree stats packets are sent in between full sends of a scene.
// We keep physics disabled until we've recieved a full scene and everything near the avatar in that // We keep physics disabled until we've received a full scene and everything near the avatar in that
// scene is ready to compute its collision shape. // scene is ready to compute its collision shape.
if (nearbyEntitiesAreReadyForPhysics()) { if (nearbyEntitiesAreReadyForPhysics()) {
@ -3524,7 +3512,7 @@ int Application::sendNackPackets() {
QSet<OCTREE_PACKET_SEQUENCE> missingSequenceNumbers; QSet<OCTREE_PACKET_SEQUENCE> missingSequenceNumbers;
_octreeServerSceneStats.withReadLock([&] { _octreeServerSceneStats.withReadLock([&] {
// retreive octree scene stats of this node // retrieve octree scene stats of this node
if (_octreeServerSceneStats.find(nodeUUID) == _octreeServerSceneStats.end()) { if (_octreeServerSceneStats.find(nodeUUID) == _octreeServerSceneStats.end()) {
return; return;
} }
@ -3724,7 +3712,7 @@ bool Application::isHMDMode() const {
} }
float Application::getTargetFrameRate() { return getActiveDisplayPlugin()->getTargetFrameRate(); } float Application::getTargetFrameRate() { return getActiveDisplayPlugin()->getTargetFrameRate(); }
QRect Application::getDesirableApplicationGeometry() { QRect Application::getDesirableApplicationGeometry() const {
QRect applicationGeometry = getWindow()->geometry(); QRect applicationGeometry = getWindow()->geometry();
// If our parent window is on the HMD, then don't use its geometry, instead use // If our parent window is on the HMD, then don't use its geometry, instead use
@ -3737,7 +3725,7 @@ QRect Application::getDesirableApplicationGeometry() {
// if our app's screen is the hmd screen, we don't want to place the // if our app's screen is the hmd screen, we don't want to place the
// running scripts widget on it. So we need to pick a better screen. // running scripts widget on it. So we need to pick a better screen.
// we will use the screen for the HMDTools since it's a guarenteed // we will use the screen for the HMDTools since it's a guaranteed
// better screen. // better screen.
if (appScreen == hmdScreen) { if (appScreen == hmdScreen) {
QScreen* betterScreen = hmdTools->windowHandle()->screen(); QScreen* betterScreen = hmdTools->windowHandle()->screen();
@ -3766,7 +3754,7 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
viewFrustum.calculate(); viewFrustum.calculate();
} }
glm::vec3 Application::getSunDirection() { glm::vec3 Application::getSunDirection() const {
// Sun direction is in fact just the location of the sun relative to the origin // Sun direction is in fact just the location of the sun relative to the origin
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage(); auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
return skyStage->getSunLight()->getDirection(); return skyStage->getSunLight()->getDirection();
@ -3968,7 +3956,8 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE;
if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) { if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) {
renderDebugFlags = (RenderArgs::DebugFlags) (renderDebugFlags | (int)RenderArgs::RENDER_DEBUG_HULLS); renderDebugFlags = static_cast<RenderArgs::DebugFlags>(renderDebugFlags |
static_cast<int>(RenderArgs::RENDER_DEBUG_HULLS));
} }
renderArgs->_debugFlags = renderDebugFlags; renderArgs->_debugFlags = renderDebugFlags;
//ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges); //ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges);
@ -4033,7 +4022,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi
myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * myAvatar->getScale()); myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * myAvatar->getScale());
} else { // HEAD zoom level } else { // HEAD zoom level
// FIXME note that the positioing of the camera relative to the avatar can suffer limited // FIXME note that the positioning of the camera relative to the avatar can suffer limited
// precision as the user's position moves further away from the origin. Thus at // precision as the user's position moves further away from the origin. Thus at
// /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways
// wildly as you rotate your avatar because the floating point values are becoming // wildly as you rotate your avatar because the floating point values are becoming
@ -4079,7 +4068,7 @@ void Application::resetSensors(bool andReload) {
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "reset", Qt::QueuedConnection); QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "reset", Qt::QueuedConnection);
} }
void Application::updateWindowTitle(){ void Application::updateWindowTitle() const {
QString buildVersion = " (build " + applicationVersion() + ")"; QString buildVersion = " (build " + applicationVersion() + ")";
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
@ -4137,14 +4126,14 @@ void Application::resettingDomain() {
_notifiedPacketVersionMismatchThisDomain = false; _notifiedPacketVersionMismatchThisDomain = false;
} }
void Application::nodeAdded(SharedNodePointer node) { void Application::nodeAdded(SharedNodePointer node) const {
if (node->getType() == NodeType::AvatarMixer) { if (node->getType() == NodeType::AvatarMixer) {
// new avatar mixer, send off our identity packet right away // new avatar mixer, send off our identity packet right away
getMyAvatar()->sendIdentityPacket(); getMyAvatar()->sendIdentityPacket();
} }
} }
void Application::nodeActivated(SharedNodePointer node) { void Application::nodeActivated(SharedNodePointer node) const {
if (node->getType() == NodeType::AssetServer) { if (node->getType() == NodeType::AssetServer) {
// asset server just connected - check if we have the asset browser showing // asset server just connected - check if we have the asset browser showing
@ -4278,7 +4267,7 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer
statsMessageLength = octreeStats.unpackFromPacket(message); statsMessageLength = octreeStats.unpackFromPacket(message);
// see if this is the first we've heard of this node... // see if this is the first we've heard of this node...
NodeToJurisdictionMap* jurisdiction = NULL; NodeToJurisdictionMap* jurisdiction = nullptr;
QString serverType; QString serverType;
if (sendingNode->getType() == NodeType::EntityServer) { if (sendingNode->getType() == NodeType::EntityServer) {
jurisdiction = &_entityServerJurisdictions; jurisdiction = &_entityServerJurisdictions;
@ -4434,7 +4423,7 @@ bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
return defaultUpload; return defaultUpload;
} }
void Application::setSessionUUID(const QUuid& sessionUUID) { void Application::setSessionUUID(const QUuid& sessionUUID) const {
// HACK: until we swap the library dependency order between physics and entities // HACK: until we swap the library dependency order between physics and entities
// we cache the sessionID in two distinct places for physics. // we cache the sessionID in two distinct places for physics.
Physics::setSessionUUID(sessionUUID); // TODO: remove this one Physics::setSessionUUID(sessionUUID); // TODO: remove this one
@ -4575,7 +4564,7 @@ bool Application::displayAvatarAttachmentConfirmationDialog(const QString& name)
} }
} }
void Application::toggleRunningScriptsWidget() { void Application::toggleRunningScriptsWidget() const {
static const QUrl url("hifi/dialogs/RunningScripts.qml"); static const QUrl url("hifi/dialogs/RunningScripts.qml");
DependencyManager::get<OffscreenUi>()->show(url, "RunningScripts"); DependencyManager::get<OffscreenUi>()->show(url, "RunningScripts");
//if (_runningScriptsWidget->isVisible()) { //if (_runningScriptsWidget->isVisible()) {
@ -4612,7 +4601,7 @@ void Application::packageModel() {
ModelPackager::package(); ModelPackager::package();
} }
void Application::openUrl(const QUrl& url) { void Application::openUrl(const QUrl& url) const {
if (!url.isEmpty()) { if (!url.isEmpty()) {
if (url.scheme() == HIFI_URL_SCHEME) { if (url.scheme() == HIFI_URL_SCHEME) {
DependencyManager::get<AddressManager>()->handleLookupString(url.toString()); DependencyManager::get<AddressManager>()->handleLookupString(url.toString());
@ -4642,7 +4631,7 @@ void Application::setPreviousScriptLocation(const QString& location) {
_previousScriptLocation.set(location); _previousScriptLocation.set(location);
} }
void Application::loadScriptURLDialog() { void Application::loadScriptURLDialog() const {
auto newScript = OffscreenUi::getText(nullptr, "Open and Run Script", "Script URL"); auto newScript = OffscreenUi::getText(nullptr, "Open and Run Script", "Script URL");
if (!newScript.isEmpty()) { if (!newScript.isEmpty()) {
DependencyManager::get<ScriptEngines>()->loadScript(newScript); DependencyManager::get<ScriptEngines>()->loadScript(newScript);
@ -4707,7 +4696,7 @@ void Application::notifyPacketVersionMismatch() {
} }
} }
void Application::checkSkeleton() { void Application::checkSkeleton() const {
if (getMyAvatar()->getSkeletonModel()->isActive() && !getMyAvatar()->getSkeletonModel()->hasSkeleton()) { if (getMyAvatar()->getSkeletonModel()->isActive() && !getMyAvatar()->getSkeletonModel()->hasSkeleton()) {
qCDebug(interfaceapp) << "MyAvatar model has no skeleton"; qCDebug(interfaceapp) << "MyAvatar model has no skeleton";
@ -4788,7 +4777,7 @@ void Application::setMaxOctreePacketsPerSecond(int maxOctreePPS) {
} }
} }
int Application::getMaxOctreePacketsPerSecond() { int Application::getMaxOctreePacketsPerSecond() const {
return _maxOctreePPS; return _maxOctreePPS;
} }
@ -4812,7 +4801,7 @@ DisplayPlugin* Application::getActiveDisplayPlugin() {
} }
const DisplayPlugin* Application::getActiveDisplayPlugin() const { const DisplayPlugin* Application::getActiveDisplayPlugin() const {
return ((Application*)this)->getActiveDisplayPlugin(); return const_cast<Application*>(this)->getActiveDisplayPlugin();
} }
static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) {
@ -4892,7 +4881,7 @@ void Application::updateDisplayMode() {
} }
} }
// concactonate the groupings into a single list in the order: standard, advanced, developer // concatenate the groupings into a single list in the order: standard, advanced, developer
standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); standard.insert(std::end(standard), std::begin(advanced), std::end(advanced));
standard.insert(std::end(standard), std::begin(developer), std::end(developer)); standard.insert(std::end(standard), std::begin(developer), std::end(developer));
@ -4904,7 +4893,7 @@ void Application::updateDisplayMode() {
first = false; first = false;
} }
// after all plugins have been added to the menu, add a seperator to the menu // after all plugins have been added to the menu, add a separator to the menu
auto menu = Menu::getInstance(); auto menu = Menu::getInstance();
auto parent = menu->getMenu(MenuOption::OutputMenu); auto parent = menu->getMenu(MenuOption::OutputMenu);
parent->addSeparator(); parent->addSeparator();
@ -4975,7 +4964,7 @@ void Application::updateDisplayMode() {
emit activeDisplayPluginChanged(); emit activeDisplayPluginChanged();
// reset the avatar, to set head and hand palms back to a resonable default pose. // reset the avatar, to set head and hand palms back to a reasonable default pose.
getMyAvatar()->reset(false); getMyAvatar()->reset(false);
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
@ -5104,7 +5093,7 @@ void Application::setActiveDisplayPlugin(const QString& pluginName) {
updateDisplayMode(); updateDisplayMode();
} }
void Application::handleLocalServerConnection() { void Application::handleLocalServerConnection() const {
auto server = qobject_cast<QLocalServer*>(sender()); auto server = qobject_cast<QLocalServer*>(sender());
qDebug() << "Got connection on local server from additional instance - waiting for parameters"; qDebug() << "Got connection on local server from additional instance - waiting for parameters";
@ -5117,7 +5106,7 @@ void Application::handleLocalServerConnection() {
qApp->getWindow()->activateWindow(); qApp->getWindow()->activateWindow();
} }
void Application::readArgumentsFromLocalSocket() { void Application::readArgumentsFromLocalSocket() const {
auto socket = qobject_cast<QLocalSocket*>(sender()); auto socket = qobject_cast<QLocalSocket*>(sender());
auto message = socket->readAll(); auto message = socket->readAll();

View file

@ -135,14 +135,14 @@ public:
const ViewFrustum* getDisplayViewFrustum() const; const ViewFrustum* getDisplayViewFrustum() const;
ViewFrustum* getShadowViewFrustum() override { return &_shadowViewFrustum; } ViewFrustum* getShadowViewFrustum() override { return &_shadowViewFrustum; }
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
EntityTreeRenderer* getEntities() { return DependencyManager::get<EntityTreeRenderer>().data(); } EntityTreeRenderer* getEntities() const { return DependencyManager::get<EntityTreeRenderer>().data(); }
QUndoStack* getUndoStack() { return &_undoStack; } QUndoStack* getUndoStack() { return &_undoStack; }
MainWindow* getWindow() { return _window; } MainWindow* getWindow() const { return _window; }
EntityTreePointer getEntityClipboard() { return _entityClipboard; } EntityTreePointer getEntityClipboard() const { return _entityClipboard; }
EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; } EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; }
EntityEditPacketSender* getEntityEditPacketSender() { return &_entityEditSender; } EntityEditPacketSender* getEntityEditPacketSender() { return &_entityEditSender; }
ivec2 getMouse(); ivec2 getMouse() const;
FaceTracker* getActiveFaceTracker(); FaceTracker* getActiveFaceTracker();
FaceTracker* getSelectedFaceTracker(); FaceTracker* getSelectedFaceTracker();
@ -155,7 +155,7 @@ public:
bool isForeground() const { return _isForeground; } bool isForeground() const { return _isForeground; }
uint32_t getFrameCount() { return _frameCount; } uint32_t getFrameCount() const { return _frameCount; }
float getFps() const { return _fps; } float getFps() const { return _fps; }
float getTargetFrameRate(); // frames/second float getTargetFrameRate(); // frames/second
float getLastInstanteousFps() const { return _lastInstantaneousFps; } float getLastInstanteousFps() const { return _lastInstantaneousFps; }
@ -179,7 +179,7 @@ public:
DisplayPlugin* getActiveDisplayPlugin(); DisplayPlugin* getActiveDisplayPlugin();
const DisplayPlugin* getActiveDisplayPlugin() const; const DisplayPlugin* getActiveDisplayPlugin() const;
FileLogger* getLogger() { return _logger; } FileLogger* getLogger() const { return _logger; }
glm::vec2 getViewportDimensions() const; glm::vec2 getViewportDimensions() const;
@ -189,7 +189,7 @@ public:
bool isAboutToQuit() const { return _aboutToQuit; } bool isAboutToQuit() const { return _aboutToQuit; }
// the isHMDmode is true whenever we use the interface from an HMD and not a standard flat display // the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display
// rendering of several elements depend on that // rendering of several elements depend on that
// TODO: carry that information on the Camera as a setting // TODO: carry that information on the Camera as a setting
bool isHMDMode() const; bool isHMDMode() const;
@ -197,14 +197,14 @@ public:
glm::mat4 getEyeOffset(int eye) const; glm::mat4 getEyeOffset(int eye) const;
glm::mat4 getEyeProjection(int eye) const; glm::mat4 getEyeProjection(int eye) const;
QRect getDesirableApplicationGeometry(); QRect getDesirableApplicationGeometry() const;
Bookmarks* getBookmarks() const { return _bookmarks; } Bookmarks* getBookmarks() const { return _bookmarks; }
virtual bool canAcceptURL(const QString& url) const override; virtual bool canAcceptURL(const QString& url) const override;
virtual bool acceptURL(const QString& url, bool defaultUpload = false) override; virtual bool acceptURL(const QString& url, bool defaultUpload = false) override;
void setMaxOctreePacketsPerSecond(int maxOctreePPS); void setMaxOctreePacketsPerSecond(int maxOctreePPS);
int getMaxOctreePacketsPerSecond(); int getMaxOctreePacketsPerSecond() const;
render::ScenePointer getMain3DScene() override { return _main3DScene; } render::ScenePointer getMain3DScene() override { return _main3DScene; }
render::ScenePointer getMain3DScene() const { return _main3DScene; } render::ScenePointer getMain3DScene() const { return _main3DScene; }
@ -239,22 +239,22 @@ public slots:
bool exportEntities(const QString& filename, float x, float y, float z, float scale); bool exportEntities(const QString& filename, float x, float y, float z, float scale);
bool importEntities(const QString& url); bool importEntities(const QString& url);
void setLowVelocityFilter(bool lowVelocityFilter); static void setLowVelocityFilter(bool lowVelocityFilter);
Q_INVOKABLE void loadDialog(); Q_INVOKABLE void loadDialog();
Q_INVOKABLE void loadScriptURLDialog(); Q_INVOKABLE void loadScriptURLDialog() const;
void toggleLogDialog(); void toggleLogDialog();
void toggleRunningScriptsWidget(); void toggleRunningScriptsWidget() const;
void toggleAssetServerWidget(QString filePath = ""); void toggleAssetServerWidget(QString filePath = "");
void handleLocalServerConnection(); void handleLocalServerConnection() const;
void readArgumentsFromLocalSocket(); void readArgumentsFromLocalSocket() const;
void packageModel(); static void packageModel();
void openUrl(const QUrl& url); void openUrl(const QUrl& url) const;
void resetSensors(bool andReload = false); void resetSensors(bool andReload = false);
void setActiveFaceTracker(); void setActiveFaceTracker() const;
#ifdef HAVE_IVIEWHMD #ifdef HAVE_IVIEWHMD
void setActiveEyeTracker(); void setActiveEyeTracker();
@ -264,7 +264,7 @@ public slots:
#endif #endif
void aboutApp(); void aboutApp();
void showHelp(); static void showHelp();
void cycleCamera(); void cycleCamera();
void cameraMenuChanged(); void cameraMenuChanged();
@ -273,14 +273,14 @@ public slots:
void reloadResourceCaches(); void reloadResourceCaches();
void updateHeartbeat(); void updateHeartbeat() const;
void crashApplication(); static void crashApplication();
void deadlockApplication(); static void deadlockApplication();
void rotationModeChanged(); void rotationModeChanged() const;
void runTests(); static void runTests();
private slots: private slots:
void showDesktop(); void showDesktop();
@ -290,7 +290,7 @@ private slots:
void resettingDomain(); void resettingDomain();
void audioMuteToggled(); void audioMuteToggled() const;
void faceTrackerMuteToggled(); void faceTrackerMuteToggled();
void activeChanged(Qt::ApplicationState state); void activeChanged(Qt::ApplicationState state);
@ -298,7 +298,7 @@ private slots:
void notifyPacketVersionMismatch(); void notifyPacketVersionMismatch();
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings() const;
bool acceptSnapshot(const QString& urlString); bool acceptSnapshot(const QString& urlString);
bool askToSetAvatarUrl(const QString& url); bool askToSetAvatarUrl(const QString& url);
@ -308,18 +308,18 @@ private slots:
void displayAvatarAttachmentWarning(const QString& message) const; void displayAvatarAttachmentWarning(const QString& message) const;
bool displayAvatarAttachmentConfirmationDialog(const QString& name) const; bool displayAvatarAttachmentConfirmationDialog(const QString& name) const;
void setSessionUUID(const QUuid& sessionUUID); void setSessionUUID(const QUuid& sessionUUID) const;
void domainChanged(const QString& domainHostname); void domainChanged(const QString& domainHostname);
void updateWindowTitle(); void updateWindowTitle() const;
void nodeAdded(SharedNodePointer node); void nodeAdded(SharedNodePointer node) const;
void nodeActivated(SharedNodePointer node); void nodeActivated(SharedNodePointer node) const;
void nodeKilled(SharedNodePointer node); void nodeKilled(SharedNodePointer node);
void packetSent(quint64 length); static void packetSent(quint64 length);
void updateDisplayMode(); void updateDisplayMode();
void updateInputModes(); void updateInputModes();
private: private:
void initDisplay(); static void initDisplay();
void init(); void init();
void cleanupBeforeQuit(); void cleanupBeforeQuit();
@ -327,14 +327,14 @@ private:
void update(float deltaTime); void update(float deltaTime);
// Various helper functions called during update() // Various helper functions called during update()
void updateLOD(); void updateLOD() const;
void updateThreads(float deltaTime); void updateThreads(float deltaTime);
void updateDialogs(float deltaTime); void updateDialogs(float deltaTime) const;
void queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions); void queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions);
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum); static void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
glm::vec3 getSunDirection(); glm::vec3 getSunDirection() const;
void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region); void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region);
@ -344,7 +344,7 @@ private:
MyAvatar* getMyAvatar() const; MyAvatar* getMyAvatar() const;
void checkSkeleton(); void checkSkeleton() const;
void initializeAcceptedFiles(); void initializeAcceptedFiles();
@ -366,18 +366,18 @@ private:
void mouseMoveEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event);
void mousePressEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event);
void mouseDoublePressEvent(QMouseEvent* event); void mouseDoublePressEvent(QMouseEvent* event) const;
void mouseReleaseEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
void touchBeginEvent(QTouchEvent* event); void touchBeginEvent(QTouchEvent* event);
void touchEndEvent(QTouchEvent* event); void touchEndEvent(QTouchEvent* event);
void touchUpdateEvent(QTouchEvent* event); void touchUpdateEvent(QTouchEvent* event);
void wheelEvent(QWheelEvent* event); void wheelEvent(QWheelEvent* event) const;
void dropEvent(QDropEvent* event); void dropEvent(QDropEvent* event);
void dragEnterEvent(QDragEnterEvent* event); static void dragEnterEvent(QDragEnterEvent* event);
void maybeToggleMenuVisible(QMouseEvent* event); void maybeToggleMenuVisible(QMouseEvent* event) const;
MainWindow* _window; MainWindow* _window;
QElapsedTimer& _sessionRunTimer; QElapsedTimer& _sessionRunTimer;
@ -423,7 +423,7 @@ private:
int _avatarSimsPerSecondReport {0}; int _avatarSimsPerSecondReport {0};
quint64 _lastAvatarSimsPerSecondUpdate {0}; quint64 _lastAvatarSimsPerSecondUpdate {0};
Camera _myCamera; // My view onto the world Camera _myCamera; // My view onto the world
Camera _mirrorCamera; // Cammera for mirror view Camera _mirrorCamera; // Camera for mirror view
QRect _mirrorViewRect; QRect _mirrorViewRect;
Setting::Handle<QString> _previousScriptLocation; Setting::Handle<QString> _previousScriptLocation;

View file

@ -297,7 +297,14 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
auto sceneLocation = sceneStage->getLocation(); auto sceneLocation = sceneStage->getLocation();
auto sceneTime = sceneStage->getTime(); auto sceneTime = sceneStage->getTime();
// Skybox and procedural skybox data
auto skybox = std::dynamic_pointer_cast<ProceduralSkybox>(skyStage->getSkybox());
static QString userData;
if (!zone) { if (!zone) {
userData = QString();
skybox->clear();
_pendingSkyboxTexture = false; _pendingSkyboxTexture = false;
_skyboxTexture.clear(); _skyboxTexture.clear();
@ -373,9 +380,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
switch (zone->getBackgroundMode()) { switch (zone->getBackgroundMode()) {
case BACKGROUND_MODE_SKYBOX: { case BACKGROUND_MODE_SKYBOX: {
auto skybox = std::dynamic_pointer_cast<ProceduralSkybox>(skyStage->getSkybox());
skybox->setColor(zone->getSkyboxProperties().getColorVec3()); skybox->setColor(zone->getSkyboxProperties().getColorVec3());
static QString userData;
if (userData != zone->getUserData()) { if (userData != zone->getUserData()) {
userData = zone->getUserData(); userData = zone->getUserData();
skybox->parse(userData); skybox->parse(userData);
@ -414,9 +419,15 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
case BACKGROUND_MODE_INHERIT: case BACKGROUND_MODE_INHERIT:
default: default:
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application background through // Clear the skybox to release its textures
_pendingSkyboxTexture = false; userData = QString();
skybox->clear();
_skyboxTexture.clear(); _skyboxTexture.clear();
_pendingSkyboxTexture = false;
// Let the application background through
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME);
break; break;
} }

View file

@ -1323,7 +1323,9 @@ QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSen
// We need to keep a map so that we can map parent identifiers correctly. // We need to keep a map so that we can map parent identifiers correctly.
QHash<EntityItemID, EntityItemID> map; QHash<EntityItemID, EntityItemID> map;
args.map = &map; args.map = &map;
recurseTreeWithOperation(sendEntitiesOperation, &args); withReadLock([&] {
recurseTreeWithOperation(sendEntitiesOperation, &args);
});
packetSender->releaseQueuedMessages(); packetSender->releaseQueuedMessages();
return map.values().toVector(); return map.values().toVector();

View file

@ -9,17 +9,20 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <iostream>
#include <QBuffer>
#include <QDataStream>
#include <QIODevice>
#include <QStringList>
#include <QTextStream>
#include <QtDebug>
#include <QtEndian>
#include <QFileInfo>
#include "FBXReader.h" #include "FBXReader.h"
#include <iostream>
#include <QtCore/QBuffer>
#include <QtCore/QDataStream>
#include <QtCore/QIODevice>
#include <QtCore/QStringList>
#include <QtCore/QTextStream>
#include <QtCore/QDebug>
#include <QtCore/QtEndian>
#include <QtCore/QFileInfo>
#include <shared/NsightHelpers.h>
template<class T> int streamSize() { template<class T> int streamSize() {
return sizeof(T); return sizeof(T);
} }
@ -299,6 +302,7 @@ FBXNode parseTextFBXNode(Tokenizer& tokenizer) {
} }
FBXNode FBXReader::parseFBX(QIODevice* device) { FBXNode FBXReader::parseFBX(QIODevice* device) {
PROFILE_RANGE_EX(__FUNCTION__, 0xff0000ff, device);
// verify the prolog // verify the prolog
const QByteArray BINARY_PROLOG = "Kaydara FBX Binary "; const QByteArray BINARY_PROLOG = "Kaydara FBX Binary ";
if (device->peek(BINARY_PROLOG.size()) != BINARY_PROLOG) { if (device->peek(BINARY_PROLOG.size()) != BINARY_PROLOG) {

View file

@ -12,17 +12,20 @@
// http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/obj-file-format/obj-file-format/ // http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/obj-file-format/obj-file-format/
// http://paulbourke.net/dataformats/obj/ // http://paulbourke.net/dataformats/obj/
#include "OBJReader.h"
#include <QBuffer>
#include <QIODevice>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QEventLoop>
#include <ctype.h> // .obj files are not locale-specific. The C/ASCII charset applies. #include <ctype.h> // .obj files are not locale-specific. The C/ASCII charset applies.
#include <QtCore/QBuffer>
#include <QtCore/QIODevice>
#include <QtCore/QEventLoop>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <shared/NsightHelpers.h>
#include <NetworkAccessManager.h> #include <NetworkAccessManager.h>
#include "FBXReader.h" #include "FBXReader.h"
#include "OBJReader.h"
#include "ModelFormatLogging.h" #include "ModelFormatLogging.h"
QHash<QString, float> COMMENT_SCALE_HINTS = {{"This file uses centimeters as units", 1.0f / 100.0f}, QHash<QString, float> COMMENT_SCALE_HINTS = {{"This file uses centimeters as units", 1.0f / 100.0f},
@ -404,7 +407,7 @@ done:
FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, const QUrl& url) { FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, const QUrl& url) {
PROFILE_RANGE_EX(__FUNCTION__, 0xffff0000, nullptr);
QBuffer buffer { &model }; QBuffer buffer { &model };
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);

View file

@ -10,6 +10,7 @@
// //
#include "GPULogging.h" #include "GPULogging.h"
#include "GLBackendShared.h" #include "GLBackendShared.h"
#include "GLTexelFormat.h"
using namespace gpu; using namespace gpu;
@ -36,369 +37,6 @@ void GLBackend::GLTexture::setSize(GLuint size) {
_size = size; _size = size;
} }
class GLTexelFormat {
public:
GLenum internalFormat;
GLenum format;
GLenum type;
static GLTexelFormat evalGLTexelFormat(const Element& dstFormat, const Element& srcFormat) {
if (dstFormat != srcFormat) {
GLTexelFormat texel = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
switch(dstFormat.getDimension()) {
case gpu::SCALAR: {
texel.format = GL_RED;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RED;
break;
case gpu::DEPTH:
texel.internalFormat = GL_DEPTH_COMPONENT;
break;
case gpu::DEPTH_STENCIL:
texel.type = GL_UNSIGNED_INT_24_8;
texel.format = GL_DEPTH_STENCIL;
texel.internalFormat = GL_DEPTH24_STENCIL8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC2: {
texel.format = GL_RG;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RG;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC3: {
texel.format = GL_RGB;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RGB;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC4: {
texel.format = GL_RGBA;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(srcFormat.getSemantic()) {
case gpu::BGRA:
case gpu::SBGRA:
texel.format = GL_BGRA;
break;
case gpu::RGB:
case gpu::RGBA:
case gpu::SRGB:
case gpu::SRGBA:
default:
break;
};
switch(dstFormat.getSemantic()) {
case gpu::RGB:
texel.internalFormat = GL_RGB;
break;
case gpu::RGBA:
texel.internalFormat = GL_RGBA;
break;
case gpu::SRGB:
texel.internalFormat = GL_SRGB;
break;
case gpu::SRGBA:
texel.internalFormat = GL_SRGB_ALPHA;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
return texel;
} else {
GLTexelFormat texel = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
switch(dstFormat.getDimension()) {
case gpu::SCALAR: {
texel.format = GL_RED;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
case gpu::SRGB:
case gpu::SRGBA:
texel.internalFormat = GL_RED;
switch (dstFormat.getType()) {
case gpu::UINT32: {
texel.internalFormat = GL_R32UI;
break;
}
case gpu::INT32: {
texel.internalFormat = GL_R32I;
break;
}
case gpu::NUINT32: {
texel.internalFormat = GL_RED;
break;
}
case gpu::NINT32: {
texel.internalFormat = GL_RED_SNORM;
break;
}
case gpu::FLOAT: {
texel.internalFormat = GL_R32F;
break;
}
case gpu::UINT16: {
texel.internalFormat = GL_R16UI;
break;
}
case gpu::INT16: {
texel.internalFormat = GL_R16I;
break;
}
case gpu::NUINT16: {
texel.internalFormat = GL_R16;
break;
}
case gpu::NINT16: {
texel.internalFormat = GL_R16_SNORM;
break;
}
case gpu::HALF: {
texel.internalFormat = GL_R16F;
break;
}
case gpu::UINT8: {
texel.internalFormat = GL_R8UI;
break;
}
case gpu::INT8: {
texel.internalFormat = GL_R8I;
break;
}
case gpu::NUINT8: {
if ((dstFormat.getSemantic() == gpu::SRGB || dstFormat.getSemantic() == gpu::SRGBA)) {
texel.internalFormat = GL_SLUMINANCE;
} else {
texel.internalFormat = GL_R8;
}
break;
}
case gpu::NINT8: {
texel.internalFormat = GL_R8_SNORM;
break;
}
case gpu::NUM_TYPES: { // quiet compiler
Q_UNREACHABLE();
}
}
break;
case gpu::R11G11B10:
texel.format = GL_RGB;
// the type should be float
texel.internalFormat = GL_R11F_G11F_B10F;
break;
case gpu::DEPTH:
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
texel.internalFormat = GL_DEPTH_COMPONENT;
switch (dstFormat.getType()) {
case gpu::UINT32:
case gpu::INT32:
case gpu::NUINT32:
case gpu::NINT32: {
texel.internalFormat = GL_DEPTH_COMPONENT32;
break;
}
case gpu::FLOAT: {
texel.internalFormat = GL_DEPTH_COMPONENT32F;
break;
}
case gpu::UINT16:
case gpu::INT16:
case gpu::NUINT16:
case gpu::NINT16:
case gpu::HALF: {
texel.internalFormat = GL_DEPTH_COMPONENT16;
break;
}
case gpu::UINT8:
case gpu::INT8:
case gpu::NUINT8:
case gpu::NINT8: {
texel.internalFormat = GL_DEPTH_COMPONENT24;
break;
}
case gpu::NUM_TYPES: { // quiet compiler
Q_UNREACHABLE();
}
}
break;
case gpu::DEPTH_STENCIL:
texel.type = GL_UNSIGNED_INT_24_8;
texel.format = GL_DEPTH_STENCIL;
texel.internalFormat = GL_DEPTH24_STENCIL8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC2: {
texel.format = GL_RG;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RG;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC3: {
texel.format = GL_RGB;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RGB;
break;
case gpu::SRGB:
case gpu::SRGBA:
texel.internalFormat = GL_SRGB; // standard 2.2 gamma correction color
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC4: {
texel.format = GL_RGBA;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
texel.internalFormat = GL_RGB;
break;
case gpu::RGBA:
texel.internalFormat = GL_RGBA;
switch (dstFormat.getType()) {
case gpu::UINT32:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA32UI;
break;
case gpu::INT32:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA32I;
break;
case gpu::FLOAT:
texel.internalFormat = GL_RGBA32F;
break;
case gpu::UINT16:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA16UI;
break;
case gpu::INT16:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA16I;
break;
case gpu::NUINT16:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA16;
break;
case gpu::NINT16:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA16_SNORM;
break;
case gpu::HALF:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA16F;
break;
case gpu::UINT8:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA8UI;
break;
case gpu::INT8:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA8I;
break;
case gpu::NUINT8:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA8;
break;
case gpu::NINT8:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA8_SNORM;
break;
case gpu::NUINT32:
case gpu::NINT32:
case gpu::NUM_TYPES: // quiet compiler
Q_UNREACHABLE();
}
break;
case gpu::SRGB:
texel.internalFormat = GL_SRGB;
break;
case gpu::SRGBA:
texel.internalFormat = GL_SRGB_ALPHA; // standard 2.2 gamma correction color
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
return texel;
}
}
};
GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
GLTexture* object = Backend::getGPUObject<GLBackend::GLTexture>(texture); GLTexture* object = Backend::getGPUObject<GLBackend::GLTexture>(texture);

View file

@ -0,0 +1,372 @@
//
// Created by Bradley Austin Davis on 2016/04/03
// Copyright 2013-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
//
#include "GLBackendShared.h"
class GLTexelFormat {
public:
GLenum internalFormat;
GLenum format;
GLenum type;
static GLTexelFormat evalGLTexelFormat(const gpu::Element& dstFormat, const gpu::Element& srcFormat) {
using namespace gpu;
if (dstFormat != srcFormat) {
GLTexelFormat texel = { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE };
switch (dstFormat.getDimension()) {
case gpu::SCALAR: {
texel.format = GL_RED;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch (dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_R8;
break;
case gpu::DEPTH:
texel.internalFormat = GL_DEPTH_COMPONENT32;
break;
case gpu::DEPTH_STENCIL:
texel.type = GL_UNSIGNED_INT_24_8;
texel.format = GL_DEPTH_STENCIL;
texel.internalFormat = GL_DEPTH24_STENCIL8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC2: {
texel.format = GL_RG;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch (dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RG8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC3: {
texel.format = GL_RGB;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch (dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RGB8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC4: {
texel.format = GL_RGBA;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch (srcFormat.getSemantic()) {
case gpu::BGRA:
case gpu::SBGRA:
texel.format = GL_BGRA;
break;
case gpu::RGB:
case gpu::RGBA:
case gpu::SRGB:
case gpu::SRGBA:
default:
break;
};
switch (dstFormat.getSemantic()) {
case gpu::RGB:
texel.internalFormat = GL_RGB8;
break;
case gpu::RGBA:
texel.internalFormat = GL_RGBA8;
break;
case gpu::SRGB:
texel.internalFormat = GL_SRGB8;
break;
case gpu::SRGBA:
texel.internalFormat = GL_SRGB8_ALPHA8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
return texel;
} else {
GLTexelFormat texel = { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE };
switch (dstFormat.getDimension()) {
case gpu::SCALAR: {
texel.format = GL_RED;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch (dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
case gpu::SRGB:
case gpu::SRGBA:
texel.internalFormat = GL_R8;
switch (dstFormat.getType()) {
case gpu::UINT32: {
texel.internalFormat = GL_R32UI;
break;
}
case gpu::INT32: {
texel.internalFormat = GL_R32I;
break;
}
case gpu::NUINT32: {
texel.internalFormat = GL_R8;
break;
}
case gpu::NINT32: {
texel.internalFormat = GL_R8_SNORM;
break;
}
case gpu::FLOAT: {
texel.internalFormat = GL_R32F;
break;
}
case gpu::UINT16: {
texel.internalFormat = GL_R16UI;
break;
}
case gpu::INT16: {
texel.internalFormat = GL_R16I;
break;
}
case gpu::NUINT16: {
texel.internalFormat = GL_R16;
break;
}
case gpu::NINT16: {
texel.internalFormat = GL_R16_SNORM;
break;
}
case gpu::HALF: {
texel.internalFormat = GL_R16F;
break;
}
case gpu::UINT8: {
texel.internalFormat = GL_R8UI;
break;
}
case gpu::INT8: {
texel.internalFormat = GL_R8I;
break;
}
case gpu::NUINT8: {
if ((dstFormat.getSemantic() == gpu::SRGB || dstFormat.getSemantic() == gpu::SRGBA)) {
texel.internalFormat = GL_SLUMINANCE8;
} else {
texel.internalFormat = GL_R8;
}
break;
}
case gpu::NINT8: {
texel.internalFormat = GL_R8_SNORM;
break;
}
case gpu::NUM_TYPES: { // quiet compiler
Q_UNREACHABLE();
}
}
break;
case gpu::R11G11B10:
texel.format = GL_RGB;
// the type should be float
texel.internalFormat = GL_R11F_G11F_B10F;
break;
case gpu::DEPTH:
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
texel.internalFormat = GL_DEPTH_COMPONENT32;
switch (dstFormat.getType()) {
case gpu::UINT32:
case gpu::INT32:
case gpu::NUINT32:
case gpu::NINT32: {
texel.internalFormat = GL_DEPTH_COMPONENT32;
break;
}
case gpu::FLOAT: {
texel.internalFormat = GL_DEPTH_COMPONENT32F;
break;
}
case gpu::UINT16:
case gpu::INT16:
case gpu::NUINT16:
case gpu::NINT16:
case gpu::HALF: {
texel.internalFormat = GL_DEPTH_COMPONENT16;
break;
}
case gpu::UINT8:
case gpu::INT8:
case gpu::NUINT8:
case gpu::NINT8: {
texel.internalFormat = GL_DEPTH_COMPONENT24;
break;
}
case gpu::NUM_TYPES: { // quiet compiler
Q_UNREACHABLE();
}
}
break;
case gpu::DEPTH_STENCIL:
texel.type = GL_UNSIGNED_INT_24_8;
texel.format = GL_DEPTH_STENCIL;
texel.internalFormat = GL_DEPTH24_STENCIL8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC2: {
texel.format = GL_RG;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch (dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RG8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC3: {
texel.format = GL_RGB;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch (dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RGB8;
break;
case gpu::SRGB:
case gpu::SRGBA:
texel.internalFormat = GL_SRGB8; // standard 2.2 gamma correction color
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
case gpu::VEC4: {
texel.format = GL_RGBA;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch (dstFormat.getSemantic()) {
case gpu::RGB:
texel.internalFormat = GL_RGB8;
break;
case gpu::RGBA:
texel.internalFormat = GL_RGBA8;
switch (dstFormat.getType()) {
case gpu::UINT32:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA32UI;
break;
case gpu::INT32:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA32I;
break;
case gpu::FLOAT:
texel.internalFormat = GL_RGBA32F;
break;
case gpu::UINT16:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA16UI;
break;
case gpu::INT16:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA16I;
break;
case gpu::NUINT16:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA16;
break;
case gpu::NINT16:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA16_SNORM;
break;
case gpu::HALF:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA16F;
break;
case gpu::UINT8:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA8UI;
break;
case gpu::INT8:
texel.format = GL_RGBA_INTEGER;
texel.internalFormat = GL_RGBA8I;
break;
case gpu::NUINT8:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA8;
break;
case gpu::NINT8:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA8_SNORM;
break;
case gpu::NUINT32:
case gpu::NINT32:
case gpu::NUM_TYPES: // quiet compiler
Q_UNREACHABLE();
}
break;
case gpu::SRGB:
texel.internalFormat = GL_SRGB8;
break;
case gpu::SRGBA:
texel.internalFormat = GL_SRGB8_ALPHA8; // standard 2.2 gamma correction color
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
break;
}
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
return texel;
}
}
};

View file

@ -118,10 +118,8 @@ void GeometryReader::run() {
} }
QThread::currentThread()->setPriority(QThread::LowPriority); QThread::currentThread()->setPriority(QThread::LowPriority);
// Ensure the resource is still being requested if (!_resource.data()) {
auto resource = _resource.toStrongRef(); qCWarning(modelnetworking) << "Abandoning load of" << _url << "; resource was deleted";
if (!resource) {
qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref";
return; return;
} }
@ -146,14 +144,28 @@ void GeometryReader::run() {
throw QString("unsupported format"); throw QString("unsupported format");
} }
QMetaObject::invokeMethod(resource.data(), "setGeometryDefinition", // Ensure the resource has not been deleted, and won't be while invokeMethod is in flight.
Q_ARG(void*, fbxGeometry)); 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));
}
} else { } else {
throw QString("url is invalid"); throw QString("url is invalid");
} }
} catch (const QString& error) { } catch (const QString& error) {
qCDebug(modelnetworking) << "Error reading " << _url << ": " << error; qCDebug(modelnetworking) << "Error reading " << _url << ": " << error;
QMetaObject::invokeMethod(resource.data(), "finishedLoading", Q_ARG(bool, false));
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));
}
} }
QThread::currentThread()->setPriority(originalPriority); QThread::currentThread()->setPriority(originalPriority);
@ -232,7 +244,7 @@ std::shared_ptr<NetworkGeometry> ModelCache::getGeometry(const QUrl& url, const
GeometryExtra geometryExtra = { mapping, textureBaseUrl }; GeometryExtra geometryExtra = { mapping, textureBaseUrl };
GeometryResource::Pointer resource = getResource(url, QUrl(), true, &geometryExtra).staticCast<GeometryResource>(); GeometryResource::Pointer resource = getResource(url, QUrl(), true, &geometryExtra).staticCast<GeometryResource>();
if (resource) { if (resource) {
if (resource->isLoaded() && !resource->hasTextures()) { if (resource->isLoaded() && resource->shouldSetTextures()) {
resource->setTextures(); resource->setTextures();
} }
return std::make_shared<NetworkGeometry>(resource); return std::make_shared<NetworkGeometry>(resource);

View file

@ -107,7 +107,8 @@ protected:
friend class GeometryMappingResource; friend class GeometryMappingResource;
// Geometries may not hold onto textures while cached - that is for the texture cache // Geometries may not hold onto textures while cached - that is for the texture cache
bool hasTextures() const { return !_materials.empty(); } // Instead, these methods clear and reset textures from the geometry when caching/loading
bool shouldSetTextures() const { return _geometry && _materials.empty(); }
void setTextures(); void setTextures();
void resetTextures(); void resetTextures();

View file

@ -11,19 +11,21 @@
#include "TextureCache.h" #include "TextureCache.h"
#include <mutex>
#include <QNetworkReply> #include <QNetworkReply>
#include <QPainter> #include <QPainter>
#include <QRunnable> #include <QRunnable>
#include <QThreadPool> #include <QThreadPool>
#include <QImageReader> #include <QImageReader>
#include <mutex>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/random.hpp> #include <glm/gtc/random.hpp>
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include <shared/NsightHelpers.h>
#include <Finally.h> #include <Finally.h>
#include <PathUtils.h> #include <PathUtils.h>
@ -280,6 +282,7 @@ void ImageReader::listSupportedImageFormats() {
} }
void ImageReader::run() { void ImageReader::run() {
PROFILE_RANGE_EX(__FUNCTION__, 0xffff0000, nullptr);
auto originalPriority = QThread::currentThread()->priority(); auto originalPriority = QThread::currentThread()->priority();
if (originalPriority == QThread::InheritPriority) { if (originalPriority == QThread::InheritPriority) {
originalPriority = QThread::NormalPriority; originalPriority = QThread::NormalPriority;
@ -326,6 +329,8 @@ void ImageReader::run() {
} }
auto url = _url.toString().toStdString(); auto url = _url.toString().toStdString();
PROFILE_RANGE_EX(__FUNCTION__"::textureLoader", 0xffffff00, nullptr);
texture = resource.dynamicCast<NetworkTexture>()->getTextureLoader()(image, url); texture = resource.dynamicCast<NetworkTexture>()->getTextureLoader()(image, url);
} }

View file

@ -35,6 +35,8 @@ public:
void setCubemap(const gpu::TexturePointer& cubemap); void setCubemap(const gpu::TexturePointer& cubemap);
const gpu::TexturePointer& getCubemap() const { return _cubemap; } const gpu::TexturePointer& getCubemap() const { return _cubemap; }
virtual void clear() { setCubemap(nullptr); }
void prepare(gpu::Batch& batch, int textureSlot = SKYBOX_SKYMAP_SLOT, int bufferSlot = SKYBOX_CONSTANTS_SLOT) const; void prepare(gpu::Batch& batch, int textureSlot = SKYBOX_SKYMAP_SLOT, int bufferSlot = SKYBOX_CONSTANTS_SLOT) const;
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const;

View file

@ -96,6 +96,7 @@ bool Procedural::parseVersion(const QJsonValue& version) {
bool Procedural::parseUrl(const QUrl& shaderUrl) { bool Procedural::parseUrl(const QUrl& shaderUrl) {
if (!shaderUrl.isValid()) { if (!shaderUrl.isValid()) {
qWarning() << "Invalid shader URL: " << shaderUrl; qWarning() << "Invalid shader URL: " << shaderUrl;
_networkShader.reset();
return false; return false;
} }
@ -110,6 +111,7 @@ bool Procedural::parseUrl(const QUrl& shaderUrl) {
_shaderPath = _shaderUrl.toLocalFile(); _shaderPath = _shaderUrl.toLocalFile();
qDebug() << "Shader path: " << _shaderPath; qDebug() << "Shader path: " << _shaderPath;
if (!QFile(_shaderPath).exists()) { if (!QFile(_shaderPath).exists()) {
_networkShader.reset();
return false;; return false;;
} }
} else { } else {
@ -135,9 +137,14 @@ bool Procedural::parseTextures(const QJsonArray& channels) {
auto textureCache = DependencyManager::get<TextureCache>(); auto textureCache = DependencyManager::get<TextureCache>();
size_t channelCount = std::min(MAX_PROCEDURAL_TEXTURE_CHANNELS, (size_t)_parsedChannels.size()); size_t channelCount = std::min(MAX_PROCEDURAL_TEXTURE_CHANNELS, (size_t)_parsedChannels.size());
for (size_t i = 0; i < channelCount; ++i) { size_t channel = 0;
QString url = _parsedChannels.at((int)i).toString(); for (; channel < channelCount; ++channel) {
_channels[i] = textureCache->getTexture(QUrl(url)); QString url = _parsedChannels.at((int)channel).toString();
_channels[channel] = textureCache->getTexture(QUrl(url));
}
for (; channel < MAX_PROCEDURAL_TEXTURE_CHANNELS; ++channel) {
// Release those textures no longer in use
_channels[channel] = textureCache->getTexture(QUrl());
} }
_channelsDirty = true; _channelsDirty = true;
@ -149,20 +156,21 @@ bool Procedural::parseTextures(const QJsonArray& channels) {
void Procedural::parse(const QJsonObject& proceduralData) { void Procedural::parse(const QJsonObject& proceduralData) {
_enabled = false; _enabled = false;
if (proceduralData.isEmpty()) {
return;
}
auto version = proceduralData[VERSION_KEY]; auto version = proceduralData[VERSION_KEY];
auto shaderUrl = proceduralData[URL_KEY].toString(); auto shaderUrl = proceduralData[URL_KEY].toString();
shaderUrl = ResourceManager::normalizeURL(shaderUrl); shaderUrl = ResourceManager::normalizeURL(shaderUrl);
auto uniforms = proceduralData[UNIFORMS_KEY].toObject(); auto uniforms = proceduralData[UNIFORMS_KEY].toObject();
auto channels = proceduralData[CHANNELS_KEY].toArray(); auto channels = proceduralData[CHANNELS_KEY].toArray();
if (parseVersion(version) && bool isValid = true;
parseUrl(shaderUrl) &&
parseUniforms(uniforms) && // Run through parsing regardless of validity to clear old cached resources
parseTextures(channels)) { isValid = parseVersion(version) && isValid;
isValid = parseUrl(shaderUrl) && isValid;
isValid = parseUniforms(uniforms) && isValid;
isValid = parseTextures(channels) && isValid;
if (!proceduralData.isEmpty() && isValid) {
_enabled = true; _enabled = true;
} }
} }

View file

@ -25,6 +25,14 @@ ProceduralSkybox::ProceduralSkybox() : model::Skybox() {
_procedural._state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); _procedural._state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
} }
void ProceduralSkybox::clear() {
// Parse and prepare a procedural with no shaders to release textures
parse(QString());
_procedural.ready();
Skybox::clear();
}
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const {
if (_procedural.ready()) { if (_procedural.ready()) {
ProceduralSkybox::render(batch, frustum, (*this)); ProceduralSkybox::render(batch, frustum, (*this));

View file

@ -24,6 +24,8 @@ public:
void parse(const QString& userData) { _procedural.parse(userData); } void parse(const QString& userData) { _procedural.parse(userData); }
virtual void clear() override;
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const;
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox);

View file

@ -159,11 +159,13 @@ void Model::updateRenderItems() {
Transform collisionMeshOffset; Transform collisionMeshOffset;
collisionMeshOffset.postTranslate(self->_offset); collisionMeshOffset.postTranslate(self->_offset);
uint32_t deleteGeometryCounter = self->_deleteGeometryCounter;
render::PendingChanges pendingChanges; render::PendingChanges pendingChanges;
foreach (auto itemID, self->_modelMeshRenderItems.keys()) { foreach (auto itemID, self->_modelMeshRenderItems.keys()) {
pendingChanges.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, modelMeshOffset](ModelMeshPartPayload& data) { pendingChanges.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, modelMeshOffset, deleteGeometryCounter](ModelMeshPartPayload& data) {
// Ensure the model geometry was not reset between frames // Ensure the model geometry was not reset between frames
if (data._model->isLoaded()) { if (data._model && data._model->isLoaded() && deleteGeometryCounter == data._model->_deleteGeometryCounter) {
// lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box. // lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box.
data._model->updateClusterMatrices(modelTransform.getTranslation(), modelTransform.getRotation()); data._model->updateClusterMatrices(modelTransform.getTranslation(), modelTransform.getRotation());
@ -1146,6 +1148,7 @@ void Model::setBlendedVertices(int blendNumber, const std::weak_ptr<NetworkGeome
} }
void Model::deleteGeometry() { void Model::deleteGeometry() {
_deleteGeometryCounter++;
_blendedVertexBuffers.clear(); _blendedVertexBuffers.clear();
_meshStates.clear(); _meshStates.clear();
_rig->destroyAnimGraph(); _rig->destroyAnimGraph();

View file

@ -394,6 +394,8 @@ protected:
friend class ModelMeshPartPayload; friend class ModelMeshPartPayload;
RigPointer _rig; RigPointer _rig;
uint32_t _deleteGeometryCounter { 0 };
}; };
Q_DECLARE_METATYPE(ModelPointer) Q_DECLARE_METATYPE(ModelPointer)

View file

@ -20,7 +20,7 @@ public:
}; };
#define PROFILE_RANGE(name) ProfileRange profileRangeThis(name); #define PROFILE_RANGE(name) ProfileRange profileRangeThis(name);
#define PROFILE_RANGE_EX(name, argbColor, payload) ProfileRange profileRangeThis(name, argbColor, payload); #define PROFILE_RANGE_EX(name, argbColor, payload) ProfileRange profileRangeThis(name, argbColor, (uint64_t)payload);
#else #else
#define PROFILE_RANGE(name) #define PROFILE_RANGE(name)
#define PROFILE_RANGE_EX(name, argbColor, payload) #define PROFILE_RANGE_EX(name, argbColor, payload)