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

This commit is contained in:
David Kelly 2017-04-07 14:30:22 -07:00
commit 948a821824
55 changed files with 637 additions and 343 deletions

View file

@ -2,6 +2,7 @@ import QtQuick 2.5
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtWebChannel 1.0 import QtWebChannel 1.0
import QtWebEngine 1.2 import QtWebEngine 1.2
import FileTypeProfile 1.0
import "controls-uit" import "controls-uit"
import "styles" as HifiStyles import "styles" as HifiStyles
@ -216,6 +217,11 @@ ScrollingWindow {
WebChannel.id: "eventBridgeWrapper" WebChannel.id: "eventBridgeWrapper"
property var eventBridge; property var eventBridge;
} }
profile: FileTypeProfile {
id: webviewProfile
storageName: "qmlWebEngine"
}
webChannel.registeredObjects: [eventBridgeWrapper] webChannel.registeredObjects: [eventBridgeWrapper]

View file

@ -0,0 +1,22 @@
//
// WebEntityView.qml
//
// Created by Kunal Gosar on 16 March 2017
// Copyright 2017 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 "."
import FileTypeProfile 1.0
WebView {
viewProfile: FileTypeProfile {
id: webviewProfile
storageName: "qmlWebEngine"
}
urlTag: "noDownload=true";
}

View file

@ -10,6 +10,7 @@ Item {
property alias eventBridge: eventBridgeWrapper.eventBridge property alias eventBridge: eventBridgeWrapper.eventBridge
property alias canGoBack: root.canGoBack; property alias canGoBack: root.canGoBack;
property var goBack: root.goBack; property var goBack: root.goBack;
property alias urlTag: root.urlTag
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
property bool keyboardRaised: false property bool keyboardRaised: false
property bool punctuationMode: false property bool punctuationMode: false
@ -27,6 +28,8 @@ Item {
WebChannel.id: "eventBridgeWrapper" WebChannel.id: "eventBridgeWrapper"
property var eventBridge; property var eventBridge;
} }
property alias viewProfile: root.profile
WebEngineView { WebEngineView {
id: root id: root
@ -66,6 +69,8 @@ Item {
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
worldId: WebEngineScript.MainWorld worldId: WebEngineScript.MainWorld
} }
property string urlTag: "noDownload=false";
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
@ -94,6 +99,7 @@ Item {
// Required to support clicking on "hifi://" links // Required to support clicking on "hifi://" links
if (WebEngineView.LoadStartedStatus == loadRequest.status) { if (WebEngineView.LoadStartedStatus == loadRequest.status) {
var url = loadRequest.url.toString(); var url = loadRequest.url.toString();
url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag;
if (urlHandler.canHandleUrl(url)) { if (urlHandler.canHandleUrl(url)) {
if (urlHandler.handleUrl(url)) { if (urlHandler.handleUrl(url)) {
root.stop(); root.stop();

View file

@ -12,6 +12,7 @@
import QtQuick 2.5 import QtQuick 2.5
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import "../styles-uit" import "../styles-uit"
import "../controls-uit"
Item { Item {
property var dialogTitleText : ""; property var dialogTitleText : "";
@ -67,6 +68,29 @@ Item {
verticalAlignment: Text.AlignTop; verticalAlignment: Text.AlignTop;
} }
HiFiGlyphs {
id: closeGlyphButton;
text: hifi.glyphs.close;
size: 32;
anchors.verticalCenter: dialogTitle.verticalCenter;
anchors.right: parent.right;
anchors.rightMargin: 20;
MouseArea {
anchors.fill: closeGlyphButton;
hoverEnabled: true;
onEntered: {
parent.text = hifi.glyphs.closeInverted;
}
onExited: {
parent.text = hifi.glyphs.close;
}
onClicked: {
combo.visible = false;
}
}
}
ListModel { ListModel {
id: comboListViewModel; id: comboListViewModel;
} }
@ -92,8 +116,7 @@ Item {
color: selectedOptionIndex === index ? '#cee6ff' : 'white'; color: selectedOptionIndex === index ? '#cee6ff' : 'white';
Rectangle { Rectangle {
id: comboOptionSelected; id: comboOptionSelected;
visible: selectedOptionIndex === index ? true : false; color: selectedOptionIndex == index ? hifi.colors.blueAccent : 'white';
color: hifi.colors.blueAccent;
anchors.left: parent.left; anchors.left: parent.left;
anchors.leftMargin: 20; anchors.leftMargin: 20;
anchors.top: parent.top; anchors.top: parent.top;
@ -102,7 +125,7 @@ Item {
height: width; height: width;
radius: width; radius: width;
border.width: 3; border.width: 3;
border.color: hifi.colors.blueHighlight; border.color: selectedOptionIndex === index ? hifi.colors.blueHighlight: hifi.colors.lightGrayText;
} }

View file

@ -85,6 +85,28 @@ Item {
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textFormat: Text.StyledText textFormat: Text.StyledText
} }
HiFiGlyphs {
id: closeGlyphButton
text: hifi.glyphs.close
size: headerTextPixelSize
anchors.top: parent.top
anchors.topMargin: -20
anchors.right: parent.right
anchors.rightMargin: -25
MouseArea {
anchors.fill: closeGlyphButton
hoverEnabled: true
onEntered: {
parent.text = hifi.glyphs.closeInverted;
}
onExited: {
parent.text = hifi.glyphs.close;
}
onClicked: {
letterbox.visible = false;
}
}
}
} }
// Popup Text // Popup Text
Text { Text {

View file

@ -308,12 +308,11 @@ Rectangle {
MouseArea { MouseArea {
anchors.fill: parent; anchors.fill: parent;
hoverEnabled: true; hoverEnabled: true;
enabled: activeTab === "connectionsTab";
onClicked: letterbox(hifi.glyphs.question, onClicked: letterbox(hifi.glyphs.question,
"Connections and Friends", "Connections and Friends",
"<font color='purple'>Purple borders around profile pictures are <b>Connections</b>.</font><br>" + "<font color='purple'>Purple borders around profile pictures represent <b>Connections</b>.</font><br>" +
"When your availability is set to Everyone, Connections can see your username and location.<br><br>" + "When your availability is set to Everyone, Connections can see your username and location.<br><br>" +
"<font color='green'>Green borders around profile pictures are <b>Friends</b>.</font><br>" + "<font color='green'>Green borders around profile pictures represent <b>Friends</b>.</font><br>" +
"When your availability is set to Friends, only Friends can see your username and location."); "When your availability is set to Friends, only Friends can see your username and location.");
onEntered: connectionsHelpText.color = hifi.colors.blueHighlight; onEntered: connectionsHelpText.color = hifi.colors.blueHighlight;
onExited: connectionsHelpText.color = hifi.colors.blueAccent; onExited: connectionsHelpText.color = hifi.colors.blueAccent;
@ -849,11 +848,6 @@ Rectangle {
pal.sendToScript({method: newValue ? 'addFriend' : 'removeFriend', params: model.userName}); pal.sendToScript({method: newValue ? 'addFriend' : 'removeFriend', params: model.userName});
UserActivityLogger["palAction"](newValue ? styleData.role : "un-" + styleData.role, model.sessionId); UserActivityLogger["palAction"](newValue ? styleData.role : "un-" + styleData.role, model.sessionId);
// http://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html#creating-property-bindings-from-javascript
// I'm using an explicit binding here because clicking a checkbox breaks the implicit binding as set by
// "checked:" statement above.
checked = Qt.binding(function() { return (model["connection"] === "friend" ? true : false)});
} }
} }
} }

View file

@ -142,6 +142,7 @@
#include "ModelPackager.h" #include "ModelPackager.h"
#include "networking/HFWebEngineProfile.h" #include "networking/HFWebEngineProfile.h"
#include "networking/HFTabletWebEngineProfile.h" #include "networking/HFTabletWebEngineProfile.h"
#include "networking/FileTypeProfile.h"
#include "scripting/TestScriptingInterface.h" #include "scripting/TestScriptingInterface.h"
#include "scripting/AccountScriptingInterface.h" #include "scripting/AccountScriptingInterface.h"
#include "scripting/AssetMappingsScriptingInterface.h" #include "scripting/AssetMappingsScriptingInterface.h"
@ -218,6 +219,7 @@ static const QString FST_EXTENSION = ".fst";
static const QString FBX_EXTENSION = ".fbx"; static const QString FBX_EXTENSION = ".fbx";
static const QString OBJ_EXTENSION = ".obj"; static const QString OBJ_EXTENSION = ".obj";
static const QString AVA_JSON_EXTENSION = ".ava.json"; static const QString AVA_JSON_EXTENSION = ".ava.json";
static const QString WEB_VIEW_TAG = "noDownload=true";
static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f;
@ -1934,6 +1936,7 @@ void Application::initializeUi() {
qmlRegisterType<HFWebEngineProfile>("HFWebEngineProfile", 1, 0, "HFWebEngineProfile"); qmlRegisterType<HFWebEngineProfile>("HFWebEngineProfile", 1, 0, "HFWebEngineProfile");
qmlRegisterType<HFTabletWebEngineProfile>("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile"); qmlRegisterType<HFTabletWebEngineProfile>("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile");
qmlRegisterType<FileTypeProfile>("FileTypeProfile", 1, 0, "FileTypeProfile");
auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->create(_glWidget->qglContext()); offscreenUi->create(_glWidget->qglContext());
@ -5036,7 +5039,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
// TODO fix shadows and make them use the GPU library // TODO fix shadows and make them use the GPU library
// The pending changes collecting the changes here // The pending changes collecting the changes here
render::PendingChanges pendingChanges; render::Transaction transaction;
// FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities // FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities
// Background rendering decision // Background rendering decision
@ -5044,7 +5047,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
auto backgroundRenderData = make_shared<BackgroundRenderData>(); auto backgroundRenderData = make_shared<BackgroundRenderData>();
auto backgroundRenderPayload = make_shared<BackgroundRenderData::Payload>(backgroundRenderData); auto backgroundRenderPayload = make_shared<BackgroundRenderData::Payload>(backgroundRenderData);
BackgroundRenderData::_item = _main3DScene->allocateID(); BackgroundRenderData::_item = _main3DScene->allocateID();
pendingChanges.resetItem(BackgroundRenderData::_item, backgroundRenderPayload); transaction.resetItem(BackgroundRenderData::_item, backgroundRenderPayload);
} }
// Assuming nothing get's rendered through that // Assuming nothing get's rendered through that
@ -5062,7 +5065,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
static_cast<int>(RenderArgs::RENDER_DEBUG_HULLS)); static_cast<int>(RenderArgs::RENDER_DEBUG_HULLS));
} }
renderArgs->_debugFlags = renderDebugFlags; renderArgs->_debugFlags = renderDebugFlags;
//ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges); //ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, transaction);
} }
} }
@ -5074,9 +5077,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
WorldBoxRenderData::_item = _main3DScene->allocateID(); WorldBoxRenderData::_item = _main3DScene->allocateID();
pendingChanges.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
} else { } else {
pendingChanges.updateItem<WorldBoxRenderData>(WorldBoxRenderData::_item, transaction.updateItem<WorldBoxRenderData>(WorldBoxRenderData::_item,
[](WorldBoxRenderData& payload) { [](WorldBoxRenderData& payload) {
payload._val++; payload._val++;
}); });
@ -5089,10 +5092,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
} }
{ {
PerformanceTimer perfTimer("SceneProcessPendingChanges"); PerformanceTimer perfTimer("SceneProcessTransaction");
_main3DScene->enqueuePendingChanges(pendingChanges); _main3DScene->enqueueTransaction(transaction);
_main3DScene->processPendingChangesQueue(); _main3DScene->processTransactionQueue();
} }
// For now every frame pass the renderContext // For now every frame pass the renderContext
@ -5545,7 +5548,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
bool Application::canAcceptURL(const QString& urlString) const { bool Application::canAcceptURL(const QString& urlString) const {
QUrl url(urlString); QUrl url(urlString);
if (urlString.startsWith(HIFI_URL_SCHEME)) { if (url.query().contains(WEB_VIEW_TAG)) {
return false;
} else if (urlString.startsWith(HIFI_URL_SCHEME)) {
return true; return true;
} }
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions); QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
@ -5653,7 +5658,9 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
QUrl scriptURL { scriptFilenameOrURL }; QUrl scriptURL { scriptFilenameOrURL };
if (scriptURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) { if (scriptURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) {
shortName = shortName.mid(shortName.lastIndexOf('/') + 1); int startIndex = shortName.lastIndexOf('/') + 1;
int endIndex = shortName.lastIndexOf('?');
shortName = shortName.mid(startIndex, endIndex - startIndex);
} }
QString message = "Would you like to run this script:\n" + shortName; QString message = "Would you like to run this script:\n" + shortName;

View file

@ -476,34 +476,34 @@ static TextRenderer3D* textRenderer(TextRendererType type) {
return displayNameRenderer; return displayNameRenderer;
} }
bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
auto avatarPayload = new render::Payload<AvatarData>(self); auto avatarPayload = new render::Payload<AvatarData>(self);
auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload); auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload);
_renderItemID = scene->allocateID(); _renderItemID = scene->allocateID();
pendingChanges.resetItem(_renderItemID, avatarPayloadPointer); transaction.resetItem(_renderItemID, avatarPayloadPointer);
_skeletonModel->addToScene(scene, pendingChanges); _skeletonModel->addToScene(scene, transaction);
for (auto& attachmentModel : _attachmentModels) { for (auto& attachmentModel : _attachmentModels) {
attachmentModel->addToScene(scene, pendingChanges); attachmentModel->addToScene(scene, transaction);
} }
_inScene = true; _inScene = true;
return true; return true;
} }
void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
pendingChanges.removeItem(_renderItemID); transaction.removeItem(_renderItemID);
render::Item::clearID(_renderItemID); render::Item::clearID(_renderItemID);
_skeletonModel->removeFromScene(scene, pendingChanges); _skeletonModel->removeFromScene(scene, transaction);
for (auto& attachmentModel : _attachmentModels) { for (auto& attachmentModel : _attachmentModels) {
attachmentModel->removeFromScene(scene, pendingChanges); attachmentModel->removeFromScene(scene, transaction);
} }
_inScene = false; _inScene = false;
} }
void Avatar::updateRenderItem(render::PendingChanges& pendingChanges) { void Avatar::updateRenderItem(render::Transaction& transaction) {
if (render::Item::isValidID(_renderItemID)) { if (render::Item::isValidID(_renderItemID)) {
pendingChanges.updateItem<render::Payload<AvatarData>>(_renderItemID, [](render::Payload<AvatarData>& p) {}); transaction.updateItem<render::Payload<AvatarData>>(_renderItemID, [](render::Payload<AvatarData>& p) {});
} }
} }
@ -680,24 +680,24 @@ void Avatar::fixupModelsInScene() {
// check to see if when we added our models to the scene they were ready, if they were not ready, then // check to see if when we added our models to the scene they were ready, if they were not ready, then
// fix them up in the scene // fix them up in the scene
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) { if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) {
_skeletonModel->removeFromScene(scene, pendingChanges); _skeletonModel->removeFromScene(scene, transaction);
_skeletonModel->addToScene(scene, pendingChanges); _skeletonModel->addToScene(scene, transaction);
} }
for (auto attachmentModel : _attachmentModels) { for (auto attachmentModel : _attachmentModels) {
if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) { if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) {
attachmentModel->removeFromScene(scene, pendingChanges); attachmentModel->removeFromScene(scene, transaction);
attachmentModel->addToScene(scene, pendingChanges); attachmentModel->addToScene(scene, transaction);
} }
} }
for (auto attachmentModelToRemove : _attachmentsToRemove) { for (auto attachmentModelToRemove : _attachmentsToRemove) {
attachmentModelToRemove->removeFromScene(scene, pendingChanges); attachmentModelToRemove->removeFromScene(scene, transaction);
} }
_attachmentsToDelete.insert(_attachmentsToDelete.end(), _attachmentsToRemove.begin(), _attachmentsToRemove.end()); _attachmentsToDelete.insert(_attachmentsToDelete.end(), _attachmentsToRemove.begin(), _attachmentsToRemove.end());
_attachmentsToRemove.clear(); _attachmentsToRemove.clear();
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const { bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const {
@ -1422,14 +1422,14 @@ QList<QVariant> Avatar::getSkeleton() {
void Avatar::addToScene(AvatarSharedPointer myHandle) { void Avatar::addToScene(AvatarSharedPointer myHandle) {
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
if (scene) { if (scene) {
render::PendingChanges pendingChanges; render::Transaction transaction;
auto nodelist = DependencyManager::get<NodeList>(); auto nodelist = DependencyManager::get<NodeList>();
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars() if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()
&& !nodelist->isIgnoringNode(getSessionUUID()) && !nodelist->isIgnoringNode(getSessionUUID())
&& !nodelist->isRadiusIgnoringNode(getSessionUUID())) { && !nodelist->isRadiusIgnoringNode(getSessionUUID())) {
addToScene(myHandle, scene, pendingChanges); addToScene(myHandle, scene, transaction);
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} else { } else {
qCWarning(interfaceapp) << "AvatarManager::addAvatar() : Unexpected null scene, possibly during application shutdown"; qCWarning(interfaceapp) << "AvatarManager::addAvatar() : Unexpected null scene, possibly during application shutdown";
} }

View file

@ -82,12 +82,12 @@ public:
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition); virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition);
bool addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, bool addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges); render::Transaction& transaction);
void removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, void removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges); render::Transaction& transaction);
void updateRenderItem(render::PendingChanges& pendingChanges); void updateRenderItem(render::Transaction& transaction);
virtual void postUpdate(float deltaTime); virtual void postUpdate(float deltaTime);

View file

@ -104,11 +104,11 @@ void AvatarManager::init() {
this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection); this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection);
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()) { if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()) {
_myAvatar->addToScene(_myAvatar, scene, pendingChanges); _myAvatar->addToScene(_myAvatar, scene, transaction);
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
void AvatarManager::updateMyAvatar(float deltaTime) { void AvatarManager::updateMyAvatar(float deltaTime) {
@ -192,7 +192,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
return false; return false;
}); });
render::PendingChanges pendingChanges; render::Transaction transaction;
uint64_t startTime = usecTimestampNow(); uint64_t startTime = usecTimestampNow();
const uint64_t UPDATE_BUDGET = 2000; // usec const uint64_t UPDATE_BUDGET = 2000; // usec
uint64_t updateExpiry = startTime + UPDATE_BUDGET; uint64_t updateExpiry = startTime + UPDATE_BUDGET;
@ -228,7 +228,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
numAvatarsUpdated++; numAvatarsUpdated++;
} }
avatar->simulate(deltaTime, inView); avatar->simulate(deltaTime, inView);
avatar->updateRenderItem(pendingChanges); avatar->updateRenderItem(transaction);
avatar->setLastRenderUpdateTime(startTime); avatar->setLastRenderUpdateTime(startTime);
} else { } else {
// we've spent our full time budget --> bail on the rest of the avatar updates // we've spent our full time budget --> bail on the rest of the avatar updates
@ -262,7 +262,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
_avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC; _avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC;
_numAvatarsUpdated = numAvatarsUpdated; _numAvatarsUpdated = numAvatarsUpdated;
_numAvatarsNotUpdated = numAVatarsNotUpdated; _numAvatarsNotUpdated = numAVatarsNotUpdated;
qApp->getMain3DScene()->enqueuePendingChanges(pendingChanges); qApp->getMain3DScene()->enqueueTransaction(transaction);
simulateAvatarFades(deltaTime); simulateAvatarFades(deltaTime);
} }
@ -283,13 +283,13 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
const float MIN_FADE_SCALE = MIN_AVATAR_SCALE; const float MIN_FADE_SCALE = MIN_AVATAR_SCALE;
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
while (fadingIterator != _avatarFades.end()) { while (fadingIterator != _avatarFades.end()) {
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator); auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE);
avatar->animateScaleChanges(deltaTime); avatar->animateScaleChanges(deltaTime);
if (avatar->getTargetScale() <= MIN_FADE_SCALE) { if (avatar->getTargetScale() <= MIN_FADE_SCALE) {
avatar->removeFromScene(*fadingIterator, scene, pendingChanges); avatar->removeFromScene(*fadingIterator, scene, transaction);
// only remove from _avatarFades if we're sure its motionState has been removed from PhysicsEngine // only remove from _avatarFades if we're sure its motionState has been removed from PhysicsEngine
if (_motionStatesToRemoveFromPhysics.empty()) { if (_motionStatesToRemoveFromPhysics.empty()) {
fadingIterator = _avatarFades.erase(fadingIterator); fadingIterator = _avatarFades.erase(fadingIterator);
@ -302,7 +302,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
++fadingIterator; ++fadingIterator;
} }
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
AvatarSharedPointer AvatarManager::newSharedAvatar() { AvatarSharedPointer AvatarManager::newSharedAvatar() {
@ -479,17 +479,17 @@ void AvatarManager::updateAvatarRenderStatus(bool shouldRenderAvatars) {
for (auto avatarData : _avatarHash) { for (auto avatarData : _avatarHash) {
auto avatar = std::static_pointer_cast<Avatar>(avatarData); auto avatar = std::static_pointer_cast<Avatar>(avatarData);
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
avatar->addToScene(avatar, scene, pendingChanges); avatar->addToScene(avatar, scene, transaction);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
} else { } else {
for (auto avatarData : _avatarHash) { for (auto avatarData : _avatarHash) {
auto avatar = std::static_pointer_cast<Avatar>(avatarData); auto avatar = std::static_pointer_cast<Avatar>(avatarData);
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
avatar->removeFromScene(avatar, scene, pendingChanges); avatar->removeFromScene(avatar, scene, transaction);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
} }
} }

View file

@ -205,10 +205,10 @@ void CauterizedModel::updateRenderItems() {
uint32_t deleteGeometryCounter = self->getGeometryCounter(); uint32_t deleteGeometryCounter = self->getGeometryCounter();
render::PendingChanges pendingChanges; render::Transaction transaction;
QList<render::ItemID> keys = self->getRenderItems().keys(); QList<render::ItemID> keys = self->getRenderItems().keys();
foreach (auto itemID, keys) { foreach (auto itemID, keys) {
pendingChanges.updateItem<CauterizedMeshPartPayload>(itemID, [modelTransform, deleteGeometryCounter](CauterizedMeshPartPayload& data) { transaction.updateItem<CauterizedMeshPartPayload>(itemID, [modelTransform, deleteGeometryCounter](CauterizedMeshPartPayload& data) {
if (data._model && data._model->isLoaded()) { if (data._model && data._model->isLoaded()) {
// Ensure the model geometry was not reset between frames // Ensure the model geometry was not reset between frames
if (deleteGeometryCounter == data._model->getGeometryCounter()) { if (deleteGeometryCounter == data._model->getGeometryCounter()) {
@ -233,7 +233,7 @@ void CauterizedModel::updateRenderItems() {
}); });
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
}); });
} else { } else {
Model::updateRenderItems(); Model::updateRenderItems();

View file

@ -0,0 +1,26 @@
//
// FileTypeProfile.cpp
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 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 "FileTypeProfile.h"
#include "FileTypeRequestInterceptor.h"
static const QString QML_WEB_ENGINE_STORAGE_NAME = "qmlWebEngine";
FileTypeProfile::FileTypeProfile(QObject* parent) :
QQuickWebEngineProfile(parent)
{
static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)";
setHttpUserAgent(WEB_ENGINE_USER_AGENT);
auto requestInterceptor = new FileTypeRequestInterceptor(this);
setRequestInterceptor(requestInterceptor);
}

View file

@ -0,0 +1,25 @@
//
// FileTypeProfile.h
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 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
//
#pragma once
#ifndef hifi_FileTypeProfile_h
#define hifi_FileTypeProfile_h
#include <QtWebEngine/QQuickWebEngineProfile>
class FileTypeProfile : public QQuickWebEngineProfile {
public:
FileTypeProfile(QObject* parent = Q_NULLPTR);
};
#endif // hifi_FileTypeProfile_h

View file

@ -0,0 +1,21 @@
//
// FileTypeRequestInterceptor.cpp
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 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 "FileTypeRequestInterceptor.h"
#include <QtCore/QDebug>
#include "RequestFilters.h"
void FileTypeRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
RequestFilters::interceptHFWebEngineRequest(info);
RequestFilters::interceptFileType(info);
}

View file

@ -0,0 +1,26 @@
//
// FileTypeRequestInterceptor.h
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 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
//
#pragma once
#ifndef hifi_FileTypeRequestInterceptor_h
#define hifi_FileTypeRequestInterceptor_h
#include <QWebEngineUrlRequestInterceptor>
class FileTypeRequestInterceptor : public QWebEngineUrlRequestInterceptor {
public:
FileTypeRequestInterceptor(QObject* parent) : QWebEngineUrlRequestInterceptor(parent) {};
virtual void interceptRequest(QWebEngineUrlRequestInfo& info) override;
};
#endif // hifi_FileTypeRequestInterceptor_h

View file

@ -10,35 +10,12 @@
// //
#include "HFWebEngineRequestInterceptor.h" #include "HFWebEngineRequestInterceptor.h"
#include "NetworkingConstants.h"
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <AccountManager.h> #include <AccountManager.h>
#include "RequestFilters.h"
bool isAuthableHighFidelityURL(const QUrl& url) {
static const QStringList HF_HOSTS = {
"highfidelity.com", "highfidelity.io",
"metaverse.highfidelity.com", "metaverse.highfidelity.io"
};
const auto& scheme = url.scheme();
const auto& host = url.host();
return (scheme == "https" && HF_HOSTS.contains(host)) ||
((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host()));
}
void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
// check if this is a request to a highfidelity URL RequestFilters::interceptHFWebEngineRequest(info);
if (isAuthableHighFidelityURL(info.requestUrl())) {
// if we have an access token, add it to the right HTTP header for authorization
auto accountManager = DependencyManager::get<AccountManager>();
if (accountManager->hasValidAccessToken()) {
static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization";
QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token;
info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit());
}
}
} }

View file

@ -0,0 +1,65 @@
//
// RequestFilters.cpp
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 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 "RequestFilters.h"
#include "NetworkingConstants.h"
#include <QtCore/QDebug>
#include <AccountManager.h>
namespace {
bool isAuthableHighFidelityURL(const QUrl& url) {
static const QStringList HF_HOSTS = {
"highfidelity.com", "highfidelity.io",
"metaverse.highfidelity.com", "metaverse.highfidelity.io"
};
const auto& scheme = url.scheme();
const auto& host = url.host();
return (scheme == "https" && HF_HOSTS.contains(host)) ||
((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host()));
}
bool isScript(const QString filename) {
return filename.endsWith(".js", Qt::CaseInsensitive);
}
bool isJSON(const QString filename) {
return filename.endsWith(".json", Qt::CaseInsensitive);
}
}
void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) {
// check if this is a request to a highfidelity URL
if (isAuthableHighFidelityURL(info.requestUrl())) {
// if we have an access token, add it to the right HTTP header for authorization
auto accountManager = DependencyManager::get<AccountManager>();
if (accountManager->hasValidAccessToken()) {
static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization";
QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token;
info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit());
}
}
}
void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) {
QString filename = info.requestUrl().fileName();
if (isScript(filename) || isJSON(filename)) {
static const QString CONTENT_HEADER = "Accept";
static const QString TYPE_VALUE = "text/plain,text/html";
info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit());
}
}

View file

@ -0,0 +1,28 @@
//
// RequestFilters.h
// interface/src/networking
//
// Created by Kunal Gosar on 2017-03-10.
// Copyright 2017 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
//
#pragma once
#ifndef hifi_RequestFilters_h
#define hifi_RequestFilters_h
#include <QObject>
#include <QWebEngineUrlRequestInfo>
class RequestFilters : public QObject {
Q_OBJECT
public:
static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info);
static void interceptFileType(QWebEngineUrlRequestInfo& info);
};
#endif // hifi_RequestFilters_h

View file

@ -199,9 +199,9 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) {
auto itemID = getRenderItemID(); auto itemID = getRenderItemID();
if (render::Item::isValidID(itemID)) { if (render::Item::isValidID(itemID)) {
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.updateItem(itemID); transaction.updateItem(itemID);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
} }
} }
@ -264,9 +264,9 @@ void Base3DOverlay::locationChanged(bool tellPhysics) {
auto itemID = getRenderItemID(); auto itemID = getRenderItemID();
if (render::Item::isValidID(itemID)) { if (render::Item::isValidID(itemID)) {
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.updateItem(itemID); transaction.updateItem(itemID);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
} }

View file

@ -58,15 +58,15 @@ void ModelOverlay::update(float deltatime) {
_isLoaded = _model->isActive(); _isLoaded = _model->isActive();
} }
bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
Volume3DOverlay::addToScene(overlay, scene, pendingChanges); Volume3DOverlay::addToScene(overlay, scene, transaction);
_model->addToScene(scene, pendingChanges); _model->addToScene(scene, transaction);
return true; return true;
} }
void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
Volume3DOverlay::removeFromScene(overlay, scene, pendingChanges); Volume3DOverlay::removeFromScene(overlay, scene, transaction);
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, transaction);
} }
void ModelOverlay::render(RenderArgs* args) { void ModelOverlay::render(RenderArgs* args) {
@ -74,16 +74,16 @@ void ModelOverlay::render(RenderArgs* args) {
// check to see if when we added our model to the scene they were ready, if they were not ready, then // check to see if when we added our model to the scene they were ready, if they were not ready, then
// fix them up in the scene // fix them up in the scene
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
if (_model->needsFixupInScene()) { if (_model->needsFixupInScene()) {
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, transaction);
_model->addToScene(scene, pendingChanges); _model->addToScene(scene, transaction);
} }
_model->setVisibleInScene(_visible, scene); _model->setVisibleInScene(_visible, scene);
_model->setLayeredInFront(getDrawInFront(), scene); _model->setLayeredInFront(getDrawInFront(), scene);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
void ModelOverlay::setProperties(const QVariantMap& properties) { void ModelOverlay::setProperties(const QVariantMap& properties) {

View file

@ -36,8 +36,8 @@ public:
virtual ModelOverlay* createClone() const override; virtual ModelOverlay* createClone() const override;
virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override; virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override;
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override; virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override;
void locationChanged(bool tellPhysics) override; void locationChanged(bool tellPhysics) override;

View file

@ -196,14 +196,14 @@ float Overlay::updatePulse() {
return _pulse; return _pulse;
} }
bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
_renderItemID = scene->allocateID(); _renderItemID = scene->allocateID();
pendingChanges.resetItem(_renderItemID, std::make_shared<Overlay::Payload>(overlay)); transaction.resetItem(_renderItemID, std::make_shared<Overlay::Payload>(overlay));
return true; return true;
} }
void Overlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { void Overlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
pendingChanges.removeItem(_renderItemID); transaction.removeItem(_renderItemID);
render::Item::clearID(_renderItemID); render::Item::clearID(_renderItemID);
} }

View file

@ -48,8 +48,8 @@ public:
virtual AABox getBounds() const = 0; virtual AABox getBounds() const = 0;
virtual bool supportsGetProperty() const { return true; } virtual bool supportsGetProperty() const { return true; }
virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges); virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::Transaction& transaction);
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::Transaction& transaction);
virtual const render::ShapeKey getShapeKey() { return render::ShapeKey::Builder::ownPipeline(); } virtual const render::ShapeKey getShapeKey() { return render::ShapeKey::Builder::ownPipeline(); }

View file

@ -78,7 +78,7 @@ void Overlays::update(float deltatime) {
void Overlays::cleanupOverlaysToDelete() { void Overlays::cleanupOverlaysToDelete() {
if (!_overlaysToDelete.isEmpty()) { if (!_overlaysToDelete.isEmpty()) {
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
{ {
QWriteLocker lock(&_deleteLock); QWriteLocker lock(&_deleteLock);
@ -88,13 +88,13 @@ void Overlays::cleanupOverlaysToDelete() {
auto itemID = overlay->getRenderItemID(); auto itemID = overlay->getRenderItemID();
if (render::Item::isValidID(itemID)) { if (render::Item::isValidID(itemID)) {
overlay->removeFromScene(overlay, scene, pendingChanges); overlay->removeFromScene(overlay, scene, transaction);
} }
} while (!_overlaysToDelete.isEmpty()); } while (!_overlaysToDelete.isEmpty());
} }
if (pendingChanges._removedItems.size() > 0) { if (transaction._removedItems.size() > 0) {
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
} }
} }
@ -197,9 +197,9 @@ OverlayID Overlays::addOverlay(Overlay::Pointer overlay) {
_overlaysWorld[thisID] = overlay; _overlaysWorld[thisID] = overlay;
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
overlay->addToScene(overlay, scene, pendingChanges); overlay->addToScene(overlay, scene, transaction);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} else { } else {
_overlaysHUD[thisID] = overlay; _overlaysHUD[thisID] = overlay;
} }

View file

@ -127,11 +127,11 @@ void EntityTreeRenderer::clear() {
// remove all entities from the scene // remove all entities from the scene
auto scene = _viewState->getMain3DScene(); auto scene = _viewState->getMain3DScene();
if (scene) { if (scene) {
render::PendingChanges pendingChanges; render::Transaction transaction;
foreach(auto entity, _entitiesInScene) { foreach(auto entity, _entitiesInScene) {
entity->removeFromScene(entity, scene, pendingChanges); entity->removeFromScene(entity, scene, transaction);
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} else { } else {
qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown"; qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown";
} }
@ -951,11 +951,11 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
// here's where we remove the entity payload from the scene // here's where we remove the entity payload from the scene
if (_entitiesInScene.contains(entityID)) { if (_entitiesInScene.contains(entityID)) {
auto entity = _entitiesInScene.take(entityID); auto entity = _entitiesInScene.take(entityID);
render::PendingChanges pendingChanges; render::Transaction transaction;
auto scene = _viewState->getMain3DScene(); auto scene = _viewState->getMain3DScene();
if (scene) { if (scene) {
entity->removeFromScene(entity, scene, pendingChanges); entity->removeFromScene(entity, scene, transaction);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} else { } else {
qCWarning(entitiesrenderer) << "EntityTreeRenderer::deletingEntity(), Unexpected null scene, possibly during application shutdown"; qCWarning(entitiesrenderer) << "EntityTreeRenderer::deletingEntity(), Unexpected null scene, possibly during application shutdown";
} }
@ -973,13 +973,13 @@ void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) {
void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) { void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) {
// here's where we add the entity payload to the scene // here's where we add the entity payload to the scene
render::PendingChanges pendingChanges; render::Transaction transaction;
auto scene = _viewState->getMain3DScene(); auto scene = _viewState->getMain3DScene();
if (scene) { if (scene) {
if (entity->addToScene(entity, scene, pendingChanges)) { if (entity->addToScene(entity, scene, transaction)) {
_entitiesInScene.insert(entity->getEntityItemID(), entity); _entitiesInScene.insert(entity->getEntityItemID(), entity);
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} else { } else {
qCWarning(entitiesrenderer) << "EntityTreeRenderer::addEntityToScene(), Unexpected null scene, possibly during application shutdown"; qCWarning(entitiesrenderer) << "EntityTreeRenderer::addEntityToScene(), Unexpected null scene, possibly during application shutdown";
} }

View file

@ -54,7 +54,7 @@ namespace render {
// Mixin class for implementing basic single item rendering // Mixin class for implementing basic single item rendering
class SimpleRenderableEntityItem { class SimpleRenderableEntityItem {
public: public:
bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
_myItem = scene->allocateID(); _myItem = scene->allocateID();
auto renderData = std::make_shared<RenderableEntityItemProxy>(self, _myItem); auto renderData = std::make_shared<RenderableEntityItemProxy>(self, _myItem);
@ -64,13 +64,13 @@ public:
makeEntityItemStatusGetters(self, statusGetters); makeEntityItemStatusGetters(self, statusGetters);
renderPayload->addStatusGetters(statusGetters); renderPayload->addStatusGetters(statusGetters);
pendingChanges.resetItem(_myItem, renderPayload); transaction.resetItem(_myItem, renderPayload);
return true; return true;
} }
void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
pendingChanges.removeItem(_myItem); transaction.removeItem(_myItem);
render::Item::clearID(_myItem); render::Item::clearID(_myItem);
} }
@ -79,14 +79,14 @@ public:
return; return;
} }
render::PendingChanges pendingChanges; render::Transaction transaction;
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
if (scene) { if (scene) {
pendingChanges.updateItem<RenderableEntityItemProxy>(_myItem, [](RenderableEntityItemProxy& data) { transaction.updateItem<RenderableEntityItemProxy>(_myItem, [](RenderableEntityItemProxy& data) {
}); });
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} else { } else {
qCWarning(entitiesrenderer) << "SimpleRenderableEntityItem::notifyChanged(), Unexpected null scene, possibly during application shutdown"; qCWarning(entitiesrenderer) << "SimpleRenderableEntityItem::notifyChanged(), Unexpected null scene, possibly during application shutdown";
} }
@ -99,8 +99,8 @@ private:
#define SIMPLE_RENDERABLE() \ #define SIMPLE_RENDERABLE() \
public: \ public: \
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override { return _renderHelper.addToScene(self, scene, pendingChanges); } \ virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override { return _renderHelper.addToScene(self, scene, transaction); } \
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override { _renderHelper.removeFromScene(self, scene, pendingChanges); } \ virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override { _renderHelper.removeFromScene(self, scene, transaction); } \
virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); _renderHelper.notifyChanged(); } \ virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); _renderHelper.notifyChanged(); } \
virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); _renderHelper.notifyChanged(); } \ virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); _renderHelper.notifyChanged(); } \
void checkFading() { \ void checkFading() { \

View file

@ -27,7 +27,7 @@ RenderableLightEntityItem::RenderableLightEntityItem(const EntityItemID& entityI
{ {
} }
bool RenderableLightEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { bool RenderableLightEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
_myItem = scene->allocateID(); _myItem = scene->allocateID();
auto renderItem = std::make_shared<LightPayload>(); auto renderItem = std::make_shared<LightPayload>();
@ -39,7 +39,7 @@ bool RenderableLightEntityItem::addToScene(EntityItemPointer self, std::shared_p
makeEntityItemStatusGetters(self, statusGetters); makeEntityItemStatusGetters(self, statusGetters);
renderPayload->addStatusGetters(statusGetters); renderPayload->addStatusGetters(statusGetters);
pendingChanges.resetItem(_myItem, renderPayload); transaction.resetItem(_myItem, renderPayload);
return true; return true;
} }
@ -51,8 +51,8 @@ void RenderableLightEntityItem::somethingChangedNotification() {
LightEntityItem::somethingChangedNotification(); LightEntityItem::somethingChangedNotification();
} }
void RenderableLightEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { void RenderableLightEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
pendingChanges.removeItem(_myItem); transaction.removeItem(_myItem);
render::Item::clearID(_myItem); render::Item::clearID(_myItem);
} }
@ -81,12 +81,12 @@ void RenderableLightEntityItem::notifyChanged() {
return; return;
} }
render::PendingChanges pendingChanges; render::Transaction transaction;
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
updateLightFromEntity(pendingChanges); updateLightFromEntity(transaction);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
@ -103,13 +103,13 @@ bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& ori
} }
void RenderableLightEntityItem::updateLightFromEntity(render::PendingChanges& pendingChanges) { void RenderableLightEntityItem::updateLightFromEntity(render::Transaction& transaction) {
if (!render::Item::isValidID(_myItem)) { if (!render::Item::isValidID(_myItem)) {
return; return;
} }
pendingChanges.updateItem<LightPayload>(_myItem, [&](LightPayload& data) { transaction.updateItem<LightPayload>(_myItem, [&](LightPayload& data) {
updateRenderItemFromEntity(data); updateRenderItemFromEntity(data);
}); });
} }

View file

@ -28,12 +28,12 @@ public:
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
void** intersectedObject, bool precisionPicking) const override; void** intersectedObject, bool precisionPicking) const override;
void updateLightFromEntity(render::PendingChanges& pendingChanges); void updateLightFromEntity(render::Transaction& transaction);
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override; virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override;
virtual void somethingChangedNotification() override; virtual void somethingChangedNotification() override;
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override; virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override;
virtual void locationChanged(bool tellPhysics = true) override; virtual void locationChanged(bool tellPhysics = true) override;

View file

@ -228,20 +228,20 @@ namespace render {
} }
bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { render::Transaction& transaction) {
_myMetaItem = scene->allocateID(); _myMetaItem = scene->allocateID();
auto renderData = std::make_shared<RenderableModelEntityItemMeta>(self); auto renderData = std::make_shared<RenderableModelEntityItemMeta>(self);
auto renderPayload = std::make_shared<RenderableModelEntityItemMeta::Payload>(renderData); auto renderPayload = std::make_shared<RenderableModelEntityItemMeta::Payload>(renderData);
pendingChanges.resetItem(_myMetaItem, renderPayload); transaction.resetItem(_myMetaItem, renderPayload);
if (_model) { if (_model) {
render::Item::Status::Getters statusGetters; render::Item::Status::Getters statusGetters;
makeEntityItemStatusGetters(getThisPointer(), statusGetters); makeEntityItemStatusGetters(getThisPointer(), statusGetters);
// note: we don't mind if the model fails to add, we'll retry (in render()) until it succeeds // note: we don't mind if the model fails to add, we'll retry (in render()) until it succeeds
_model->addToScene(scene, pendingChanges, statusGetters); _model->addToScene(scene, transaction, statusGetters);
} }
// we've successfully added _myMetaItem so we always return true // we've successfully added _myMetaItem so we always return true
@ -249,11 +249,11 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p
} }
void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { render::Transaction& transaction) {
pendingChanges.removeItem(_myMetaItem); transaction.removeItem(_myMetaItem);
render::Item::clearID(_myMetaItem); render::Item::clearID(_myMetaItem);
if (_model) { if (_model) {
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, transaction);
} }
} }
@ -467,15 +467,15 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
} }
if (_model->needsFixupInScene()) { if (_model->needsFixupInScene()) {
render::PendingChanges pendingChanges; render::Transaction transaction;
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, transaction);
render::Item::Status::Getters statusGetters; render::Item::Status::Getters statusGetters;
makeEntityItemStatusGetters(getThisPointer(), statusGetters); makeEntityItemStatusGetters(getThisPointer(), statusGetters);
_model->addToScene(scene, pendingChanges, statusGetters); _model->addToScene(scene, transaction, statusGetters);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
auto& currentURL = getParsedModelURL(); auto& currentURL = getParsedModelURL();
@ -525,9 +525,9 @@ ModelPointer RenderableModelEntityItem::getModel(QSharedPointer<EntityTreeRender
} else if (_model) { } else if (_model) {
// remove from scene // remove from scene
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, transaction);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
// release interest // release interest
_myRenderer->releaseModel(_model); _myRenderer->releaseModel(_model);
@ -1226,10 +1226,10 @@ void RenderableModelEntityItem::locationChanged(bool tellPhysics) {
} }
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.updateItem(myMetaItem); transaction.updateItem(myMetaItem);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
}); });
} }
} }

View file

@ -40,8 +40,8 @@ public:
void doInitialModelSimulation(); void doInitialModelSimulation();
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override; virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override;
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override; virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override;
void updateModelBounds(); void updateModelBounds();

View file

@ -162,7 +162,7 @@ RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const Ent
bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self,
render::ScenePointer scene, render::ScenePointer scene,
render::PendingChanges& pendingChanges) { render::Transaction& transaction) {
_scene = scene; _scene = scene;
_renderItemId = _scene->allocateID(); _renderItemId = _scene->allocateID();
auto particlePayloadData = std::make_shared<ParticlePayloadData>(); auto particlePayloadData = std::make_shared<ParticlePayloadData>();
@ -171,14 +171,14 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self,
render::Item::Status::Getters statusGetters; render::Item::Status::Getters statusGetters;
makeEntityItemStatusGetters(getThisPointer(), statusGetters); makeEntityItemStatusGetters(getThisPointer(), statusGetters);
renderPayload->addStatusGetters(statusGetters); renderPayload->addStatusGetters(statusGetters);
pendingChanges.resetItem(_renderItemId, renderPayload); transaction.resetItem(_renderItemId, renderPayload);
return true; return true;
} }
void RenderableParticleEffectEntityItem::removeFromScene(EntityItemPointer self, void RenderableParticleEffectEntityItem::removeFromScene(EntityItemPointer self,
render::ScenePointer scene, render::ScenePointer scene,
render::PendingChanges& pendingChanges) { render::Transaction& transaction) {
pendingChanges.removeItem(_renderItemId); transaction.removeItem(_renderItemId);
_scene = nullptr; _scene = nullptr;
render::Item::clearID(_renderItemId); render::Item::clearID(_renderItemId);
}; };
@ -206,12 +206,12 @@ void RenderableParticleEffectEntityItem::updateRenderItem() {
return; return;
} }
if (!getVisible()) { if (!getVisible()) {
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.updateItem<ParticlePayloadData>(_renderItemId, [](ParticlePayloadData& payload) { transaction.updateItem<ParticlePayloadData>(_renderItemId, [](ParticlePayloadData& payload) {
payload.setVisibleFlag(false); payload.setVisibleFlag(false);
}); });
_scene->enqueuePendingChanges(pendingChanges); _scene->enqueueTransaction(transaction);
return; return;
} }
@ -253,8 +253,8 @@ void RenderableParticleEffectEntityItem::updateRenderItem() {
} }
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.updateItem<ParticlePayloadData>(_renderItemId, [=](ParticlePayloadData& payload) { transaction.updateItem<ParticlePayloadData>(_renderItemId, [=](ParticlePayloadData& payload) {
payload.setVisibleFlag(true); payload.setVisibleFlag(true);
// Update particle uniforms // Update particle uniforms
@ -282,7 +282,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() {
} }
}); });
_scene->enqueuePendingChanges(pendingChanges); _scene->enqueueTransaction(transaction);
} }
void RenderableParticleEffectEntityItem::createPipelines() { void RenderableParticleEffectEntityItem::createPipelines() {
@ -318,9 +318,9 @@ void RenderableParticleEffectEntityItem::notifyBoundChanged() {
if (!render::Item::isValidID(_renderItemId)) { if (!render::Item::isValidID(_renderItemId)) {
return; return;
} }
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.updateItem<ParticlePayloadData>(_renderItemId, [](ParticlePayloadData& payload) { transaction.updateItem<ParticlePayloadData>(_renderItemId, [](ParticlePayloadData& payload) {
}); });
_scene->enqueuePendingChanges(pendingChanges); _scene->enqueueTransaction(transaction);
} }

View file

@ -25,8 +25,8 @@ public:
void updateRenderItem(); void updateRenderItem();
virtual bool addToScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) override; virtual bool addToScene(EntityItemPointer self, render::ScenePointer scene, render::Transaction& transaction) override;
virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) override; virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::Transaction& transaction) override;
protected: protected:
virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); } virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); }

View file

@ -817,7 +817,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self, bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self,
std::shared_ptr<render::Scene> scene, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { render::Transaction& transaction) {
_myItem = scene->allocateID(); _myItem = scene->allocateID();
auto renderItem = std::make_shared<PolyVoxPayload>(getThisPointer()); auto renderItem = std::make_shared<PolyVoxPayload>(getThisPointer());
@ -828,15 +828,15 @@ bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self,
makeEntityItemStatusGetters(getThisPointer(), statusGetters); makeEntityItemStatusGetters(getThisPointer(), statusGetters);
renderPayload->addStatusGetters(statusGetters); renderPayload->addStatusGetters(statusGetters);
pendingChanges.resetItem(_myItem, renderPayload); transaction.resetItem(_myItem, renderPayload);
return true; return true;
} }
void RenderablePolyVoxEntityItem::removeFromScene(EntityItemPointer self, void RenderablePolyVoxEntityItem::removeFromScene(EntityItemPointer self,
std::shared_ptr<render::Scene> scene, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { render::Transaction& transaction) {
pendingChanges.removeItem(_myItem); transaction.removeItem(_myItem);
render::Item::clearID(_myItem); render::Item::clearID(_myItem);
} }
@ -1615,10 +1615,10 @@ void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) {
return; return;
} }
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.updateItem<PolyVoxPayload>(_myItem, [](PolyVoxPayload& payload) {}); transaction.updateItem<PolyVoxPayload>(_myItem, [](PolyVoxPayload& payload) {});
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) { bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) {

View file

@ -107,10 +107,10 @@ public:
virtual bool addToScene(EntityItemPointer self, virtual bool addToScene(EntityItemPointer self,
std::shared_ptr<render::Scene> scene, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) override; render::Transaction& transaction) override;
virtual void removeFromScene(EntityItemPointer self, virtual void removeFromScene(EntityItemPointer self,
std::shared_ptr<render::Scene> scene, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) override; render::Transaction& transaction) override;
virtual void setXNNeighborID(const EntityItemID& xNNeighborID) override; virtual void setXNNeighborID(const EntityItemID& xNNeighborID) override;
virtual void setYNNeighborID(const EntityItemID& yNNeighborID) override; virtual void setYNNeighborID(const EntityItemID& yNNeighborID) override;

View file

@ -266,7 +266,7 @@ void RenderableWebEntityItem::loadSourceURL() {
_webSurface->setMaxFps(DEFAULT_MAX_FPS); _webSurface->setMaxFps(DEFAULT_MAX_FPS);
} }
_webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) { _webSurface->load("WebEntityView.qml", [&](QQmlContext* context, QObject* obj) {
context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject)); context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject));
}); });

View file

@ -118,13 +118,13 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
// check to see if when we added our models to the scene they were ready, if they were not ready, then // check to see if when we added our models to the scene they were ready, if they were not ready, then
// fix them up in the scene // fix them up in the scene
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, transaction);
render::Item::Status::Getters statusGetters; render::Item::Status::Getters statusGetters;
makeEntityItemStatusGetters(getThisPointer(), statusGetters); makeEntityItemStatusGetters(getThisPointer(), statusGetters);
_model->addToScene(scene, pendingChanges); _model->addToScene(scene, transaction);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
_model->setVisibleInScene(getVisible(), scene); _model->setVisibleInScene(getVisible(), scene);
} }
@ -164,9 +164,9 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
_model && !_model->needsFixupInScene()) { _model && !_model->needsFixupInScene()) {
// If the model is in the scene but doesn't need to be, remove it. // If the model is in the scene but doesn't need to be, remove it.
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
render::PendingChanges pendingChanges; render::Transaction transaction;
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, transaction);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
} }
@ -218,7 +218,7 @@ namespace render {
} }
bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { render::Transaction& transaction) {
_myMetaItem = scene->allocateID(); _myMetaItem = scene->allocateID();
auto renderData = std::make_shared<RenderableZoneEntityItemMeta>(self); auto renderData = std::make_shared<RenderableZoneEntityItemMeta>(self);
@ -228,16 +228,16 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt
makeEntityItemStatusGetters(getThisPointer(), statusGetters); makeEntityItemStatusGetters(getThisPointer(), statusGetters);
renderPayload->addStatusGetters(statusGetters); renderPayload->addStatusGetters(statusGetters);
pendingChanges.resetItem(_myMetaItem, renderPayload); transaction.resetItem(_myMetaItem, renderPayload);
return true; return true;
} }
void RenderableZoneEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, void RenderableZoneEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { render::Transaction& transaction) {
pendingChanges.removeItem(_myMetaItem); transaction.removeItem(_myMetaItem);
render::Item::clearID(_myMetaItem); render::Item::clearID(_myMetaItem);
if (_model) { if (_model) {
_model->removeFromScene(scene, pendingChanges); _model->removeFromScene(scene, transaction);
} }
} }
@ -246,13 +246,13 @@ void RenderableZoneEntityItem::notifyBoundChanged() {
if (!render::Item::isValidID(_myMetaItem)) { if (!render::Item::isValidID(_myMetaItem)) {
return; return;
} }
render::PendingChanges pendingChanges; render::Transaction transaction;
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
if (scene) { if (scene) {
pendingChanges.updateItem<RenderableZoneEntityItemMeta>(_myMetaItem, [](RenderableZoneEntityItemMeta& data) { transaction.updateItem<RenderableZoneEntityItemMeta>(_myMetaItem, [](RenderableZoneEntityItemMeta& data) {
}); });
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} else { } else {
qCWarning(entitiesrenderer) << "RenderableZoneEntityItem::notifyBoundChanged(), Unexpected null scene, possibly during application shutdown"; qCWarning(entitiesrenderer) << "RenderableZoneEntityItem::notifyBoundChanged(), Unexpected null scene, possibly during application shutdown";
} }

View file

@ -38,8 +38,8 @@ public:
virtual void render(RenderArgs* args) override; virtual void render(RenderArgs* args) override;
virtual bool contains(const glm::vec3& point) const override; virtual bool contains(const glm::vec3& point) const override;
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override; virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override;
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override; virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::Transaction& transaction) override;
private: private:
virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); } virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); }

View file

@ -53,7 +53,7 @@ using EntityTreeElementExtraEncodeDataPointer = std::shared_ptr<EntityTreeElemen
namespace render { namespace render {
class Scene; class Scene;
class PendingChanges; class Transaction;
} }
#define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0; #define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0;
@ -153,9 +153,9 @@ public:
{ somethingChanged = false; return 0; } { somethingChanged = false; return 0; }
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { return false; } // by default entity items don't add to scene render::Transaction& transaction) { return false; } // by default entity items don't add to scene
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { } // by default entity items don't add to scene render::Transaction& transaction) { } // by default entity items don't add to scene
virtual void render(RenderArgs* args) { } // by default entity items don't know how to render virtual void render(RenderArgs* args) { } // by default entity items don't know how to render
static int expectedBytes(); static int expectedBytes();

View file

@ -114,9 +114,9 @@ AnimDebugDraw::AnimDebugDraw() :
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
if (scene) { if (scene) {
_itemID = scene->allocateID(); _itemID = scene->allocateID();
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.resetItem(_itemID, _animDebugDrawPayload); transaction.resetItem(_itemID, _animDebugDrawPayload);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
// HACK: add red, green and blue axis at (1,1,1) // HACK: add red, green and blue axis at (1,1,1)
@ -142,9 +142,9 @@ void AnimDebugDraw::shutdown() {
// remove renderItem from main 3d scene. // remove renderItem from main 3d scene.
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
if (scene && _itemID) { if (scene && _itemID) {
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.removeItem(_itemID); transaction.removeItem(_itemID);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
} }
@ -317,8 +317,8 @@ void AnimDebugDraw::update() {
return; return;
} }
render::PendingChanges pendingChanges; render::Transaction transaction;
pendingChanges.updateItem<AnimDebugDrawData>(_itemID, [&](AnimDebugDrawData& data) { transaction.updateItem<AnimDebugDrawData>(_itemID, [&](AnimDebugDrawData& data) {
const size_t VERTICES_PER_BONE = (6 + (NUM_CIRCLE_SLICES * 2) * 3); const size_t VERTICES_PER_BONE = (6 + (NUM_CIRCLE_SLICES * 2) * 3);
const size_t VERTICES_PER_LINK = 8 * 2; const size_t VERTICES_PER_LINK = 8 * 2;
@ -422,5 +422,5 @@ void AnimDebugDraw::update() {
data._indexBuffer->setSubData<uint16_t>(i, (uint16_t)i);; data._indexBuffer->setSubData<uint16_t>(i, (uint16_t)i);;
} }
}); });
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }

View file

@ -88,8 +88,9 @@ static const std::string DEFAULT_NORMAL_SHADER {
static const std::string DEFAULT_OCCLUSION_SHADER{ static const std::string DEFAULT_OCCLUSION_SHADER{
"vec4 getFragmentColor() {" "vec4 getFragmentColor() {"
" DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" // " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);"
" return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" // " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);"
" return vec4(vec3(pow(texture(specularMap, uv).a, 1.0 / 2.2)), 1.0);"
" }" " }"
}; };
@ -194,6 +195,18 @@ static const std::string DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER{
" }" " }"
}; };
static const std::string DEFAULT_CURVATURE_OCCLUSION_SHADER{
"vec4 getFragmentColor() {"
" vec4 midNormalCurvature;"
" vec4 lowNormalCurvature;"
" unpackMidLowNormalCurvature(uv, midNormalCurvature, lowNormalCurvature);"
" float ambientOcclusion = curvatureAO(lowNormalCurvature.a * 20.0f) * 0.5f;"
" float ambientOcclusionHF = curvatureAO(midNormalCurvature.a * 8.0f) * 0.5f;"
" ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);"
" return vec4(vec3(ambientOcclusion), 1.0);"
" }"
};
static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{ static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{
"vec4 getFragmentColor() {" "vec4 getFragmentColor() {"
" return vec4(pow(vec3(texture(scatteringMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);" " return vec4(pow(vec3(texture(scatteringMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);"
@ -203,7 +216,7 @@ static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{
static const std::string DEFAULT_AMBIENT_OCCLUSION_SHADER{ static const std::string DEFAULT_AMBIENT_OCCLUSION_SHADER{
"vec4 getFragmentColor() {" "vec4 getFragmentColor() {"
" return vec4(vec3(texture(obscuranceMap, uv).xyz), 1.0);" " return vec4(vec3(texture(obscuranceMap, uv).x), 1.0);"
// When drawing color " return vec4(vec3(texture(occlusionMap, uv).xyz), 1.0);" // When drawing color " return vec4(vec3(texture(occlusionMap, uv).xyz), 1.0);"
// when drawing normal" return vec4(normalize(texture(occlusionMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);" // when drawing normal" return vec4(normalize(texture(occlusionMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);"
" }" " }"
@ -288,6 +301,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust
return DEFAULT_DIFFUSED_CURVATURE_SHADER; return DEFAULT_DIFFUSED_CURVATURE_SHADER;
case DiffusedNormalCurvatureMode: case DiffusedNormalCurvatureMode:
return DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER; return DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER;
case CurvatureOcclusionMode:
return DEFAULT_CURVATURE_OCCLUSION_SHADER;
case ScatteringDebugMode: case ScatteringDebugMode:
return DEFAULT_DEBUG_SCATTERING_SHADER; return DEFAULT_DEBUG_SCATTERING_SHADER;
case AmbientOcclusionMode: case AmbientOcclusionMode:

View file

@ -72,6 +72,7 @@ protected:
NormalCurvatureMode, NormalCurvatureMode,
DiffusedCurvatureMode, DiffusedCurvatureMode,
DiffusedNormalCurvatureMode, DiffusedNormalCurvatureMode,
CurvatureOcclusionMode,
ScatteringDebugMode, ScatteringDebugMode,
AmbientOcclusionMode, AmbientOcclusionMode,
AmbientOcclusionBlurredMode, AmbientOcclusionBlurredMode,

View file

@ -67,10 +67,8 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) {
frag.scattering = 0.0; frag.scattering = 0.0;
unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic); unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic);
//frag.emissive = specularVal.xyz;
frag.obscurance = min(specularVal.w, frag.obscurance); frag.obscurance = min(specularVal.w, frag.obscurance);
if (frag.mode == FRAG_MODE_SCATTERING) { if (frag.mode == FRAG_MODE_SCATTERING) {
frag.scattering = specularVal.x; frag.scattering = specularVal.x;
} }

View file

@ -55,7 +55,7 @@ void DeferredFramebuffer::allocate() {
_deferredColorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); _deferredColorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler));
_deferredNormalTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); _deferredNormalTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler));
_deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler));
_deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture); _deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture);
_deferredFramebuffer->setRenderBuffer(1, _deferredNormalTexture); _deferredFramebuffer->setRenderBuffer(1, _deferredNormalTexture);

View file

@ -62,7 +62,7 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 f
<@if supportScattering@> <@if supportScattering@>
float curvatureAO(in float k) { float curvatureAO(in float k) {
return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369; return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;
} }
<@endif@> <@endif@>
@ -83,13 +83,12 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie
specular = evalAmbientSpecularIrradiance(ambient, eyeDir, normal, roughness) * ambientFresnel; specular = evalAmbientSpecularIrradiance(ambient, eyeDir, normal, roughness) * ambientFresnel;
<@if supportScattering@> <@if supportScattering@>
float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;
float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;
ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);
obscurance = min(obscurance, ambientOcclusion);
if (scattering * isScatteringEnabled() > 0.0) { if (scattering * isScatteringEnabled() > 0.0) {
float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f;
float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f;
ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);
obscurance = min(obscurance, ambientOcclusion);
// Diffuse from ambient // Diffuse from ambient
diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz; diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz;

View file

@ -235,9 +235,9 @@ void Model::updateRenderItems() {
uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; uint32_t deleteGeometryCounter = self->_deleteGeometryCounter;
render::PendingChanges pendingChanges; render::Transaction transaction;
foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) {
pendingChanges.updateItem<ModelMeshPartPayload>(itemID, [deleteGeometryCounter](ModelMeshPartPayload& data) { transaction.updateItem<ModelMeshPartPayload>(itemID, [deleteGeometryCounter](ModelMeshPartPayload& data) {
if (data._model && data._model->isLoaded()) { if (data._model && data._model->isLoaded()) {
// Ensure the model geometry was not reset between frames // Ensure the model geometry was not reset between frames
if (deleteGeometryCounter == data._model->_deleteGeometryCounter) { if (deleteGeometryCounter == data._model->_deleteGeometryCounter) {
@ -259,14 +259,14 @@ void Model::updateRenderItems() {
Transform collisionMeshOffset; Transform collisionMeshOffset;
collisionMeshOffset.setIdentity(); collisionMeshOffset.setIdentity();
Transform modelTransform = self->getTransform(); Transform modelTransform = self->getTransform();
foreach(auto itemID, self->_collisionRenderItemsMap.keys()) { foreach(auto itemID, self->_collisionRenderItemsMap.keys()) {
pendingChanges.updateItem<MeshPartPayload>(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) { transaction.updateItem<MeshPartPayload>(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) {
// update the model transform for this render item. // update the model transform for this render item.
data.updateTransform(modelTransform, collisionMeshOffset); data.updateTransform(modelTransform, collisionMeshOffset);
}); });
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
}); });
} }
@ -538,14 +538,14 @@ void Model::setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scen
if (_isVisible != newValue) { if (_isVisible != newValue) {
_isVisible = newValue; _isVisible = newValue;
render::PendingChanges pendingChanges; render::Transaction transaction;
foreach (auto item, _modelMeshRenderItemsMap.keys()) { foreach (auto item, _modelMeshRenderItemsMap.keys()) {
pendingChanges.resetItem(item, _modelMeshRenderItemsMap[item]); transaction.resetItem(item, _modelMeshRenderItemsMap[item]);
} }
foreach(auto item, _collisionRenderItemsMap.keys()) { foreach(auto item, _collisionRenderItemsMap.keys()) {
pendingChanges.resetItem(item, _collisionRenderItemsMap[item]); transaction.resetItem(item, _collisionRenderItemsMap[item]);
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
} }
@ -554,19 +554,19 @@ void Model::setLayeredInFront(bool layered, std::shared_ptr<render::Scene> scene
if (_isLayeredInFront != layered) { if (_isLayeredInFront != layered) {
_isLayeredInFront = layered; _isLayeredInFront = layered;
render::PendingChanges pendingChanges; render::Transaction transaction;
foreach(auto item, _modelMeshRenderItemsMap.keys()) { foreach(auto item, _modelMeshRenderItemsMap.keys()) {
pendingChanges.resetItem(item, _modelMeshRenderItemsMap[item]); transaction.resetItem(item, _modelMeshRenderItemsMap[item]);
} }
foreach(auto item, _collisionRenderItemsMap.keys()) { foreach(auto item, _collisionRenderItemsMap.keys()) {
pendingChanges.resetItem(item, _collisionRenderItemsMap[item]); transaction.resetItem(item, _collisionRenderItemsMap[item]);
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} }
} }
bool Model::addToScene(std::shared_ptr<render::Scene> scene, bool Model::addToScene(std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges, render::Transaction& transaction,
render::Item::Status::Getters& statusGetters) { render::Item::Status::Getters& statusGetters) {
bool readyToRender = _collisionGeometry || isLoaded(); bool readyToRender = _collisionGeometry || isLoaded();
if (!_addedToScene && readyToRender) { if (!_addedToScene && readyToRender) {
@ -579,11 +579,11 @@ bool Model::addToScene(std::shared_ptr<render::Scene> scene,
foreach (auto renderItem, _collisionRenderItems) { foreach (auto renderItem, _collisionRenderItems) {
auto item = scene->allocateID(); auto item = scene->allocateID();
auto renderPayload = std::make_shared<MeshPartPayload::Payload>(renderItem); auto renderPayload = std::make_shared<MeshPartPayload::Payload>(renderItem);
if (_collisionRenderItems.empty() && statusGetters.size()) { if (_collisionRenderItems.empty() && statusGetters.size()) {
renderPayload->addStatusGetters(statusGetters); renderPayload->addStatusGetters(statusGetters);
} }
pendingChanges.resetItem(item, renderPayload); transaction.resetItem(item, renderPayload);
_collisionRenderItemsMap.insert(item, renderPayload); _collisionRenderItemsMap.insert(item, renderPayload);
} }
somethingAdded = !_collisionRenderItems.empty(); somethingAdded = !_collisionRenderItems.empty();
} }
@ -595,10 +595,10 @@ bool Model::addToScene(std::shared_ptr<render::Scene> scene,
foreach(auto renderItem, _modelMeshRenderItems) { foreach(auto renderItem, _modelMeshRenderItems) {
auto item = scene->allocateID(); auto item = scene->allocateID();
auto renderPayload = std::make_shared<ModelMeshPartPayload::Payload>(renderItem); auto renderPayload = std::make_shared<ModelMeshPartPayload::Payload>(renderItem);
if (_modelMeshRenderItemsMap.empty() && statusGetters.size()) { if (_modelMeshRenderItemsMap.empty() && statusGetters.size()) {
renderPayload->addStatusGetters(statusGetters); renderPayload->addStatusGetters(statusGetters);
} }
pendingChanges.resetItem(item, renderPayload); transaction.resetItem(item, renderPayload);
hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent(); hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent();
verticesCount += renderItem.get()->getVerticesCount(); verticesCount += renderItem.get()->getVerticesCount();
@ -622,16 +622,16 @@ bool Model::addToScene(std::shared_ptr<render::Scene> scene,
return somethingAdded; return somethingAdded;
} }
void Model::removeFromScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { void Model::removeFromScene(std::shared_ptr<render::Scene> scene, render::Transaction& transaction) {
foreach (auto item, _modelMeshRenderItemsMap.keys()) { foreach (auto item, _modelMeshRenderItemsMap.keys()) {
pendingChanges.removeItem(item); transaction.removeItem(item);
} }
_modelMeshRenderItemIDs.clear(); _modelMeshRenderItemIDs.clear();
_modelMeshRenderItemsMap.clear(); _modelMeshRenderItemsMap.clear();
_modelMeshRenderItems.clear(); _modelMeshRenderItems.clear();
foreach(auto item, _collisionRenderItemsMap.keys()) { foreach(auto item, _collisionRenderItemsMap.keys()) {
pendingChanges.removeItem(item); transaction.removeItem(item);
} }
_collisionRenderItems.clear(); _collisionRenderItems.clear();
_collisionRenderItems.clear(); _collisionRenderItems.clear();
@ -794,11 +794,11 @@ void Model::setURL(const QUrl& url) {
_url = url; _url = url;
{ {
render::PendingChanges pendingChanges; render::Transaction transaction;
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
if (scene) { if (scene) {
removeFromScene(scene, pendingChanges); removeFromScene(scene, transaction);
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
} else { } else {
qCWarning(renderutils) << "Model::setURL(), Unexpected null scene, possibly during application shutdown"; qCWarning(renderutils) << "Model::setURL(), Unexpected null scene, possibly during application shutdown";
} }
@ -1279,17 +1279,17 @@ bool Model::initWhenReady(render::ScenePointer scene) {
createRenderItemSet(); createRenderItemSet();
render::PendingChanges pendingChanges; render::Transaction transaction;
bool addedPendingChanges = false; bool addedTransaction = false;
if (_collisionGeometry) { if (_collisionGeometry) {
foreach (auto renderItem, _collisionRenderItems) { foreach (auto renderItem, _collisionRenderItems) {
auto item = scene->allocateID(); auto item = scene->allocateID();
auto renderPayload = std::make_shared<MeshPartPayload::Payload>(renderItem); auto renderPayload = std::make_shared<MeshPartPayload::Payload>(renderItem);
_collisionRenderItemsMap.insert(item, renderPayload); _collisionRenderItemsMap.insert(item, renderPayload);
pendingChanges.resetItem(item, renderPayload); transaction.resetItem(item, renderPayload);
} }
addedPendingChanges = !_collisionRenderItems.empty(); addedTransaction = !_collisionRenderItems.empty();
} else { } else {
bool hasTransparent = false; bool hasTransparent = false;
size_t verticesCount = 0; size_t verticesCount = 0;
@ -1300,17 +1300,17 @@ bool Model::initWhenReady(render::ScenePointer scene) {
hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent(); hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent();
verticesCount += renderItem.get()->getVerticesCount(); verticesCount += renderItem.get()->getVerticesCount();
_modelMeshRenderItemsMap.insert(item, renderPayload); _modelMeshRenderItemsMap.insert(item, renderPayload);
pendingChanges.resetItem(item, renderPayload); transaction.resetItem(item, renderPayload);
} }
addedPendingChanges = !_modelMeshRenderItemsMap.empty(); addedTransaction = !_modelMeshRenderItemsMap.empty();
_renderInfoVertexCount = verticesCount; _renderInfoVertexCount = verticesCount;
_renderInfoDrawCalls = _modelMeshRenderItemsMap.count(); _renderInfoDrawCalls = _modelMeshRenderItemsMap.count();
_renderInfoHasTransparent = hasTransparent; _renderInfoHasTransparent = hasTransparent;
} }
_addedToScene = addedPendingChanges; _addedToScene = addedTransaction;
if (addedPendingChanges) { if (addedTransaction) {
scene->enqueuePendingChanges(pendingChanges); scene->enqueueTransaction(transaction);
// NOTE: updateRender items enqueues identical pendingChanges (using a lambda) // NOTE: updateRender items enqueues identical transaction (using a lambda)
// so it looks like we're doing double work here, but I don't want to remove the call // so it looks like we're doing double work here, but I don't want to remove the call
// for fear there is some side effect we'll miss. -- Andrew 2016.07.21 // for fear there is some side effect we'll miss. -- Andrew 2016.07.21
// TODO: figure out if we really need this call to updateRenderItems() or not. // TODO: figure out if we really need this call to updateRenderItems() or not.

View file

@ -42,7 +42,7 @@ class ViewFrustum;
namespace render { namespace render {
class Scene; class Scene;
class PendingChanges; class Transaction;
typedef unsigned int ItemID; typedef unsigned int ItemID;
} }
class MeshPartPayload; class MeshPartPayload;
@ -88,14 +88,14 @@ public:
bool needsReload() const { return _needsReload; } bool needsReload() const { return _needsReload; }
bool initWhenReady(render::ScenePointer scene); bool initWhenReady(render::ScenePointer scene);
bool addToScene(std::shared_ptr<render::Scene> scene, bool addToScene(std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges) { render::Transaction& transaction) {
auto getters = render::Item::Status::Getters(0); auto getters = render::Item::Status::Getters(0);
return addToScene(scene, pendingChanges, getters); return addToScene(scene, transaction, getters);
} }
bool addToScene(std::shared_ptr<render::Scene> scene, bool addToScene(std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges, render::Transaction& transaction,
render::Item::Status::Getters& statusGetters); render::Item::Status::Getters& statusGetters);
void removeFromScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges); void removeFromScene(std::shared_ptr<render::Scene> scene, render::Transaction& transaction);
bool isRenderable() const; bool isRenderable() const;
bool isVisible() const { return _isVisible; } bool isVisible() const { return _isVisible; }

View file

@ -16,15 +16,20 @@
<@include gpu/Color.slh@> <@include gpu/Color.slh@>
<$declareColorWheel()$> <$declareColorWheel()$>
uniform sampler2D linearDepthMap; uniform sampler2D linearDepthMap;
uniform sampler2D halfLinearDepthMap; uniform sampler2D halfLinearDepthMap;
uniform sampler2D halfNormalMap; uniform sampler2D halfNormalMap;
uniform sampler2D occlusionMap; uniform sampler2D occlusionMap;
uniform sampler2D occlusionBlurredMap; uniform sampler2D occlusionBlurredMap;
uniform sampler2D curvatureMap;
uniform sampler2D diffusedCurvatureMap;
uniform sampler2D scatteringMap; uniform sampler2D scatteringMap;
<$declareDeferredCurvature()$>
float curvatureAO(float k) {
return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f;
}
in vec2 uv; in vec2 uv;
out vec4 outFragColor; out vec4 outFragColor;

View file

@ -16,31 +16,31 @@
using namespace render; using namespace render;
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) { void Transaction::resetItem(ItemID id, const PayloadPointer& payload) {
if (payload) { if (payload) {
_resetItems.push_back(id); _resetItems.push_back(id);
_resetPayloads.push_back(payload); _resetPayloads.push_back(payload);
} else { } else {
qCDebug(renderlogging) << "WARNING: PendingChanges::resetItem with a null payload!"; qCDebug(renderlogging) << "WARNING: Transaction::resetItem with a null payload!";
removeItem(id); removeItem(id);
} }
} }
void PendingChanges::removeItem(ItemID id) { void Transaction::removeItem(ItemID id) {
_removedItems.push_back(id); _removedItems.push_back(id);
} }
void PendingChanges::updateItem(ItemID id, const UpdateFunctorPointer& functor) { void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) {
_updatedItems.push_back(id); _updatedItems.push_back(id);
_updateFunctors.push_back(functor); _updateFunctors.push_back(functor);
} }
void PendingChanges::merge(const PendingChanges& changes) { void Transaction::merge(const Transaction& transaction) {
_resetItems.insert(_resetItems.end(), changes._resetItems.begin(), changes._resetItems.end()); _resetItems.insert(_resetItems.end(), transaction._resetItems.begin(), transaction._resetItems.end());
_resetPayloads.insert(_resetPayloads.end(), changes._resetPayloads.begin(), changes._resetPayloads.end()); _resetPayloads.insert(_resetPayloads.end(), transaction._resetPayloads.begin(), transaction._resetPayloads.end());
_removedItems.insert(_removedItems.end(), changes._removedItems.begin(), changes._removedItems.end()); _removedItems.insert(_removedItems.end(), transaction._removedItems.begin(), transaction._removedItems.end());
_updatedItems.insert(_updatedItems.end(), changes._updatedItems.begin(), changes._updatedItems.end()); _updatedItems.insert(_updatedItems.end(), transaction._updatedItems.begin(), transaction._updatedItems.end());
_updateFunctors.insert(_updateFunctors.end(), changes._updateFunctors.begin(), changes._updateFunctors.end()); _updateFunctors.insert(_updateFunctors.end(), transaction._updateFunctors.begin(), transaction._updateFunctors.end());
} }
Scene::Scene(glm::vec3 origin, float size) : Scene::Scene(glm::vec3 origin, float size) :
@ -63,27 +63,27 @@ bool Scene::isAllocatedID(const ItemID& id) const {
} }
/// Enqueue change batch to the scene /// Enqueue change batch to the scene
void Scene::enqueuePendingChanges(const PendingChanges& pendingChanges) { void Scene::enqueueTransaction(const Transaction& transaction) {
_changeQueueMutex.lock(); _transactionQueueMutex.lock();
_changeQueue.push(pendingChanges); _transactionQueue.push(transaction);
_changeQueueMutex.unlock(); _transactionQueueMutex.unlock();
} }
void consolidateChangeQueue(PendingChangesQueue& queue, PendingChanges& singleBatch) { void consolidateTransaction(TransactionQueue& queue, Transaction& singleBatch) {
while (!queue.empty()) { while (!queue.empty()) {
const auto& pendingChanges = queue.front(); const auto& transaction = queue.front();
singleBatch.merge(pendingChanges); singleBatch.merge(transaction);
queue.pop(); queue.pop();
}; };
} }
void Scene::processPendingChangesQueue() { void Scene::processTransactionQueue() {
PROFILE_RANGE(render, __FUNCTION__); PROFILE_RANGE(render, __FUNCTION__);
PendingChanges consolidatedPendingChanges; Transaction consolidatedTransaction;
{ {
std::unique_lock<std::mutex> lock(_changeQueueMutex); std::unique_lock<std::mutex> lock(_transactionQueueMutex);
consolidateChangeQueue(_changeQueue, consolidatedPendingChanges); consolidateTransaction(_transactionQueue, consolidatedTransaction);
} }
{ {
@ -95,19 +95,19 @@ void Scene::processPendingChangesQueue() {
_items.resize(maxID + 100); // allocate the maxId and more _items.resize(maxID + 100); // allocate the maxId and more
} }
// Now we know for sure that we have enough items in the array to // Now we know for sure that we have enough items in the array to
// capture anything coming from the pendingChanges // capture anything coming from the transaction
// resets and potential NEW items // resets and potential NEW items
resetItems(consolidatedPendingChanges._resetItems, consolidatedPendingChanges._resetPayloads); resetItems(consolidatedTransaction._resetItems, consolidatedTransaction._resetPayloads);
// Update the numItemsAtomic counter AFTER the reset changes went through // Update the numItemsAtomic counter AFTER the reset changes went through
_numAllocatedItems.exchange(maxID); _numAllocatedItems.exchange(maxID);
// updates // updates
updateItems(consolidatedPendingChanges._updatedItems, consolidatedPendingChanges._updateFunctors); updateItems(consolidatedTransaction._updatedItems, consolidatedTransaction._updateFunctors);
// removes // removes
removeItems(consolidatedPendingChanges._removedItems); removeItems(consolidatedTransaction._removedItems);
// Update the numItemsAtomic counter AFTER the pending changes went through // Update the numItemsAtomic counter AFTER the pending changes went through
_numAllocatedItems.exchange(maxID); _numAllocatedItems.exchange(maxID);

View file

@ -19,10 +19,19 @@ namespace render {
class Engine; class Engine;
class PendingChanges { // Transaction is the mechanism to make any change to the scene.
// Whenever a new item need to be reset,
// or when an item changes its position or its size
// or when an item's payload has to be be updated with new states (coming from outside the scene knowledge)
// or when an item is destroyed
// These changes must be expressed through the corresponding command from the Transaction
// THe Transaction is then queued on the Scene so all the pending transactions can be consolidated and processed at the time
// of updating the scene before it s rendered.
//
class Transaction {
public: public:
PendingChanges() {} Transaction() {}
~PendingChanges() {} ~Transaction() {}
void resetItem(ItemID id, const PayloadPointer& payload); void resetItem(ItemID id, const PayloadPointer& payload);
void removeItem(ItemID id); void removeItem(ItemID id);
@ -34,7 +43,7 @@ public:
void updateItem(ItemID id, const UpdateFunctorPointer& functor); void updateItem(ItemID id, const UpdateFunctorPointer& functor);
void updateItem(ItemID id) { updateItem(id, nullptr); } void updateItem(ItemID id) { updateItem(id, nullptr); }
void merge(const PendingChanges& changes); void merge(const Transaction& transaction);
ItemIDs _resetItems; ItemIDs _resetItems;
Payloads _resetPayloads; Payloads _resetPayloads;
@ -44,12 +53,12 @@ public:
protected: protected:
}; };
typedef std::queue<PendingChanges> PendingChangesQueue; typedef std::queue<Transaction> TransactionQueue;
// Scene is a container for Items // Scene is a container for Items
// Items are introduced, modified or erased in the scene through PendingChanges // Items are introduced, modified or erased in the scene through Transaction
// Once per Frame, the PendingChanges are all flushed // Once per Frame, the Transaction are all flushed
// During the flush the standard buckets are updated // During the flush the standard buckets are updated
// Items are notified accordingly on any update message happening // Items are notified accordingly on any update message happening
class Scene { class Scene {
@ -66,11 +75,11 @@ public:
// THis is the total number of allocated items, this a threadsafe call // THis is the total number of allocated items, this a threadsafe call
size_t getNumItems() const { return _numAllocatedItems.load(); } size_t getNumItems() const { return _numAllocatedItems.load(); }
// Enqueue change batch to the scene // Enqueue transaction to the scene
void enqueuePendingChanges(const PendingChanges& pendingChanges); void enqueueTransaction(const Transaction& transaction);
// Process the penging changes equeued // Process the pending transactions queued
void processPendingChangesQueue(); void processTransactionQueue();
// This next call are NOT threadsafe, you have to call them from the correct thread to avoid any potential issues // This next call are NOT threadsafe, you have to call them from the correct thread to avoid any potential issues
@ -91,8 +100,8 @@ protected:
// Thread safe elements that can be accessed from anywhere // Thread safe elements that can be accessed from anywhere
std::atomic<unsigned int> _IDAllocator{ 1 }; // first valid itemID will be One std::atomic<unsigned int> _IDAllocator{ 1 }; // first valid itemID will be One
std::atomic<unsigned int> _numAllocatedItems{ 1 }; // num of allocated items, matching the _items.size() std::atomic<unsigned int> _numAllocatedItems{ 1 }; // num of allocated items, matching the _items.size()
std::mutex _changeQueueMutex; std::mutex _transactionQueueMutex;
PendingChangesQueue _changeQueue; TransactionQueue _transactionQueue;
// The actual database // The actual database
// database of items is protected for editing by a mutex // database of items is protected for editing by a mutex

View file

@ -133,7 +133,8 @@ namespace SceneScripting {
class SceneScriptingInterface : public QObject, public Dependency { class SceneScriptingInterface : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
SINGLETON_DEPENDENCY SINGLETON_DEPENDENCY
public: public:
Q_PROPERTY(bool shouldRenderAvatars READ shouldRenderAvatars WRITE setShouldRenderAvatars) Q_PROPERTY(bool shouldRenderAvatars READ shouldRenderAvatars WRITE setShouldRenderAvatars)
Q_PROPERTY(bool shouldRenderEntities READ shouldRenderEntities WRITE setShouldRenderEntities) Q_PROPERTY(bool shouldRenderEntities READ shouldRenderEntities WRITE setShouldRenderEntities)

View file

@ -179,7 +179,7 @@ void Tracer::serialize(const QString& originalPath) {
{ {
// "traceEvents":[ // "traceEvents":[
// {"args":{"nv_payload":0},"cat":"hifi.render","name":"render::Scene::processPendingChangesQueue","ph":"B","pid":14796,"tid":21636,"ts":68795933487} // {"args":{"nv_payload":0},"cat":"hifi.render","name":"render::Scene::processTransactionQueue","ph":"B","pid":14796,"tid":21636,"ts":68795933487}
QJsonArray traceEvents; QJsonArray traceEvents;

View file

@ -63,7 +63,8 @@ Column {
"Directional:LightingModel:enableDirectionalLight", "Directional:LightingModel:enableDirectionalLight",
"Point:LightingModel:enablePointLight", "Point:LightingModel:enablePointLight",
"Spot:LightingModel:enableSpotLight", "Spot:LightingModel:enableSpotLight",
"Light Contour:LightingModel:showLightContour" "Light Contour:LightingModel:showLightContour",
"Shadow:RenderShadowTask:enabled"
] ]
CheckBox { CheckBox {
text: modelData.split(":")[0] text: modelData.split(":")[0]
@ -150,6 +151,7 @@ Column {
ListElement { text: "Mid Normal"; color: "White" } ListElement { text: "Mid Normal"; color: "White" }
ListElement { text: "Low Curvature"; color: "White" } ListElement { text: "Low Curvature"; color: "White" }
ListElement { text: "Low Normal"; color: "White" } ListElement { text: "Low Normal"; color: "White" }
ListElement { text: "Curvature Occlusion"; color: "White" }
ListElement { text: "Debug Scattering"; color: "White" } ListElement { text: "Debug Scattering"; color: "White" }
ListElement { text: "Ambient Occlusion"; color: "White" } ListElement { text: "Ambient Occlusion"; color: "White" }
ListElement { text: "Ambient Occlusion Blurred"; color: "White" } ListElement { text: "Ambient Occlusion Blurred"; color: "White" }

View file

@ -131,7 +131,6 @@ function request(options, callback) { // cb(error, responseOfCorrectContentType)
var error = (httpRequest.status !== HTTP_OK) && httpRequest.status.toString() + ':' + httpRequest.statusText, var error = (httpRequest.status !== HTTP_OK) && httpRequest.status.toString() + ':' + httpRequest.statusText,
response = !error && httpRequest.responseText, response = !error && httpRequest.responseText,
contentType = !error && httpRequest.getResponseHeader('content-type'); contentType = !error && httpRequest.getResponseHeader('content-type');
debug('FIXME REMOVE: server response', options, error, response, contentType);
if (!error && contentType.indexOf('application/json') === 0) { // ignoring charset, etc. if (!error && contentType.indexOf('application/json') === 0) { // ignoring charset, etc.
try { try {
response = JSON.parse(response); response = JSON.parse(response);
@ -139,6 +138,9 @@ function request(options, callback) { // cb(error, responseOfCorrectContentType)
error = e; error = e;
} }
} }
if (error) {
response = {statusCode: httpRequest.status};
}
callback(error, response); callback(error, response);
} }
}; };
@ -164,7 +166,6 @@ function request(options, callback) { // cb(error, responseOfCorrectContentType)
options.headers["Content-type"] = "application/json"; options.headers["Content-type"] = "application/json";
options.body = JSON.stringify(options.body); options.body = JSON.stringify(options.body);
} }
debug("FIXME REMOVE: final options to send", options);
for (key in options.headers || {}) { for (key in options.headers || {}) {
httpRequest.setRequestHeader(key, options.headers[key]); httpRequest.setRequestHeader(key, options.headers[key]);
} }
@ -574,6 +575,9 @@ function handleConnectionResponseAndMaybeRepeat(error, response) {
} }
} else if (error || (response.status !== 'success')) { } else if (error || (response.status !== 'success')) {
debug('server fail', error, response.status); debug('server fail', error, response.status);
if (response && (response.statusCode === 401)) {
error = "All participants must be logged in to connect.";
}
result = error ? {status: 'error', connection: error} : response; result = error ? {status: 'error', connection: error} : response;
UserActivityLogger.makeUserConnection(connectingId, false, error || response); UserActivityLogger.makeUserConnection(connectingId, false, error || response);
connectionRequestCompleted(); connectionRequestCompleted();
@ -603,6 +607,15 @@ function makeConnection(id) {
// probably, in which we do this. // probably, in which we do this.
Controller.triggerHapticPulse(HAPTIC_DATA.background.strength, MAKING_CONNECTION_TIMEOUT, handToHaptic(currentHand)); Controller.triggerHapticPulse(HAPTIC_DATA.background.strength, MAKING_CONNECTION_TIMEOUT, handToHaptic(currentHand));
requestBody = {node_id: cleanId(MyAvatar.sessionUUID), proposed_node_id: cleanId(id)}; // for use when repeating requestBody = {node_id: cleanId(MyAvatar.sessionUUID), proposed_node_id: cleanId(id)}; // for use when repeating
// It would be "simpler" to skip this and just look at the response, but:
// 1. We don't want to bother the metaverse with request that we know will fail.
// 2. We don't want our code here to be dependent on precisely how the metaverse responds (400, 401, etc.)
if (!Account.isLoggedIn()) {
handleConnectionResponseAndMaybeRepeat("401:Unauthorized", {statusCode: 401});
return;
}
// This will immediately set response if successfull (e.g., the other guy got his request in first), or immediate failure, // This will immediately set response if successfull (e.g., the other guy got his request in first), or immediate failure,
// and will otherwise poll (using the requestBody we just set). // and will otherwise poll (using the requestBody we just set).
request({ // request({ //

View file

@ -427,21 +427,24 @@ function deleteNotification(index) {
arrays.splice(index, 1); arrays.splice(index, 1);
} }
// wraps whole word to newline
function stringDivider(str, slotWidth, spaceReplacer) {
var left, right;
if (str.length > slotWidth && slotWidth > 0) { // Trims extra whitespace and breaks into lines of length no more than MAX_LENGTH, breaking at spaces. Trims extra whitespace.
left = str.substring(0, slotWidth); var MAX_LENGTH = 42;
right = str.substring(slotWidth); function wordWrap(string) {
return left + spaceReplacer + stringDivider(right, slotWidth, spaceReplacer); var finishedLines = [], currentLine = '';
string.split(/\s/).forEach(function (word) {
var tail = currentLine ? ' ' + word : word;
if ((currentLine.length + tail.length) <= MAX_LENGTH) {
currentLine += tail;
} else {
finishedLines.push(currentLine);
currentLine = word;
}
});
if (currentLine) {
finishedLines.push(currentLine);
} }
return str; return finishedLines.join('\n');
}
// formats string to add newline every 43 chars
function wordWrap(str) {
return stringDivider(str, 43.0, "\n");
} }
function update() { function update() {

View file

@ -880,7 +880,7 @@ private:
getEntities()->update(); getEntities()->update();
// The pending changes collecting the changes here // The pending changes collecting the changes here
render::PendingChanges pendingChanges; render::Transaction transaction;
// FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities // FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities
// Background rendering decision // Background rendering decision
@ -888,7 +888,7 @@ private:
auto backgroundRenderData = std::make_shared<BackgroundRenderData>(); auto backgroundRenderData = std::make_shared<BackgroundRenderData>();
auto backgroundRenderPayload = std::make_shared<BackgroundRenderData::Payload>(backgroundRenderData); auto backgroundRenderPayload = std::make_shared<BackgroundRenderData::Payload>(backgroundRenderData);
BackgroundRenderData::_item = _main3DScene->allocateID(); BackgroundRenderData::_item = _main3DScene->allocateID();
pendingChanges.resetItem(BackgroundRenderData::_item, backgroundRenderPayload); transaction.resetItem(BackgroundRenderData::_item, backgroundRenderPayload);
} }
// Setup the current Zone Entity lighting // Setup the current Zone Entity lighting
{ {
@ -897,10 +897,10 @@ private:
} }
{ {
PerformanceTimer perfTimer("SceneProcessPendingChanges"); PerformanceTimer perfTimer("SceneProcessTransaction");
_main3DScene->enqueuePendingChanges(pendingChanges); _main3DScene->enqueueTransaction(transaction);
_main3DScene->processPendingChangesQueue(); _main3DScene->processTransactionQueue();
} }
} }
@ -914,13 +914,13 @@ private:
PROFILE_RANGE(render, __FUNCTION__); PROFILE_RANGE(render, __FUNCTION__);
PerformanceTimer perfTimer("draw"); PerformanceTimer perfTimer("draw");
// The pending changes collecting the changes here // The pending changes collecting the changes here
render::PendingChanges pendingChanges; render::Transaction transaction;
// Setup the current Zone Entity lighting // Setup the current Zone Entity lighting
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(_sunSkyStage.getSunLight()); DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(_sunSkyStage.getSunLight());
{ {
PerformanceTimer perfTimer("SceneProcessPendingChanges"); PerformanceTimer perfTimer("SceneProcessTransaction");
_main3DScene->enqueuePendingChanges(pendingChanges); _main3DScene->enqueueTransaction(transaction);
_main3DScene->processPendingChangesQueue(); _main3DScene->processTransactionQueue();
} }
// For now every frame pass the renderContext // For now every frame pass the renderContext