From 37541e4ed2ce178508db014664139d650e78b324 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 10 Feb 2017 14:29:29 -0800 Subject: [PATCH 001/133] Start capping the time budget for draw opaque --- .../render-utils/src/RenderDeferredTask.cpp | 3 +- libraries/render/src/render/DrawTask.cpp | 105 ++++++++++++++++++ libraries/render/src/render/DrawTask.h | 2 +- 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 55a9c8b9e4..82db502af1 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -295,7 +295,8 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); if (_stateSort) { - renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); + // renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); + renderStateSortShapesCapped(sceneContext, renderContext, _shapePlumber, inItems, 2.0, _maxDrawn); } else { renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 2829c6f8e7..d6f09f735c 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -123,6 +123,111 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons } } + +void render::renderStateSortShapesCapped(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, double mstimeBudget, int maxDrawnItems) { + + auto& scene = sceneContext->_scene; + RenderArgs* args = renderContext->args; + auto now = usecTimestampNow(); + + int numItemsToDraw = (int)inItems.size(); + if (maxDrawnItems != -1) { + numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems); + } + + using SortedPipelines = std::vector; + using SortedShapes = std::unordered_map, render::ShapeKey::Hash, render::ShapeKey::KeyEqual>; + SortedPipelines sortedPipelines; + SortedShapes sortedShapes; + std::vector ownPipelineBucket; + + { + PROFILE_RANGE(render_detail, "sort"); + + for (auto i = 0; i < numItemsToDraw; ++i) { + auto item = scene->getItem(inItems[i].id); + + { + assert(item.getKey().isShape()); + const auto key = item.getShapeKey(); + if (key.isValid() && !key.hasOwnPipeline()) { + auto& bucket = sortedShapes[key]; + if (bucket.empty()) { + sortedPipelines.push_back(key); + } + bucket.push_back(item); + } else if (key.hasOwnPipeline()) { + ownPipelineBucket.push_back(item); + } else { + qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key; + } + } + } + } + + { + PROFILE_RANGE(render_detail, "render"); + + // Then render + quint64 usecHalfBudget = 1000 * 0.5 * mstimeBudget; + quint64 usecBudget = 1000 * mstimeBudget; + + int numDrawCalls = 0; + int numDrawcallsChecks = 128; + int numChecks = 0; + int numChecksBudget = 4; + + for (auto& pipelineKey : sortedPipelines) { + auto& bucket = sortedShapes[pipelineKey]; + args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); + if (!args->_pipeline) { + continue; + } + for (auto& item : bucket) { + item.render(args); + + numDrawCalls++; + if ((numDrawCalls % numDrawcallsChecks) == 0) { + auto newNow = usecTimestampNow(); + if ((newNow - now) > usecHalfBudget) { + if ((newNow - now) > usecBudget) { + return; + } + + usecHalfBudget += (usecHalfBudget / 2); + numDrawcallsChecks / 2; + numChecks++; + if (numChecks > numChecksBudget) { + return; + } + } + } + } + } + args->_pipeline = nullptr; + for (auto& item : ownPipelineBucket) { + item.render(args); + + numDrawCalls++; + if ((numDrawCalls % numDrawcallsChecks) == 0) { + auto newNow = usecTimestampNow(); + if ((newNow - now) > usecHalfBudget) { + if ((newNow - now) > usecBudget) { + return; + } + + usecHalfBudget += (usecHalfBudget / 2); + numDrawcallsChecks / 2; + numChecks++; + if (numChecks > numChecksBudget) { + return; + } + } + } + } + } +} + void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 27f07921c3..042a927caf 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -19,7 +19,7 @@ namespace render { void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); - +void renderStateSortShapesCapped(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, double mstimeBudget, int maxDrawnItems = -1); class DrawLightConfig : public Job::Config { From 9261e81ba2f4004fad6b613e54ee29acaf6ee8ce Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 10 Feb 2017 17:47:56 -0800 Subject: [PATCH 002/133] Cleaning up the interface --- .../render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/RenderDeferredTask.h | 5 ++++- scripts/developer/utilities/render/culling.qml | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 82db502af1..24e284a416 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -296,7 +296,7 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R if (_stateSort) { // renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); - renderStateSortShapesCapped(sceneContext, renderContext, _shapePlumber, inItems, 2.0, _maxDrawn); + renderStateSortShapesCapped(sceneContext, renderContext, _shapePlumber, inItems, _maxTimeBudget, _maxDrawn); } else { renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 8a95447e67..2d9a7d4888 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -85,6 +85,7 @@ class DrawStateSortConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) + Q_PROPERTY(float maxTimeBudget MEMBER maxTimeBudget NOTIFY dirty) Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty) public: @@ -92,6 +93,7 @@ public: void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } int maxDrawn{ -1 }; + float maxTimeBudget { 8.0f }; // 8ms maximum bool stateSort{ true }; signals: @@ -111,12 +113,13 @@ public: DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _maxTimeBudget = config.maxTimeBudget; _stateSort = config.stateSort; } void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: render::ShapePlumberPointer _shapePlumber; int _maxDrawn; // initialized by Config + float _maxTimeBudget; //ms time budget bool _stateSort; }; diff --git a/scripts/developer/utilities/render/culling.qml b/scripts/developer/utilities/render/culling.qml index e3f5e67bbe..4157b5e4dd 100644 --- a/scripts/developer/utilities/render/culling.qml +++ b/scripts/developer/utilities/render/culling.qml @@ -95,6 +95,7 @@ Column { GroupBox { title: "Render Items" + Column{ Column{ Repeater { @@ -110,5 +111,20 @@ Column { } } } + + Column{ + Repeater { + model: [ "Draw Opaque [ms]:DrawOpaqueDeferred" ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: Render.getConfig(modelData.split(":")[1]) + property: "maxTimeBudget" + max: 10.0 + min: 0.0 + } + } + } + } } } From 6302ae6bd5d204b91a5a2773a3cb1d8d738c20b7 Mon Sep 17 00:00:00 2001 From: Menithal Date: Wed, 15 Feb 2017 19:48:29 +0200 Subject: [PATCH 003/133] Changed AudioScope Hotkeys, Allowing User Hotkeys AudioScope Open Hotkey changed from Ctrl + P to Ctrl + Alt + P and Audioscope Pause Hotkey changed from Ctrl + Shift + P to Ctrl + Shift + Alt + P --- interface/src/Menu.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index acf97ad5f7..431fe0638a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -577,7 +577,7 @@ Menu::Menu() { nodeList.data(), SLOT(toggleSendNewerDSConnectVersion(bool))); #endif - + // Developer >> Tests >>> MenuWrapper* testMenu = developerMenu->addMenu("Tests"); addActionToQMenuAndActionHash(testMenu, MenuOption::RunClientScriptTests, 0, dialogsManager.data(), SLOT(showTestingResults())); @@ -628,9 +628,9 @@ Menu::Menu() { auto scope = DependencyManager::get(); MenuWrapper* audioScopeMenu = audioDebugMenu->addMenu("Audio Scope"); - addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScope, Qt::CTRL | Qt::Key_P, false, + addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScope, Qt::CTRL | Qt::ALT | Qt::Key_P, false, scope.data(), SLOT(toggle())); - addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause, Qt::CTRL | Qt::SHIFT | Qt::Key_P, false, + addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause, Qt::CTRL | Qt::ALT | Qt::SHIFT | Qt::Key_P, false, scope.data(), SLOT(togglePause())); addDisabledActionAndSeparator(audioScopeMenu, "Display Frames"); From 7b02d1073a08cca23b904f2c1848b38fe7a9ca5a Mon Sep 17 00:00:00 2001 From: Menithal Date: Wed, 15 Feb 2017 19:49:31 +0200 Subject: [PATCH 004/133] Added a generic Window Notification for Feedback This allows to use the existing Pop-up notifications for generic notification messages --- scripts/system/notifications.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 3ae071c7e3..b2ebb1fd46 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -521,6 +521,9 @@ function onEditError(msg) { createNotification(wordWrap(msg), NotificationType.EDIT_ERROR); } +function onNotify(msg) { + createNotification(wordWrap(msg), NotificationType.UNKNOWN); // Needs a generic notification system for user feedback, thus using this +} function onSnapshotTaken(pathStillSnapshot, pathAnimatedSnapshot, notify) { if (notify) { @@ -637,6 +640,7 @@ Window.domainConnectionRefused.connect(onDomainConnectionRefused); Window.snapshotTaken.connect(onSnapshotTaken); Window.processingGif.connect(processingGif); Window.notifyEditError = onEditError; +Window.notify = onNotify; setup(); From 655c49d9c00f68d8a6f6814d819ceffd1032ce7a Mon Sep 17 00:00:00 2001 From: Menithal Date: Wed, 15 Feb 2017 19:50:15 +0200 Subject: [PATCH 005/133] edit.js: started to work on Parenting via hotkey --- scripts/system/edit.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index da39edf8ba..5476e1208f 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1096,7 +1096,30 @@ function recursiveDelete(entities, childrenList) { Entities.deleteEntity(entityID); } } +function parentSelectedEntities() { + if (SelectionManager.hasSelection()) { + SelectionManager.saveProperties(); + var selectedEntities = selectionManager.selections; + if (selectedEntities.length <= 1) { + Window.notifyEditError("You must have multiple objects selected in order to parent them"); + return; + } + var lastEntityId = selectedEntities[selectedEntities.length] + selectedEntities.some(function (id, index) { + if (lastId === id) { + return false; + } + Entities.editProperties(id, {parentID: lastId}) + return true; + }); + SelectionManager.clearSelections(); + + Window.notify("Entities Parented"); + } else { + Window.notifyEditError("You have nothing selected") + } +} function deleteSelectedEntities() { if (SelectionManager.hasSelection()) { selectedParticleEntity = 0; @@ -1324,6 +1347,8 @@ Controller.keyReleaseEvent.connect(function (event) { }); grid.setPosition(newPosition); } + } else if (event.text === 'p' && event.isCtrl) { + parentSelectedEntities(); } }); From c3021ae60d917bb7c50df1757d07f6e5f46aa25b Mon Sep 17 00:00:00 2001 From: Menithal Date: Wed, 15 Feb 2017 22:21:29 +0200 Subject: [PATCH 006/133] Fixing Menu Items for Parenting / Unparenting --- scripts/system/edit.js | 78 ++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 5476e1208f..afb171e936 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -838,7 +838,6 @@ function setupModelMenus() { }); modelMenuAddedDelete = true; } - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Entity List...", @@ -846,6 +845,23 @@ function setupModelMenus() { afterItem: "Entities", grouping: "Advanced" }); + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Parent Entity to Last", + shortcutKey: "CTRL+P", + afterItem: "Entity List...", + grouping: "Advanced" + }); + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Unparent Entity", + afterItem: "Entity List...", + shortcutKey: "CTRL+SHIFT+P", + afterItem: "Entity List...", + grouping: "Advanced" + }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", @@ -953,6 +969,8 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", "Delete"); } + Menu.removeMenuItem("Edit", "Parent"); + Menu.removeMenuItem("Edit", "Unparent"); Menu.removeMenuItem("Edit", "Entity List..."); Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); @@ -1096,28 +1114,42 @@ function recursiveDelete(entities, childrenList) { Entities.deleteEntity(entityID); } } -function parentSelectedEntities() { +function unparentSelectedEntities() { + print("unparenting2 Selected Entities"); if (SelectionManager.hasSelection()) { - SelectionManager.saveProperties(); var selectedEntities = selectionManager.selections; - if (selectedEntities.length <= 1) { - Window.notifyEditError("You must have multiple objects selected in order to parent them"); - return; - } - - var lastEntityId = selectedEntities[selectedEntities.length] - selectedEntities.some(function (id, index) { - if (lastId === id) { - return false; - } - Entities.editProperties(id, {parentID: lastId}) + selectedEntities.forEach(function (id, index) { + Entities.editEntity(id, {parentID: null}) return true; }); - SelectionManager.clearSelections(); - Window.notify("Entities Parented"); + Window.notify("Entities Unparented"); + } + +} +function parentSelectedEntities() { + print("parenting selected Entities"); + if (SelectionManager.hasSelection()) { + var selectedEntities = selectionManager.selections; + if (selectedEntities.length <= 1) { + Window.notifyEditError("You must have multiple objects selected in order to parent them"); + return; + } + var lastEntityId = selectedEntities[selectedEntities.length-1]; + + print("last " + lastEntityId); + selectedEntities.forEach(function (id, index) { + if (lastEntityId !== id) { + print("iterating2 " + id); + + // OK time to check why this breaks! + Entities.editEntity(id, {parentID: lastEntityId}) + } + }); + + Window.notify("Entities Parented"); } else { - Window.notifyEditError("You have nothing selected") + Window.notifyEditError("You have nothing selected") } } function deleteSelectedEntities() { @@ -1182,6 +1214,10 @@ function handeMenuEvent(menuItem) { Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); } else if (menuItem === "Delete") { deleteSelectedEntities(); + } else if (menuItem === "Parent") { + parentSelectedEntities(); + } else if (menuItem === "Unparent") { + unparentSelectedEntities(); } else if (menuItem === "Export Entities") { if (!selectionManager.hasSelection()) { Window.notifyEditError("No entities have been selected."); @@ -1347,8 +1383,12 @@ Controller.keyReleaseEvent.connect(function (event) { }); grid.setPosition(newPosition); } - } else if (event.text === 'p' && event.isCtrl) { - parentSelectedEntities(); + } else if (event.text === 'p' && event.isControl ) { + if (event.isShifted) { + unparentSelectedEntities(); + } else { + parentSelectedEntities(); + } } }); From 127a014b4694fdbd8dac2d16799249b82d49a203 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Feb 2017 15:21:08 -0800 Subject: [PATCH 007/133] Clear caches on domain switch --- interface/src/Application.cpp | 7 +++++++ libraries/networking/src/ResourceCache.cpp | 6 +++--- libraries/networking/src/ResourceCache.h | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 488e97b5e6..1b83419db7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5152,6 +5152,7 @@ void Application::updateWindowTitle() const { #endif _window->setWindowTitle(title); } + void Application::clearDomainOctreeDetails() { // if we're about to quit, we really don't need to do any of these things... @@ -5181,6 +5182,12 @@ void Application::clearDomainOctreeDetails() { skyStage->setBackgroundMode(model::SunSkyStage::SKY_DEFAULT); _recentlyClearedDomain = true; + + DependencyManager::get()->clearOtherAvatars(); + DependencyManager::get()->clearUnusedResources(); + DependencyManager::get()->clearUnusedResources(); + DependencyManager::get()->clearUnusedResources(); + DependencyManager::get()->clearUnusedResources(); } void Application::domainChanged(const QString& domainHostname) { diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index d95c6f140f..0396e0ed94 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -221,7 +221,7 @@ ResourceCache::ResourceCache(QObject* parent) : QObject(parent) { } ResourceCache::~ResourceCache() { - clearUnusedResource(); + clearUnusedResources(); } void ResourceCache::clearATPAssets() { @@ -265,7 +265,7 @@ void ResourceCache::clearATPAssets() { void ResourceCache::refreshAll() { // Clear all unused resources so we don't have to reload them - clearUnusedResource(); + clearUnusedResources(); resetResourceCounters(); QHash> resources; @@ -418,7 +418,7 @@ void ResourceCache::reserveUnusedResource(qint64 resourceSize) { } } -void ResourceCache::clearUnusedResource() { +void ResourceCache::clearUnusedResources() { // the unused resources may themselves reference resources that will be added to the unused // list on destruction, so keep clearing until there are no references left QWriteLocker locker(&_unusedResourcesLock); diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index a369416ebe..8f1f1baed2 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -249,6 +249,7 @@ public: void refreshAll(); void refresh(const QUrl& url); + void clearUnusedResources(); signals: void dirty(); @@ -298,7 +299,7 @@ protected: void addUnusedResource(const QSharedPointer& resource); void removeUnusedResource(const QSharedPointer& resource); - + /// Attempt to load a resource if requests are below the limit, otherwise queue the resource for loading /// \return true if the resource began loading, otherwise false if the resource is in the pending queue static bool attemptRequest(QSharedPointer resource); @@ -309,7 +310,6 @@ private: friend class Resource; void reserveUnusedResource(qint64 resourceSize); - void clearUnusedResource(); void resetResourceCounters(); void removeResource(const QUrl& url, qint64 size = 0); From ff2c344eaaab3e7e6d121415fb8530277ea46428 Mon Sep 17 00:00:00 2001 From: Menithal Date: Thu, 16 Feb 2017 09:04:58 +0200 Subject: [PATCH 008/133] Migrated Audioscope Hotkeys to use F2 instead of P Apparently ctrl + shift + P which was planned to be used in the client for unparenting entities did not work out, as the command went out of the main view. Migrating to ctrl + F2 and ctrl + alt + F2 --- interface/src/Menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 431fe0638a..3ff5e00c06 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -628,9 +628,9 @@ Menu::Menu() { auto scope = DependencyManager::get(); MenuWrapper* audioScopeMenu = audioDebugMenu->addMenu("Audio Scope"); - addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScope, Qt::CTRL | Qt::ALT | Qt::Key_P, false, + addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScope, Qt::CTRL | Qt::Key_F2, false, scope.data(), SLOT(toggle())); - addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause, Qt::CTRL | Qt::ALT | Qt::SHIFT | Qt::Key_P, false, + addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause, Qt::CTRL | Qt::ALT | Qt::Key_F2, false, scope.data(), SLOT(togglePause())); addDisabledActionAndSeparator(audioScopeMenu, "Display Frames"); From d96f95a7e9b52765137c2c8d1d27eb93f9eba776 Mon Sep 17 00:00:00 2001 From: Menithal Date: Thu, 16 Feb 2017 10:05:59 +0200 Subject: [PATCH 009/133] Updated edit.js and selection tool Last selected entity will now be yellow instead of orange --- scripts/system/edit.js | 8 +------ .../system/libraries/entitySelectionTool.js | 22 +++++++++++-------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index afb171e936..1c76e03efd 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1115,7 +1115,6 @@ function recursiveDelete(entities, childrenList) { } } function unparentSelectedEntities() { - print("unparenting2 Selected Entities"); if (SelectionManager.hasSelection()) { var selectedEntities = selectionManager.selections; selectedEntities.forEach(function (id, index) { @@ -1128,7 +1127,6 @@ function unparentSelectedEntities() { } function parentSelectedEntities() { - print("parenting selected Entities"); if (SelectionManager.hasSelection()) { var selectedEntities = selectionManager.selections; if (selectedEntities.length <= 1) { @@ -1137,16 +1135,12 @@ function parentSelectedEntities() { } var lastEntityId = selectedEntities[selectedEntities.length-1]; - print("last " + lastEntityId); selectedEntities.forEach(function (id, index) { if (lastEntityId !== id) { - print("iterating2 " + id); - // OK time to check why this breaks! Entities.editEntity(id, {parentID: lastEntityId}) } }); - Window.notify("Entities Parented"); } else { Window.notifyEditError("You have nothing selected") @@ -1384,7 +1378,7 @@ Controller.keyReleaseEvent.connect(function (event) { grid.setPosition(newPosition); } } else if (event.text === 'p' && event.isControl ) { - if (event.isShifted) { + if (event.isAlt) { unparentSelectedEntities(); } else { parentSelectedEntities(); diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index b9bae72d14..146dc1894b 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1170,14 +1170,14 @@ SelectionDisplay = (function() { // determine which bottom corner we are closest to /*------------------------------ example: - + BRF +--------+ BLF | | | | BRN +--------+ BLN - + * - + ------------------------------*/ var cameraPosition = Camera.getPosition(); @@ -2189,8 +2189,12 @@ SelectionDisplay = (function() { offset = Vec3.multiplyQbyV(properties.rotation, offset); var boxPosition = Vec3.sum(properties.position, offset); + var color = {red: 255, green: 153, blue: 0}; + if (i >= selectionManager.selections.length - 1) color = {red: 255, green: 255, blue: 0}; + Overlays.editOverlay(selectionBoxes[i], { position: boxPosition, + color: color, rotation: properties.rotation, dimensions: properties.dimensions, visible: true, @@ -2395,7 +2399,7 @@ SelectionDisplay = (function() { if (wantDebug) { print("Start Elevation: " + translateXZTool.startingElevation + ", elevation: " + elevation); } - if ((translateXZTool.startingElevation > 0.0 && elevation < MIN_ELEVATION) || + if ((translateXZTool.startingElevation > 0.0 && elevation < MIN_ELEVATION) || (translateXZTool.startingElevation < 0.0 && elevation > -MIN_ELEVATION)) { if (wantDebug) { print("too close to horizon!"); @@ -3857,7 +3861,7 @@ SelectionDisplay = (function() { }; that.mousePressEvent = function(event) { - var wantDebug = false; + var wantDebug = false; if (!event.isLeftButton && !that.triggered) { // if another mouse button than left is pressed ignore it return false; @@ -3883,7 +3887,7 @@ SelectionDisplay = (function() { if (result.intersects) { - + if (wantDebug) { print("something intersects... "); print(" result.overlayID:" + result.overlayID + "[" + overlayNames[result.overlayID] + "]"); @@ -3983,7 +3987,7 @@ SelectionDisplay = (function() { if (wantDebug) { print("rotate handle case..."); } - + // After testing our stretch handles, then check out rotate handles Overlays.editOverlay(yawHandle, { @@ -4205,7 +4209,7 @@ SelectionDisplay = (function() { case selectionBox: activeTool = translateXZTool; translateXZTool.pickPlanePosition = result.intersection; - translateXZTool.greatestDimension = Math.max(Math.max(SelectionManager.worldDimensions.x, SelectionManager.worldDimensions.y), + translateXZTool.greatestDimension = Math.max(Math.max(SelectionManager.worldDimensions.x, SelectionManager.worldDimensions.y), SelectionManager.worldDimensions.z); if (wantDebug) { print("longest dimension: " + translateXZTool.greatestDimension); @@ -4214,7 +4218,7 @@ SelectionDisplay = (function() { translateXZTool.startingElevation = translateXZTool.elevation(pickRay.origin, translateXZTool.pickPlanePosition); print(" starting elevation: " + translateXZTool.startingElevation); } - + mode = translateXZTool.mode; activeTool.onBegin(event); somethingClicked = 'selectionBox'; From 7a5665ff4f2370f1cae6b018cb2568cd07a3aa59 Mon Sep 17 00:00:00 2001 From: Menithal Date: Thu, 16 Feb 2017 10:09:19 +0200 Subject: [PATCH 010/133] Hotkey change to make AudioScope similar to earlier --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3ff5e00c06..c131367aee 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -630,7 +630,7 @@ Menu::Menu() { MenuWrapper* audioScopeMenu = audioDebugMenu->addMenu("Audio Scope"); addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScope, Qt::CTRL | Qt::Key_F2, false, scope.data(), SLOT(toggle())); - addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause, Qt::CTRL | Qt::ALT | Qt::Key_F2, false, + addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause, Qt::CTRL | Qt::SHIFT | Qt::Key_F2, false, scope.data(), SLOT(togglePause())); addDisabledActionAndSeparator(audioScopeMenu, "Display Frames"); From afbf4bc30f53cd63efc2df1ab5ebfa14de7ec65d Mon Sep 17 00:00:00 2001 From: Menithal Date: Thu, 16 Feb 2017 10:52:42 +0200 Subject: [PATCH 011/133] Fixed Parenting/Unparenting Menu Removal and Binding --- scripts/system/edit.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 1c76e03efd..b83ca9a896 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -969,8 +969,8 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", "Delete"); } - Menu.removeMenuItem("Edit", "Parent"); - Menu.removeMenuItem("Edit", "Unparent"); + Menu.removeMenuItem("Edit", "Parent Entity to Last"); + Menu.removeMenuItem("Edit", "Unparent Entity"); Menu.removeMenuItem("Edit", "Entity List..."); Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); @@ -1134,10 +1134,8 @@ function parentSelectedEntities() { return; } var lastEntityId = selectedEntities[selectedEntities.length-1]; - selectedEntities.forEach(function (id, index) { if (lastEntityId !== id) { - // OK time to check why this breaks! Entities.editEntity(id, {parentID: lastEntityId}) } }); @@ -1208,9 +1206,9 @@ function handeMenuEvent(menuItem) { Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); } else if (menuItem === "Delete") { deleteSelectedEntities(); - } else if (menuItem === "Parent") { + } else if (menuItem === "Parent Entity to Last") { parentSelectedEntities(); - } else if (menuItem === "Unparent") { + } else if (menuItem === "Unparent Entity") { unparentSelectedEntities(); } else if (menuItem === "Export Entities") { if (!selectionManager.hasSelection()) { @@ -1378,7 +1376,7 @@ Controller.keyReleaseEvent.connect(function (event) { grid.setPosition(newPosition); } } else if (event.text === 'p' && event.isControl ) { - if (event.isAlt) { + if (event.isShifted) { unparentSelectedEntities(); } else { parentSelectedEntities(); From 51246a2e45ece2e60e11b97f388101de55a38800 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 17 Feb 2017 10:24:01 -0700 Subject: [PATCH 012/133] first cut, pretty ugly --- interface/resources/qml/hifi/NameCard.qml | 5 +- interface/resources/qml/hifi/Pal.qml | 42 +++++++++++---- scripts/system/pal.js | 66 +++++++++++++---------- 3 files changed, 73 insertions(+), 40 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index b55b9c517d..5eb6e6b8b1 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -31,6 +31,7 @@ Item { property real displayNameTextPixelSize: 18 property int usernameTextHeight: 12 property real audioLevel: 0.0 + property real avgAudioLevel: 0.0 property bool isMyCard: false property bool selected: false property bool isAdmin: false @@ -335,7 +336,7 @@ Item { } } - // Per-Avatar Gain Slider + // Per-Avatar Gain Slider Slider { id: gainSlider // Size @@ -369,7 +370,7 @@ Item { mouse.accepted = false } onReleased: { - // the above mouse.accepted seems to make this + // the above mouse.accepted seems to make this // never get called, nonetheless... mouse.accepted = false } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index c1fea7c09b..0d1da1eed5 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -2,7 +2,7 @@ // Pal.qml // qml/hifi // -// People Action List +// People Action List // // Created by Howard Stearns on 12/12/2016 // Copyright 2016 High Fidelity, Inc. @@ -29,8 +29,8 @@ Rectangle { property int myCardHeight: 90 property int rowHeight: 70 property int actionButtonWidth: 55 - property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 4 : 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth - property var myData: ({displayName: "", userName: "", audioLevel: 0.0, admin: true}) // valid dummy until set + property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 5 : 3) - 4 - hifi.dimensions.scrollbarBackgroundWidth + property var myData: ({displayName: "", userName: "", audioLevel: 0.0, avgAudioLevel: 0.0, admin: true}) // valid dummy until set property var ignored: ({}); // Keep a local list of ignored avatars & their data. Necessary because HashMap is slow to respond after ignoring. property var userModelData: [] // This simple list is essentially a mirror of the userModel listModel without all the extra complexities. property bool iAmAdmin: false @@ -86,6 +86,7 @@ Rectangle { displayName: myData.displayName userName: myData.userName audioLevel: myData.audioLevel + avgAudioLevel: myData.avgAudioLevel isMyCard: true // Size width: nameCardWidth @@ -184,6 +185,13 @@ Rectangle { movable: false resizable: false } + TableViewColumn { + role: "avgAudioLevel" + title: "VOL" + width: actionButtonWidth + movable: false + resizable: false + } TableViewColumn { visible: iAmAdmin role: "mute" @@ -218,6 +226,7 @@ Rectangle { id: itemCell property bool isCheckBox: styleData.role === "personalMute" || styleData.role === "ignore" property bool isButton: styleData.role === "mute" || styleData.role === "kick" + property bool isText: styleData.role == "avgAudioLevel" // This NameCard refers to the cell that contains an avatar's // DisplayName and UserName NameCard { @@ -226,7 +235,8 @@ Rectangle { displayName: styleData.value userName: model ? model.userName : "" audioLevel: model ? model.audioLevel : 0.0 - visible: !isCheckBox && !isButton + avgAudioLevel: model ? model.avgAudioLevel : 0.0 + visible: !isCheckBox && !isButton && !isText uuid: model ? model.sessionId : "" selected: styleData.selected isAdmin: model && model.admin @@ -236,7 +246,16 @@ Rectangle { // Anchors anchors.left: parent.left } - + Text { + id: avgAudioVolume + text: model ? model.avgAudioLevel : 0.0 + visible: isText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + width: parent.width + height: parent.height + } + // This CheckBox belongs in the columns that contain the stateful action buttons ("Mute" & "Ignore" for now) // KNOWN BUG with the Checkboxes: When clicking in the center of the sorting header, the checkbox // will appear in the "hovered" state. Hovering over the checkbox will fix it. @@ -272,7 +291,7 @@ Rectangle { checked = Qt.binding(function() { return (model[styleData.role])}) } } - + // This Button belongs in the columns that contain the stateless action buttons ("Silence" & "Ban" for now) HifiControls.Button { id: actionButton @@ -542,23 +561,28 @@ Rectangle { } } break; - case 'updateAudioLevel': + case 'updateAudioLevel': for (var userId in message.params) { - var audioLevel = message.params[userId]; + var audioLevel = message.params[userId][0]; + var avgAudioLevel = message.params[userId][1]; // If the userId is 0, we're updating "myData". if (userId == 0) { myData.audioLevel = audioLevel; myCard.audioLevel = audioLevel; // Defensive programming + myData.avgAudioLevel = avgAudioLevel; + myCard.avgAudioLevel = avgAudioLevel; } else { var userIndex = findSessionIndex(userId); if (userIndex != -1) { userModel.setProperty(userIndex, "audioLevel", audioLevel); userModelData[userIndex].audioLevel = audioLevel; // Defensive programming + userModel.setProperty(userIndex, "avgAudioLevel", avgAudioLevel); + userModelData[userIndex].avgAudioLevel = avgAudioLevel; } } } break; - case 'clearLocalQMLData': + case 'clearLocalQMLData': ignored = {}; gainSliderValueDB = {}; break; diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 57648da79a..b5d7c3885d 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -13,7 +13,7 @@ (function() { // BEGIN LOCAL_SCOPE -// hardcoding these as it appears we cannot traverse the originalTextures in overlays??? Maybe I've missed +// hardcoding these as it appears we cannot traverse the originalTextures in overlays??? Maybe I've missed // something, will revisit as this is sorta horrible. const UNSELECTED_TEXTURES = {"idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png"), "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png") @@ -87,7 +87,7 @@ ExtendedOverlay.prototype.hover = function (hovering) { } else { lastHoveringId = 0; } - } + } this.editOverlay({color: color(this.selected, hovering, this.audioLevel)}); if (this.model) { this.model.editOverlay({textures: textures(this.selected, hovering)}); @@ -104,7 +104,7 @@ ExtendedOverlay.prototype.select = function (selected) { if (this.selected === selected) { return; } - + UserActivityLogger.palAction(selected ? "avatar_selected" : "avatar_deselected", this.key); this.editOverlay({color: color(selected, this.hovering, this.audioLevel)}); @@ -273,7 +273,7 @@ function sendToQml(message) { // function addAvatarNode(id) { var selected = ExtendedOverlay.isSelected(id); - return new ExtendedOverlay(id, "sphere", { + return new ExtendedOverlay(id, "sphere", { drawInFront: true, solid: true, alpha: 0.8, @@ -290,6 +290,7 @@ function populateUserList(selectData) { userName: '', sessionId: id || '', audioLevel: 0.0, + avgAudioLevel: 0.0, admin: false, personalMute: !!id && Users.getPersonalMuteStatus(id), // expects proper boolean, not null ignore: !!id && Users.getIgnoreStatus(id) // ditto @@ -341,7 +342,7 @@ function updateOverlays() { var target = avatar.position; var distance = Vec3.distance(target, eye); var offset = 0.2; - + // base offset on 1/2 distance from hips to head if we can var headIndex = avatar.getJointIndex("Head"); if (headIndex > 0) { @@ -350,7 +351,7 @@ function updateOverlays() { // get diff between target and eye (a vector pointing to the eye from avatar position) var diff = Vec3.subtract(target, eye); - + // move a bit in front, towards the camera target = Vec3.subtract(target, Vec3.multiply(Vec3.normalize(diff), offset)); @@ -361,12 +362,12 @@ function updateOverlays() { overlay.editOverlay({ color: color(ExtendedOverlay.isSelected(id), overlay.hovering, overlay.audioLevel), position: target, - dimensions: 0.032 * distance + dimensions: 0.032 * distance }); if (overlay.model) { overlay.model.ping = pingPong; overlay.model.editOverlay({ - position: target, + position: target, scale: 0.2 * distance, // constant apparent size rotation: Camera.orientation }); @@ -433,7 +434,7 @@ function handleMouseMoveEvent(event) { // find out which overlay (if any) is ove handleMouseMove(pickRay); } function handleTriggerPressed(hand, value) { - // The idea is if you press one trigger, it is the one + // The idea is if you press one trigger, it is the one // we will consider the mouse. Even if the other is pressed, // we ignore it until this one is no longer pressed. isPressed = value > TRIGGER_PRESS_THRESHOLD; @@ -441,10 +442,10 @@ function handleTriggerPressed(hand, value) { currentHandPressed = isPressed ? hand : 0; return; } - if (currentHandPressed == hand) { + if (currentHandPressed == hand) { currentHandPressed = isPressed ? hand : 0; return; - } + } // otherwise, the other hand is still triggered // so do nothing. } @@ -574,41 +575,48 @@ function receiveMessage(channel, messageString, senderID) { Messages.subscribe(CHANNEL); Messages.messageReceived.connect(receiveMessage); - var AVERAGING_RATIO = 0.05; +var LONG_AVERAGING_RATIO = 0.75; var LOUDNESS_FLOOR = 11.0; var LOUDNESS_SCALE = 2.8 / 5.0; var LOG2 = Math.log(2.0); var myData = {}; // we're not includied in ExtendedOverlay.get. +function scaleAudio(val) { + var audioLevel = 0.0; + if (val <= LOUDNESS_FLOOR) { + audioLevel = val / LOUDNESS_FLOOR * LOUDNESS_SCALE; + } else { + audioLevel = (val -(LOUDNESS_FLOOR -1 )) * LOUDNESS_SCALE; + } + if (audioLevel > 1.0) { + audioLevel = 1; + } + return audioLevel; +} function getAudioLevel(id) { // the VU meter should work similarly to the one in AvatarInputs: log scale, exponentially averaged // But of course it gets the data at a different rate, so we tweak the averaging ratio and frequency // of updating (the latter for efficiency too). var avatar = AvatarList.getAvatar(id); var audioLevel = 0.0; + var avgAudioLevel = 0.0; var data = id ? ExtendedOverlay.get(id) : myData; - if (!data) { - return audioLevel; - } + if (data) { - // we will do exponential moving average by taking some the last loudness and averaging - data.accumulatedLevel = AVERAGING_RATIO * (data.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatar.audioLoudness); + // we will do exponential moving average by taking some the last loudness and averaging + data.accumulatedLevel = AVERAGING_RATIO * (data.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatar.audioLoudness); + data.longAccumulatedLevel = LONG_AVERAGING_RATIO * (data.longAccumulatedLevel || 0) + (1 - LONG_AVERAGING_RATIO) * (avatar.audioLoudness); - // add 1 to insure we don't go log() and hit -infinity. Math.log is - // natural log, so to get log base 2, just divide by ln(2). - var logLevel = Math.log(data.accumulatedLevel + 1) / LOG2; + // add 1 to insure we don't go log() and hit -infinity. Math.log is + // natural log, so to get log base 2, just divide by ln(2). + audioLevel = scaleAudio(Math.log(data.accumulatedLevel + 1) / LOG2); + avgAudioLevel = scaleAudio(Math.log(data.longAccumulatedLevel + 1) / LOG2); - if (logLevel <= LOUDNESS_FLOOR) { - audioLevel = logLevel / LOUDNESS_FLOOR * LOUDNESS_SCALE; - } else { - audioLevel = (logLevel - (LOUDNESS_FLOOR - 1.0)) * LOUDNESS_SCALE; + data.audioLevel = audioLevel; + data.averageAudioLevel = avgAudioLevel; } - if (audioLevel > 1.0) { - audioLevel = 1; - } - data.audioLevel = audioLevel; - return audioLevel; + return [audioLevel, avgAudioLevel]; } function createAudioInterval(interval) { From d938c70b486c26e9bff3c7dd78a1c9a86586098a Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 17 Feb 2017 11:11:08 -0700 Subject: [PATCH 013/133] volume goes 0-9 now --- interface/resources/qml/hifi/Pal.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 0d1da1eed5..e0f2df76ce 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -248,7 +248,7 @@ Rectangle { } Text { id: avgAudioVolume - text: model ? model.avgAudioLevel : 0.0 + text: model ? (10 * model.avgAudioLevel).toFixed(0) : 0.0 visible: isText horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter From f5d266a56253703e35a8baf78159479ccac22ac7 Mon Sep 17 00:00:00 2001 From: Menithal Date: Fri, 17 Feb 2017 23:28:28 +0200 Subject: [PATCH 014/133] Updated --- scripts/system/edit.js | 26 ++++++++++++------- scripts/system/html/entityList.html | 3 +++ scripts/system/html/entityProperties.html | 3 ++- scripts/system/html/js/parentingHotkey.js | 12 +++++++++ .../system/libraries/entitySelectionTool.js | 4 +-- 5 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 scripts/system/html/js/parentingHotkey.js diff --git a/scripts/system/edit.js b/scripts/system/edit.js index b83ca9a896..d759760893 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -859,7 +859,6 @@ function setupModelMenus() { menuItemName: "Unparent Entity", afterItem: "Entity List...", shortcutKey: "CTRL+SHIFT+P", - afterItem: "Entity List...", grouping: "Advanced" }); Menu.addMenuItem({ @@ -1003,6 +1002,9 @@ Script.scriptEnding.connect(function () { Overlays.deleteOverlay(importingSVOImageOverlay); Overlays.deleteOverlay(importingSVOTextOverlay); + + Controller.keyReleaseEvent.disconnect(keyReleaseEvent); + Controller.keyPressEvent.disconnect(keyPressEvent); }); var lastOrientation = null; @@ -1121,10 +1123,8 @@ function unparentSelectedEntities() { Entities.editEntity(id, {parentID: null}) return true; }); - Window.notify("Entities Unparented"); } - } function parentSelectedEntities() { if (SelectionManager.hasSelection()) { @@ -1335,13 +1335,12 @@ Window.svoImportRequested.connect(importSVO); Menu.menuItemEvent.connect(handeMenuEvent); -Controller.keyPressEvent.connect(function (event) { +var keyPressEvent = function (event) { if (isActive) { cameraManager.keyPressEvent(event); } -}); - -Controller.keyReleaseEvent.connect(function (event) { +}; +var keyReleaseEvent = function (event) { if (isActive) { cameraManager.keyReleaseEvent(event); } @@ -1375,14 +1374,16 @@ Controller.keyReleaseEvent.connect(function (event) { }); grid.setPosition(newPosition); } - } else if (event.text === 'p' && event.isControl ) { + } else if (event.text === 'p' && event.isControl && !event.isAutoRepeat ) { if (event.isShifted) { unparentSelectedEntities(); } else { parentSelectedEntities(); } } -}); +}; +Controller.keyReleaseEvent.connect(keyReleaseEvent); +Controller.keyPressEvent.connect(keyPressEvent); function recursiveAdd(newParentID, parentData) { var children = parentData.children; @@ -1632,6 +1633,10 @@ var PropertiesTool = function (opts) { } pushCommandForSelections(); selectionManager._update(); + } else if(data.type === 'parent') { + parentSelectedEntities(); + } else if(data.type === 'unparent') { + unparentSelectedEntities(); } else if(data.type === 'saveUserData'){ //the event bridge and json parsing handle our avatar id string differently. var actualID = data.id.split('"')[1]; @@ -1889,6 +1894,9 @@ var PopupMenu = function () { for (var i = 0; i < overlays.length; i++) { Overlays.deleteOverlay(overlays[i]); } + Controller.mousePressEvent.disconnect(self.mousePressEvent); + Controller.mouseMoveEvent.disconnect(self.mouseMoveEvent); + Controller.mouseReleaseEvent.disconnect(self.mouseReleaseEvent); } Controller.mousePressEvent.connect(self.mousePressEvent); diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index 197d8f550a..67d1973fa7 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -16,6 +16,7 @@ +
@@ -89,6 +90,8 @@ + +
No entities found in view within a 100 meter radius. Try moving to a different location and refreshing.
diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index b11127b26c..84c8a15dd3 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -22,6 +22,7 @@ +
@@ -61,7 +62,7 @@
- +

diff --git a/scripts/system/html/js/parentingHotkey.js b/scripts/system/html/js/parentingHotkey.js new file mode 100644 index 0000000000..c17dae01fe --- /dev/null +++ b/scripts/system/html/js/parentingHotkey.js @@ -0,0 +1,12 @@ +var keyReleaseEvent = function (event) { + if (event.text === 'p' && event.isControl && !event.isAutoRepeat ) { + if (event.isShifted) { + EventBridge.emitWebEvent(JSON.stringify({ type: 'unparent' })); + } else { + EventBridge.emitWebEvent(JSON.stringify({ type: 'parent' })); + } + } +}; + +window.onkeypress = keyReleaseEvent; +Controller.keyReleaseEvent.connect(keyReleaseEvent); diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 146dc1894b..13f61dfd80 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -2189,8 +2189,8 @@ SelectionDisplay = (function() { offset = Vec3.multiplyQbyV(properties.rotation, offset); var boxPosition = Vec3.sum(properties.position, offset); - var color = {red: 255, green: 153, blue: 0}; - if (i >= selectionManager.selections.length - 1) color = {red: 255, green: 255, blue: 0}; + var color = {red: 255, green: 128, blue: 0}; + if (i >= selectionManager.selections.length - 1) color = {red: 255, green: 255, blue: 64}; Overlays.editOverlay(selectionBoxes[i], { position: boxPosition, From dcbe3c622db92d2e5729813392a9c483c5ae1c22 Mon Sep 17 00:00:00 2001 From: Menithal Date: Sat, 18 Feb 2017 11:51:19 +0200 Subject: [PATCH 015/133] Added Hotkey Listening to the webview Ctrl + P and Ctrl + Shift + P are now available even if the edit window has been selected --- scripts/system/edit.js | 13 +++---- scripts/system/html/entityList.html | 2 - scripts/system/html/entityProperties.html | 1 - scripts/system/html/js/entityList.js | 44 ++++++++++++---------- scripts/system/html/js/entityProperties.js | 16 ++++++-- scripts/system/html/js/gridControls.js | 11 +++++- scripts/system/html/js/parentingHotkey.js | 12 ------ 7 files changed, 52 insertions(+), 47 deletions(-) delete mode 100644 scripts/system/html/js/parentingHotkey.js diff --git a/scripts/system/edit.js b/scripts/system/edit.js index d759760893..d0236ce993 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1374,12 +1374,6 @@ var keyReleaseEvent = function (event) { }); grid.setPosition(newPosition); } - } else if (event.text === 'p' && event.isControl && !event.isAutoRepeat ) { - if (event.isShifted) { - unparentSelectedEntities(); - } else { - parentSelectedEntities(); - } } }; Controller.keyReleaseEvent.connect(keyReleaseEvent); @@ -1586,6 +1580,7 @@ var PropertiesTool = function (opts) { print('Edit.js received web event that was not valid json.') return; } + print(JSON.stringify(data)) var i, properties, dY, diff, newPosition; if (data.type === "print") { if (data.message) { @@ -1924,7 +1919,11 @@ var particleExplorerTool = new ParticleExplorerTool(); var selectedParticleEntity = 0; entityListTool.webView.webEventReceived.connect(function (data) { data = JSON.parse(data); - if (data.type === "selectionUpdate") { + if(data.type === 'parent') { + parentSelectedEntities(); + } else if(data.type === 'unparent') { + unparentSelectedEntities(); + } else if (data.type === "selectionUpdate") { var ids = data.entityIds; if (ids.length === 1) { if (Entities.getEntityProperties(ids[0], "type").type === "ParticleEffect") { diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index 67d1973fa7..3cb79353f9 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -16,7 +16,6 @@ -
@@ -91,7 +90,6 @@ -
No entities found in view within a 100 meter radius. Try moving to a different location and refreshing.
diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 84c8a15dd3..cc73d71517 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -22,7 +22,6 @@ -
diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 1af9c1e1d6..53d2d9030b 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -26,7 +26,7 @@ debugPrint = function (message) { }; function loaded() { - openEventBridge(function() { + openEventBridge(function() { entityList = new List('entity-list', { valueNames: ['name', 'type', 'url', 'locked', 'visible'], page: MAX_ITEMS}); entityList.clear(); elEntityTable = document.getElementById("entity-table"); @@ -48,7 +48,7 @@ function loaded() { elNoEntitiesInView = document.getElementById("no-entities-in-view"); elNoEntitiesRadius = document.getElementById("no-entities-radius"); elEntityTableScroll = document.getElementById("entity-table-scroll"); - + document.getElementById("entity-name").onclick = function() { setSortColumn('name'); }; @@ -90,7 +90,7 @@ function loaded() { selection = selection.concat(selectedEntities); } else if (clickEvent.shiftKey && selectedEntities.length > 0) { var previousItemFound = -1; - var clickedItemFound = -1; + var clickedItemFound = -1; for (var entity in entityList.visibleItems) { if (clickedItemFound === -1 && this.dataset.entityId == entityList.visibleItems[entity].values().id) { clickedItemFound = entity; @@ -113,11 +113,11 @@ function loaded() { selection = selection.concat(betweenItems, selectedEntities); } } - + selectedEntities = selection; - + this.className = 'selected'; - + EventBridge.emitWebEvent(JSON.stringify({ type: "selectionUpdate", focus: false, @@ -126,7 +126,7 @@ function loaded() { refreshFooter(); } - + function onRowDoubleClicked() { EventBridge.emitWebEvent(JSON.stringify({ type: "selectionUpdate", @@ -134,7 +134,7 @@ function loaded() { entityIds: [this.dataset.entityId], })); } - + const BYTES_PER_MEGABYTE = 1024 * 1024; function decimalMegabytes(number) { @@ -173,7 +173,7 @@ function loaded() { currentElement.onclick = onRowClicked; currentElement.ondblclick = onRowDoubleClicked; }); - + if (refreshEntityListTimer) { clearTimeout(refreshEntityListTimer); } @@ -183,13 +183,13 @@ function loaded() { item.values({ name: name, url: filename, locked: locked, visible: visible }); } } - + function clearEntities() { entities = {}; entityList.clear(); refreshFooter(); } - + var elSortOrder = { name: document.querySelector('#entity-name .sort-order'), type: document.querySelector('#entity-type .sort-order'), @@ -215,12 +215,12 @@ function loaded() { entityList.sort(currentSortColumn, { order: currentSortOrder }); } setSortColumn('type'); - + function refreshEntities() { clearEntities(); EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' })); } - + function refreshFooter() { if (selectedEntities.length > 1) { elFooter.firstChild.nodeValue = selectedEntities.length + " entities selected"; @@ -239,7 +239,7 @@ function loaded() { entityList.search(elFilter.value); refreshFooter(); } - + function updateSelectedEntities(selectedIDs) { var notFound = false; for (var id in entities) { @@ -262,7 +262,7 @@ function loaded() { return notFound; } - + elRefresh.onclick = function() { refreshEntities(); } @@ -282,7 +282,7 @@ function loaded() { EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' })); refreshEntities(); } - + document.addEventListener("keydown", function (keyDownEvent) { if (keyDownEvent.target.nodeName === "INPUT") { return; @@ -292,8 +292,15 @@ function loaded() { EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' })); refreshEntities(); } + if (keyDownEvent.keyCode === 80 && keyDownEvent.ctrlKey) { + if (keyDownEvent.shiftKey) { + EventBridge.emitWebEvent(JSON.stringify({ type: 'unparent' })); + } else { + EventBridge.emitWebEvent(JSON.stringify({ type: 'parent' })); + } + } }, false); - + var isFilterInView = false; var FILTER_IN_VIEW_ATTRIBUTE = "pressed"; elNoEntitiesInView.style.display = "none"; @@ -320,7 +327,7 @@ function loaded() { if (window.EventBridge !== undefined) { EventBridge.scriptEventReceived.connect(function(data) { data = JSON.parse(data); - + if (data.type === "clearEntityList") { clearEntities(); } else if (data.type == "selectionUpdate") { @@ -426,4 +433,3 @@ function loaded() { event.preventDefault(); }, false); } - diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 8879c0f34e..ab8a3f7c85 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -273,7 +273,7 @@ function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElemen propertyValue += subPropertyString + ','; } } else { - // We've unchecked, so remove + // We've unchecked, so remove propertyValue = propertyValue.replace(subPropertyString + ",", ""); } @@ -780,7 +780,7 @@ function loaded() { if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null && editor !== null) { saveJSONUserData(true); } - //the event bridge and json parsing handle our avatar id string differently. + //the event bridge and json parsing handle our avatar id string differently. lastEntityID = '"' + properties.id + '"'; elID.innerHTML = properties.id; @@ -1390,7 +1390,7 @@ function loaded() { elZoneFlyingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('flyingAllowed')); elZoneGhostingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ghostingAllowed')); elZoneFilterURL.addEventListener('change', createEmitTextPropertyUpdateFunction('filterURL')); - + var voxelVolumeSizeChangeFunction = createEmitVec3PropertyUpdateFunction( 'voxelVolumeSize', elVoxelVolumeSizeX, elVoxelVolumeSizeY, elVoxelVolumeSizeZ); elVoxelVolumeSizeX.addEventListener('change', voxelVolumeSizeChangeFunction); @@ -1441,7 +1441,15 @@ function loaded() { })); }); - + document.addEventListener("keydown", function (keyDown) { + if (keyDown.keyCode === 80 && keyDown.ctrlKey) { + if (keyDown.shiftKey) { + EventBridge.emitWebEvent(JSON.stringify({ type: 'unparent' })); + } else { + EventBridge.emitWebEvent(JSON.stringify({ type: 'parent' })); + } + } + }); window.onblur = function() { // Fake a change event var ev = document.createEvent("HTMLEvents"); diff --git a/scripts/system/html/js/gridControls.js b/scripts/system/html/js/gridControls.js index a245ed4cda..75052414ee 100644 --- a/scripts/system/html/js/gridControls.js +++ b/scripts/system/html/js/gridControls.js @@ -131,10 +131,17 @@ function loaded() { EventBridge.emitWebEvent(JSON.stringify({ type: 'init' })); }); - + document.addEventListener("keydown", function (keyDown) { + if (keyDown.keyCode === 80 && keyDown.ctrlKey) { + if (keyDown.shiftKey) { + EventBridge.emitWebEvent(JSON.stringify({ type: 'unparent' })); + } else { + EventBridge.emitWebEvent(JSON.stringify({ type: 'parent' })); + } + } + }) // Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked document.addEventListener("contextmenu", function (event) { event.preventDefault(); }, false); } - diff --git a/scripts/system/html/js/parentingHotkey.js b/scripts/system/html/js/parentingHotkey.js deleted file mode 100644 index c17dae01fe..0000000000 --- a/scripts/system/html/js/parentingHotkey.js +++ /dev/null @@ -1,12 +0,0 @@ -var keyReleaseEvent = function (event) { - if (event.text === 'p' && event.isControl && !event.isAutoRepeat ) { - if (event.isShifted) { - EventBridge.emitWebEvent(JSON.stringify({ type: 'unparent' })); - } else { - EventBridge.emitWebEvent(JSON.stringify({ type: 'parent' })); - } - } -}; - -window.onkeypress = keyReleaseEvent; -Controller.keyReleaseEvent.connect(keyReleaseEvent); From 0df6305f901e24ab1b3f4d3028f4c169059cb8e9 Mon Sep 17 00:00:00 2001 From: Menithal Date: Sat, 18 Feb 2017 18:22:01 +0200 Subject: [PATCH 016/133] Revert removal of hotkey from js event --- scripts/system/edit.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index d0236ce993..688fabab8b 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -849,7 +849,6 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Parent Entity to Last", - shortcutKey: "CTRL+P", afterItem: "Entity List...", grouping: "Advanced" }); @@ -858,7 +857,6 @@ function setupModelMenus() { menuName: "Edit", menuItemName: "Unparent Entity", afterItem: "Entity List...", - shortcutKey: "CTRL+SHIFT+P", grouping: "Advanced" }); Menu.addMenuItem({ @@ -1374,6 +1372,12 @@ var keyReleaseEvent = function (event) { }); grid.setPosition(newPosition); } + } else if (event.text === 'p' && event.isControl && !event.isAutoRepeat ) { + if (event.isShifted) { + unparentSelectedEntities(); + } else { + parentSelectedEntities(); + } } }; Controller.keyReleaseEvent.connect(keyReleaseEvent); From f3c806e91090c720e4f3841600f7933d44258a7e Mon Sep 17 00:00:00 2001 From: Menithal Date: Sat, 18 Feb 2017 18:33:00 +0200 Subject: [PATCH 017/133] Revert of hotkey detection, removed menu hotkeys - Holding hotkeys will no longer spam parent events rapidly, detects only the release --- scripts/system/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 688fabab8b..bc76489c41 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1372,7 +1372,7 @@ var keyReleaseEvent = function (event) { }); grid.setPosition(newPosition); } - } else if (event.text === 'p' && event.isControl && !event.isAutoRepeat ) { + } else if (event.key === 80 && event.isControl && !event.isAutoRepeat ) { if (event.isShifted) { unparentSelectedEntities(); } else { From 9b8503eba5ce4d359c30c681e4765e8dfa242227 Mon Sep 17 00:00:00 2001 From: Menithal Date: Sun, 19 Feb 2017 18:18:38 +0200 Subject: [PATCH 018/133] Initial Grab Clone --- scripts/system/html/entityProperties.html | 15 ++++++++++++++- scripts/system/html/js/entityProperties.js | 13 ++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index b11127b26c..4c3723a2ef 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -61,7 +61,7 @@
- +

@@ -295,12 +295,25 @@
+
+ + +
+
+
+ Cloneable Settings +
+
+
+
+
+

diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 8879c0f34e..63cb037ada 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -273,7 +273,7 @@ function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElemen propertyValue += subPropertyString + ','; } } else { - // We've unchecked, so remove + // We've unchecked, so remove propertyValue = propertyValue.replace(subPropertyString + ",", ""); } @@ -584,6 +584,7 @@ function loaded() { var elCollisionSoundURL = document.getElementById("property-collision-sound-url"); var elGrabbable = document.getElementById("property-grabbable"); + var elCloneable = document.getElementById("property-cloneable"); var elWantsTrigger = document.getElementById("property-wants-trigger"); var elIgnoreIK = document.getElementById("property-ignore-ik"); @@ -780,7 +781,7 @@ function loaded() { if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null && editor !== null) { saveJSONUserData(true); } - //the event bridge and json parsing handle our avatar id string differently. + //the event bridge and json parsing handle our avatar id string differently. lastEntityID = '"' + properties.id + '"'; elID.innerHTML = properties.id; @@ -1156,6 +1157,12 @@ function loaded() { elGrabbable.addEventListener('change', function() { userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, properties.dynamic); }); + elCloneable.addEventListener('change', function () { + userDataChanger("grabbableKey", "cloneable", elCloneable, elUserData, false); + if (elCloneable.checked) { + + } + }); elWantsTrigger.addEventListener('change', function() { userDataChanger("grabbableKey", "wantsTrigger", elWantsTrigger, elUserData, false); }); @@ -1390,7 +1397,7 @@ function loaded() { elZoneFlyingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('flyingAllowed')); elZoneGhostingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ghostingAllowed')); elZoneFilterURL.addEventListener('change', createEmitTextPropertyUpdateFunction('filterURL')); - + var voxelVolumeSizeChangeFunction = createEmitVec3PropertyUpdateFunction( 'voxelVolumeSize', elVoxelVolumeSizeX, elVoxelVolumeSizeY, elVoxelVolumeSizeZ); elVoxelVolumeSizeX.addEventListener('change', voxelVolumeSizeChangeFunction); From 2a4b493de560049bf34f2e179cca4970a830a7c7 Mon Sep 17 00:00:00 2001 From: Menithal Date: Sun, 19 Feb 2017 18:24:56 +0200 Subject: [PATCH 019/133] Changed order on Menu --- scripts/system/edit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index bc76489c41..61bbd23180 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -856,14 +856,14 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Unparent Entity", - afterItem: "Entity List...", + afterItem: "Parent Entity to Last", grouping: "Advanced" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", - afterItem: "Entity List...", + afterItem: "Unparent Entity", isCheckable: true, isChecked: true, grouping: "Advanced" From d9f86612de72cb10004d70ae68db4e06669650fb Mon Sep 17 00:00:00 2001 From: Menithal Date: Sun, 19 Feb 2017 20:18:11 +0200 Subject: [PATCH 020/133] Fixed view toggle, Added new Notifications - View Toggle now only toggles if no other modifiers are pressed - More notification, and cases for notification - Parenting to existing parent - Unparenting when there is no parent - Unparenting single entities --- interface/src/Application.cpp | 10 ++++--- scripts/system/edit.js | 54 ++++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 488e97b5e6..bfc5be29e7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2886,10 +2886,12 @@ void Application::keyPressEvent(QKeyEvent* event) { } break; case Qt::Key_P: { - bool isFirstPersonChecked = Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson); - Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, !isFirstPersonChecked); - Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, isFirstPersonChecked); - cameraMenuChanged(); + if (!(isShifted || isMeta || isOption)) { + bool isFirstPersonChecked = Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson); + Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, !isFirstPersonChecked); + Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, isFirstPersonChecked); + cameraMenuChanged(); + } break; } diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 61bbd23180..7731edd622 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1116,30 +1116,64 @@ function recursiveDelete(entities, childrenList) { } function unparentSelectedEntities() { if (SelectionManager.hasSelection()) { - var selectedEntities = selectionManager.selections; - selectedEntities.forEach(function (id, index) { - Entities.editEntity(id, {parentID: null}) - return true; - }); - Window.notify("Entities Unparented"); + var selectedEntities = selectionManager.selections; + var parentCheck = false; + + if (selectedEntities.length < 1) { + Window.notifyEditError("You must have an entity selected inorder to unparent it."); + return; + } + selectedEntities.forEach(function (id, index) { + var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID; + if (parentId !== null && parentId.length > 0 && parentId !== "{00000000-0000-0000-0000-000000000000}") { + parentCheck = true; + } + Entities.editEntity(id, {parentID: null}) + return true; + }); + if (parentCheck) { + if (selectedEntities.length > 1) { + Window.notify("Entities unparented"); + } else { + Window.notify("Entity unparented"); + } + } else { + if (selectedEntities.length > 1) { + Window.notify("Selected Entities have no parents"); + } else { + Window.notify("Selected Entity does not have a parent"); + } + } + } else { + Window.notifyEditError("You have nothing selected to unparent"); } } function parentSelectedEntities() { if (SelectionManager.hasSelection()) { var selectedEntities = selectionManager.selections; if (selectedEntities.length <= 1) { - Window.notifyEditError("You must have multiple objects selected in order to parent them"); - return; + Window.notifyEditError("You must have multiple entities selected in order to parent them"); + return; } + var parentCheck = false; var lastEntityId = selectedEntities[selectedEntities.length-1]; selectedEntities.forEach(function (id, index) { if (lastEntityId !== id) { + var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID; + if (parentId !== lastEntityId) { + parentCheck = true; + } Entities.editEntity(id, {parentID: lastEntityId}) } }); - Window.notify("Entities Parented"); + + if(parentCheck) { + Window.notify("Entities parented"); + }else { + Window.notify("Entities are already parented to last"); + } } else { - Window.notifyEditError("You have nothing selected") + Window.notifyEditError("You have nothing selected to parent"); } } function deleteSelectedEntities() { From 55611d2373f6fd4fa7f1e1ced5687ac634529c3a Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 21 Feb 2017 14:56:07 -0800 Subject: [PATCH 021/133] Backing up to master --- .../render-utils/src/RenderDeferredTask.cpp | 3 +- .../render-utils/src/RenderDeferredTask.h | 5 +- libraries/render/src/render/DrawTask.cpp | 105 ------------------ libraries/render/src/render/DrawTask.h | 1 - .../developer/utilities/render/culling.qml | 16 --- 5 files changed, 2 insertions(+), 128 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 24e284a416..55a9c8b9e4 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -295,8 +295,7 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); if (_stateSort) { - // renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); - renderStateSortShapesCapped(sceneContext, renderContext, _shapePlumber, inItems, _maxTimeBudget, _maxDrawn); + renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); } else { renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 2d9a7d4888..8a95447e67 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -85,7 +85,6 @@ class DrawStateSortConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) - Q_PROPERTY(float maxTimeBudget MEMBER maxTimeBudget NOTIFY dirty) Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty) public: @@ -93,7 +92,6 @@ public: void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } int maxDrawn{ -1 }; - float maxTimeBudget { 8.0f }; // 8ms maximum bool stateSort{ true }; signals: @@ -113,13 +111,12 @@ public: DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; _maxTimeBudget = config.maxTimeBudget; _stateSort = config.stateSort; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; } void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: render::ShapePlumberPointer _shapePlumber; int _maxDrawn; // initialized by Config - float _maxTimeBudget; //ms time budget bool _stateSort; }; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index d6f09f735c..2829c6f8e7 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -123,111 +123,6 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons } } - -void render::renderStateSortShapesCapped(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, double mstimeBudget, int maxDrawnItems) { - - auto& scene = sceneContext->_scene; - RenderArgs* args = renderContext->args; - auto now = usecTimestampNow(); - - int numItemsToDraw = (int)inItems.size(); - if (maxDrawnItems != -1) { - numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems); - } - - using SortedPipelines = std::vector; - using SortedShapes = std::unordered_map, render::ShapeKey::Hash, render::ShapeKey::KeyEqual>; - SortedPipelines sortedPipelines; - SortedShapes sortedShapes; - std::vector ownPipelineBucket; - - { - PROFILE_RANGE(render_detail, "sort"); - - for (auto i = 0; i < numItemsToDraw; ++i) { - auto item = scene->getItem(inItems[i].id); - - { - assert(item.getKey().isShape()); - const auto key = item.getShapeKey(); - if (key.isValid() && !key.hasOwnPipeline()) { - auto& bucket = sortedShapes[key]; - if (bucket.empty()) { - sortedPipelines.push_back(key); - } - bucket.push_back(item); - } else if (key.hasOwnPipeline()) { - ownPipelineBucket.push_back(item); - } else { - qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key; - } - } - } - } - - { - PROFILE_RANGE(render_detail, "render"); - - // Then render - quint64 usecHalfBudget = 1000 * 0.5 * mstimeBudget; - quint64 usecBudget = 1000 * mstimeBudget; - - int numDrawCalls = 0; - int numDrawcallsChecks = 128; - int numChecks = 0; - int numChecksBudget = 4; - - for (auto& pipelineKey : sortedPipelines) { - auto& bucket = sortedShapes[pipelineKey]; - args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); - if (!args->_pipeline) { - continue; - } - for (auto& item : bucket) { - item.render(args); - - numDrawCalls++; - if ((numDrawCalls % numDrawcallsChecks) == 0) { - auto newNow = usecTimestampNow(); - if ((newNow - now) > usecHalfBudget) { - if ((newNow - now) > usecBudget) { - return; - } - - usecHalfBudget += (usecHalfBudget / 2); - numDrawcallsChecks / 2; - numChecks++; - if (numChecks > numChecksBudget) { - return; - } - } - } - } - } - args->_pipeline = nullptr; - for (auto& item : ownPipelineBucket) { - item.render(args); - - numDrawCalls++; - if ((numDrawCalls % numDrawcallsChecks) == 0) { - auto newNow = usecTimestampNow(); - if ((newNow - now) > usecHalfBudget) { - if ((newNow - now) > usecBudget) { - return; - } - - usecHalfBudget += (usecHalfBudget / 2); - numDrawcallsChecks / 2; - numChecks++; - if (numChecks > numChecksBudget) { - return; - } - } - } - } - } -} - void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 042a927caf..890001ded0 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -19,7 +19,6 @@ namespace render { void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); -void renderStateSortShapesCapped(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, double mstimeBudget, int maxDrawnItems = -1); class DrawLightConfig : public Job::Config { diff --git a/scripts/developer/utilities/render/culling.qml b/scripts/developer/utilities/render/culling.qml index 4157b5e4dd..e3f5e67bbe 100644 --- a/scripts/developer/utilities/render/culling.qml +++ b/scripts/developer/utilities/render/culling.qml @@ -95,7 +95,6 @@ Column { GroupBox { title: "Render Items" - Column{ Column{ Repeater { @@ -111,20 +110,5 @@ Column { } } } - - Column{ - Repeater { - model: [ "Draw Opaque [ms]:DrawOpaqueDeferred" ] - ConfigSlider { - label: qsTr(modelData.split(":")[0]) - integral: false - config: Render.getConfig(modelData.split(":")[1]) - property: "maxTimeBudget" - max: 10.0 - min: 0.0 - } - } - } - } } } From 3cd422e5081b69e206975ac2f3effc5ea54419b4 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 21 Feb 2017 15:02:12 -0800 Subject: [PATCH 022/133] Last clean up --- libraries/render/src/render/DrawTask.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 890001ded0..6e0e5ba10b 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -20,7 +20,6 @@ void renderItems(const SceneContextPointer& sceneContext, const RenderContextPoi void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); - class DrawLightConfig : public Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) From 6d7fab40530c781ffed6f6b6506352c678435033 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 21 Feb 2017 16:59:08 -0800 Subject: [PATCH 023/133] Agent Avatars sending loudness in AvatarData --- assignment-client/src/Agent.cpp | 53 +++++++++++++++++++++++++-------- assignment-client/src/Agent.h | 1 + 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index bea677aeb6..cd8c8189b2 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -88,9 +88,9 @@ void Agent::playAvatarSound(SharedSoundPointer sound) { QMetaObject::invokeMethod(this, "playAvatarSound", Q_ARG(SharedSoundPointer, sound)); return; } else { - // TODO: seems to add occasional artifact in tests. I believe it is + // TODO: seems to add occasional artifact in tests. I believe it is // correct to do this, but need to figure out for sure, so commenting this - // out until I verify. + // out until I verify. // _numAvatarSoundSentBytes = 0; setAvatarSound(sound); } @@ -105,7 +105,7 @@ void Agent::handleOctreePacket(QSharedPointer message, SharedNo if (message->getSize() > statsMessageLength) { // pull out the piggybacked packet and create a new QSharedPointer for it int piggyBackedSizeWithHeader = message->getSize() - statsMessageLength; - + auto buffer = std::unique_ptr(new char[piggyBackedSizeWithHeader]); memcpy(buffer.get(), message->getRawMessage() + statsMessageLength, piggyBackedSizeWithHeader); @@ -284,7 +284,7 @@ void Agent::selectAudioFormat(const QString& selectedCodecName) { for (auto& plugin : codecPlugins) { if (_selectedCodecName == plugin->getName()) { _codec = plugin; - _receivedAudioStream.setupCodec(plugin, _selectedCodecName, AudioConstants::STEREO); + _receivedAudioStream.setupCodec(plugin, _selectedCodecName, AudioConstants::STEREO); _encoder = plugin->createEncoder(AudioConstants::SAMPLE_RATE, AudioConstants::MONO); qDebug() << "Selected Codec Plugin:" << _codec.get(); break; @@ -424,16 +424,16 @@ void Agent::executeScript() { entityScriptingInterface->setEntityTree(_entityViewer.getTree()); DependencyManager::set(_entityViewer.getTree()); - + // 100Hz timer for audio AvatarAudioTimer* audioTimerWorker = new AvatarAudioTimer(); audioTimerWorker->moveToThread(&_avatarAudioTimerThread); connect(audioTimerWorker, &AvatarAudioTimer::avatarTick, this, &Agent::processAgentAvatarAudio); connect(this, &Agent::startAvatarAudioTimer, audioTimerWorker, &AvatarAudioTimer::start); connect(this, &Agent::stopAvatarAudioTimer, audioTimerWorker, &AvatarAudioTimer::stop); - connect(&_avatarAudioTimerThread, &QThread::finished, audioTimerWorker, &QObject::deleteLater); + connect(&_avatarAudioTimerThread, &QThread::finished, audioTimerWorker, &QObject::deleteLater); _avatarAudioTimerThread.start(); - + // 60Hz timer for avatar QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatar); _scriptEngine->run(); @@ -448,14 +448,14 @@ QUuid Agent::getSessionUUID() const { return DependencyManager::get()->getSessionUUID(); } -void Agent::setIsListeningToAudioStream(bool isListeningToAudioStream) { +void Agent::setIsListeningToAudioStream(bool isListeningToAudioStream) { // this must happen on Agent's main thread if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "setIsListeningToAudioStream", Q_ARG(bool, isListeningToAudioStream)); return; } if (_isListeningToAudioStream) { - // have to tell just the audio mixer to KillAvatar. + // have to tell just the audio mixer to KillAvatar. auto nodeList = DependencyManager::get(); nodeList->eachMatchingNode( @@ -471,7 +471,7 @@ void Agent::setIsListeningToAudioStream(bool isListeningToAudioStream) { }); } - _isListeningToAudioStream = isListeningToAudioStream; + _isListeningToAudioStream = isListeningToAudioStream; } void Agent::setIsAvatar(bool isAvatar) { @@ -552,6 +552,7 @@ void Agent::processAgentAvatar() { nodeList->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer); } } + void Agent::encodeFrameOfZeros(QByteArray& encodedZeros) { _flushEncoder = false; static const QByteArray zeros(AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL, 0); @@ -562,6 +563,23 @@ void Agent::encodeFrameOfZeros(QByteArray& encodedZeros) { } } +void Agent::computeLoudness(QByteArray* decodedBuffer) { + float loudness = 0.0f; + auto scriptedAvatar = DependencyManager::get(); + if (decodedBuffer) { + auto soundData = reinterpret_cast(decodedBuffer->constData()); + auto numFrames = decodedBuffer->size() / sizeof(int16_t); + // now iterate and come up with average + if (numFrames > 0) { + for(int i = 0; i < numFrames; i++) { + loudness += (float) std::abs(soundData[i]); + } + loudness /= numFrames; + } + } + scriptedAvatar->setAudioLoudness(loudness); +} + void Agent::processAgentAvatarAudio() { auto recordingInterface = DependencyManager::get(); bool isPlayingRecording = recordingInterface->isPlaying(); @@ -611,6 +629,9 @@ void Agent::processAgentAvatarAudio() { audioPacket->seek(sizeof(quint16)); if (silentFrame) { + // no matter what, the loudness should be set to 0 + computeLoudness(nullptr); + if (!_isListeningToAudioStream) { // if we have a silent frame and we're not listening then just send nothing and break out of here return; @@ -618,7 +639,7 @@ void Agent::processAgentAvatarAudio() { // write the codec audioPacket->writeString(_selectedCodecName); - + // write the number of silent samples so the audio-mixer can uphold timing audioPacket->writePrimitive(numAvailableSamples); @@ -628,8 +649,9 @@ void Agent::processAgentAvatarAudio() { audioPacket->writePrimitive(headOrientation); audioPacket->writePrimitive(scriptedAvatar->getPosition()); audioPacket->writePrimitive(glm::vec3(0)); + } else if (nextSoundOutput) { - + // write the codec audioPacket->writeString(_selectedCodecName); @@ -646,6 +668,8 @@ void Agent::processAgentAvatarAudio() { QByteArray encodedBuffer; if (_flushEncoder) { encodeFrameOfZeros(encodedBuffer); + // loudness is 0 + computeLoudness(nullptr); } else { QByteArray decodedBuffer(reinterpret_cast(nextSoundOutput), numAvailableSamples*sizeof(int16_t)); if (_encoder) { @@ -654,10 +678,15 @@ void Agent::processAgentAvatarAudio() { } else { encodedBuffer = decodedBuffer; } + computeLoudness(&decodedBuffer); } audioPacket->write(encodedBuffer.constData(), encodedBuffer.size()); } + // we should never have both nextSoundOutput being null and silentFrame being false, but lets + // assert on it in case things above change in a bad way + assert(nextSoundOutput || silentFrame); + // write audio packet to AudioMixer nodes auto nodeList = DependencyManager::get(); nodeList->eachNode([this, &nodeList, &audioPacket](const SharedNodePointer& node) { diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index c9b1707101..7f04b4746f 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -82,6 +82,7 @@ private: void negotiateAudioFormat(); void selectAudioFormat(const QString& selectedCodecName); void encodeFrameOfZeros(QByteArray& encodedZeros); + void computeLoudness(QByteArray* decodedBuffer); std::unique_ptr _scriptEngine; EntityEditPacketSender _entityEditSender; From a00216cb4f43d967ac49f6e05a528eab00a44b5b Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 21 Feb 2017 18:20:55 -0800 Subject: [PATCH 024/133] debugging the emissive issue for verlay in front --- .../render-utils/src/RenderPipelines.cpp | 7 +- .../render-utils/src/overlay3D_model.slf | 134 ++++++++++++++++++ .../src/overlay3D_translucent.slf | 2 + 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 libraries/render-utils/src/overlay3D_model.slf diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index c5a6c4b6ca..53fc9153e8 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -50,6 +50,7 @@ #include "overlay3D_vert.h" #include "overlay3D_frag.h" +#include "overlay3D_model_frag.h" #include "overlay3D_translucent_frag.h" #include "overlay3D_unlit_frag.h" #include "overlay3D_translucent_unlit_frag.h" @@ -70,17 +71,19 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); - auto pixel = gpu::Shader::createPixel(std::string(overlay3D_frag)); + auto pixel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag)); auto pixelUnlit = gpu::Shader::createPixel(std::string(overlay3D_unlit_frag)); auto pixelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_translucent_unlit_frag)); + auto pixelMaterial = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel); auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit); auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); + auto opaqueMaterialProgram = gpu::Shader::createProgram(vertex, pixelMaterial); - for (int i = 0; i < 8; i++) { + for (int i = 0; i < 16; i++) { bool isCulled = (i & 1); bool isBiased = (i & 2); bool isOpaque = (i & 4); diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf new file mode 100644 index 0000000000..dcc5eac58c --- /dev/null +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -0,0 +1,134 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// overlay3D.slf +// fragment shader +// +// Created by Sam Gateau on 6/16/15. +// Copyright 2015 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 model/Light.slh@> +<$declareLightBuffer()$> +<$declareLightAmbientBuffer()$> + +<@include LightingModel.slh@> + +<@include LightDirectional.slh@> +<$declareLightingDirectional()$> + +<@include model/Material.slh@> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) { + + // Need the light now + Light light = getLight(); + vec3 lightDirection = getLightDirection(light); + vec3 lightIrradiance = getLightIrradiance(light); + + LightAmbient ambient = getLightAmbient(); + + TransformCamera cam = getTransformCamera(); + vec3 fragNormal; + <$transformEyeToWorldDir(cam, normal, fragNormal)$> + vec3 fragEyeVectorView = normalize(-position); + vec3 fragEyeDir; + <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> + + vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient); + + // Directional + vec3 directionalDiffuse; + vec3 directionalSpecular; + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled(); + color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled(); + + return vec4(color, opacity); +} + + +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec4 _position; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float metallic = getMaterialMetallic(mat); + vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value + if (metallic <= 0.5) { + metallic = 0.0; + } else { + fresnel = albedo; + metallic = 1.0; + } + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + + vec3 fragPosition = _position.xyz; + vec3 fragNormal = normalize(_normal); + + TransformCamera cam = getTransformCamera(); + + vec4 color = evalGlobalColor(occlusionTex, + fragPosition, + fragNormal, + albedo, + metallic, + fresnel, + roughness, + opacity); + + color.rgb += emissive; + + // Apply standard tone mapping + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + + /*_fragColor = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + occlusionTex, + fragPosition, + fragNormal, + albedo, + fresnel, + metallic, + emissive, + roughness, opacity), + opacity); + + // Apply standard tone mapping + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);*/ +} \ No newline at end of file diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index 9bdac2d21f..0343567127 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -82,6 +82,8 @@ void main(void) { fragRoughness, fragOpacity); + color.xyz += vec3(1.0, 0.0, 0.0) * fragOpacity; + // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); } From 397eb89c143d2e746ca6e5ecd3980c210ea95e04 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 22 Feb 2017 08:38:49 -0800 Subject: [PATCH 025/133] compiler warning - odd --- assignment-client/src/Agent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index cd8c8189b2..2f91571d8b 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -568,7 +568,7 @@ void Agent::computeLoudness(QByteArray* decodedBuffer) { auto scriptedAvatar = DependencyManager::get(); if (decodedBuffer) { auto soundData = reinterpret_cast(decodedBuffer->constData()); - auto numFrames = decodedBuffer->size() / sizeof(int16_t); + int numFrames = decodedBuffer->size() / sizeof(int16_t); // now iterate and come up with average if (numFrames > 0) { for(int i = 0; i < numFrames; i++) { From c7b164d8f26d1bb45666f1c1ad96c354b648b4ae Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 22 Feb 2017 18:21:18 -0800 Subject: [PATCH 026/133] Adding differenciation for the Material shapeKey bit --- .../render-utils/src/MeshPartPayload.cpp | 4 ++ .../render-utils/src/RenderPipelines.cpp | 66 ++++++++++--------- libraries/render/src/render/ShapePipeline.h | 9 ++- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 4cb4e2a316..5b3d285b47 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -97,6 +97,8 @@ ShapeKey MeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; + builder.withMaterial(); + if (drawMaterialKey.isTranslucent()) { builder.withTranslucent(); } @@ -478,6 +480,8 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; + builder.withMaterial(); + if (isTranslucent || _fadeState != FADE_COMPLETE) { builder.withTranslucent(); } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 53fc9153e8..19284814fc 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -106,6 +106,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { } ShapeKey::Filter::Builder builder; + isCulled ? builder.withCullFace() : builder.withoutCullFace(); isBiased ? builder.withDepthBias() : builder.withoutDepthBias(); isOpaque ? builder.withOpaque() : builder.withTranslucent(); @@ -113,6 +114,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); } } @@ -147,78 +149,78 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // TODO: Refactor this to use a filter // Opaques addPipeline( - Key::Builder(), + Key::Builder().withMaterial(), modelVertex, modelPixel); addPipeline( - Key::Builder().withUnlit(), + Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); addPipeline( - Key::Builder().withTangents(), + Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); addPipeline( - Key::Builder().withSpecular(), + Key::Builder().withMaterial().withSpecular(), modelVertex, modelSpecularMapPixel); addPipeline( - Key::Builder().withTangents().withSpecular(), + Key::Builder().withMaterial().withTangents().withSpecular(), modelNormalMapVertex, modelNormalSpecularMapPixel); // Translucents addPipeline( - Key::Builder().withTranslucent(), + Key::Builder().withMaterial().withTranslucent(), modelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withTranslucent().withUnlit(), + Key::Builder().withMaterial().withTranslucent().withUnlit(), modelVertex, modelTranslucentUnlitPixel); addPipeline( - Key::Builder().withTranslucent().withTangents(), + Key::Builder().withMaterial().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withTranslucent().withSpecular(), + Key::Builder().withMaterial().withTranslucent().withSpecular(), modelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withTranslucent().withTangents().withSpecular(), + Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(), modelNormalMapVertex, modelTranslucentPixel); addPipeline( // FIXME: Ignore lightmap for translucents meshpart - Key::Builder().withTranslucent().withLightmap(), + Key::Builder().withMaterial().withTranslucent().withLightmap(), modelVertex, modelTranslucentPixel); // Lightmapped addPipeline( - Key::Builder().withLightmap(), + Key::Builder().withMaterial().withLightmap(), modelLightmapVertex, modelLightmapPixel); addPipeline( - Key::Builder().withLightmap().withTangents(), + Key::Builder().withMaterial().withLightmap().withTangents(), modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); addPipeline( - Key::Builder().withLightmap().withSpecular(), + Key::Builder().withMaterial().withLightmap().withSpecular(), modelLightmapVertex, modelLightmapSpecularMapPixel); addPipeline( - Key::Builder().withLightmap().withTangents().withSpecular(), + Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(), modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); // Skinned addPipeline( - Key::Builder().withSkinned(), + Key::Builder().withMaterial().withSkinned(), skinModelVertex, modelPixel); addPipeline( - Key::Builder().withSkinned().withTangents(), + Key::Builder().withMaterial().withSkinned().withTangents(), skinModelNormalMapVertex, modelNormalMapPixel); addPipeline( - Key::Builder().withSkinned().withSpecular(), + Key::Builder().withMaterial().withSkinned().withSpecular(), skinModelVertex, modelSpecularMapPixel); addPipeline( - Key::Builder().withSkinned().withTangents().withSpecular(), + Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(), skinModelNormalMapVertex, modelNormalSpecularMapPixel); // Skinned and Translucent addPipeline( - Key::Builder().withSkinned().withTranslucent(), + Key::Builder().withMaterial().withSkinned().withTranslucent(), skinModelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withSkinned().withTranslucent().withTangents(), + Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), skinModelNormalMapVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withSkinned().withTranslucent().withSpecular(), + Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(), skinModelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withSkinned().withTranslucent().withTangents().withSpecular(), + Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), skinModelNormalMapVertex, modelTranslucentPixel); // Depth-only addPipeline( @@ -247,32 +249,32 @@ void initForwardPipelines(render::ShapePlumber& plumber) { auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); // Opaques addPipeline( - Key::Builder(), + Key::Builder().withMaterial(), modelVertex, modelPixel); addPipeline( - Key::Builder().withUnlit(), + Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); addPipeline( - Key::Builder().withTangents(), + Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); addPipeline( - Key::Builder().withSpecular(), + Key::Builder().withMaterial().withSpecular(), modelVertex, modelSpecularMapPixel); addPipeline( - Key::Builder().withTangents().withSpecular(), + Key::Builder().withMaterial().withTangents().withSpecular(), modelNormalMapVertex, modelNormalSpecularMapPixel); // Skinned addPipeline( - Key::Builder().withSkinned(), + Key::Builder().withMaterial().withSkinned(), skinModelVertex, modelPixel); addPipeline( - Key::Builder().withSkinned().withTangents(), + Key::Builder().withMaterial().withSkinned().withTangents(), skinModelNormalMapVertex, modelNormalMapPixel); addPipeline( - Key::Builder().withSkinned().withSpecular(), + Key::Builder().withMaterial().withSkinned().withSpecular(), skinModelVertex, modelSpecularMapPixel); addPipeline( - Key::Builder().withSkinned().withTangents().withSpecular(), + Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(), skinModelNormalMapVertex, modelNormalSpecularMapPixel); } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index e7a14d2f2b..e55c1d4bc4 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -22,7 +22,8 @@ namespace render { class ShapeKey { public: enum FlagBit { - TRANSLUCENT = 0, + MATERIAL = 0, + TRANSLUCENT, LIGHTMAP, TANGENTS, SPECULAR, @@ -53,6 +54,7 @@ public: ShapeKey build() const { return ShapeKey{_flags}; } + Builder& withMaterial() { _flags.set(MATERIAL); return (*this); } Builder& withTranslucent() { _flags.set(TRANSLUCENT); return (*this); } Builder& withLightmap() { _flags.set(LIGHTMAP); return (*this); } Builder& withTangents() { _flags.set(TANGENTS); return (*this); } @@ -89,6 +91,9 @@ public: Filter build() const { return Filter(_flags, _mask); } + Builder& withMaterial() { _flags.set(MATERIAL); _mask.set(MATERIAL); return (*this); } + Builder& withoutMaterial() { _flags.reset(MATERIAL); _mask.set(MATERIAL); return (*this); } + Builder& withTranslucent() { _flags.set(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); } Builder& withOpaque() { _flags.reset(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); } @@ -134,6 +139,7 @@ public: Flags _mask{0}; }; + bool useMaterial() const { return _flags[MATERIAL]; } bool hasLightmap() const { return _flags[LIGHTMAP]; } bool hasTangents() const { return _flags[TANGENTS]; } bool hasSpecular() const { return _flags[SPECULAR]; } @@ -170,6 +176,7 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) { debug << "[ShapeKey: OWN_PIPELINE]"; } else { debug << "[ShapeKey:" + << "useMaterial:" << key.useMaterial() << "hasLightmap:" << key.hasLightmap() << "hasTangents:" << key.hasTangents() << "hasSpecular:" << key.hasSpecular() From e95e50ad6ebade12a4c07e0bfcd524803fbc9d73 Mon Sep 17 00:00:00 2001 From: Menithal Date: Thu, 23 Feb 2017 10:34:04 +0200 Subject: [PATCH 027/133] Preliminary work on edit.js to allow for new param --- scripts/system/html/entityProperties.html | 6 ++-- scripts/system/html/js/entityProperties.js | 38 +++++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 4c3723a2ef..25cd4417d5 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -305,13 +305,13 @@
-
+
Cloneable Settings
-
-
+
+
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 63cb037ada..7212fd9b9e 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -323,13 +323,9 @@ function setUserDataFromEditor(noUpdate) { }) ); } - } - - } - -function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, defaultValue) { +function userDataChanger(groupName, keyName, values, userDataElement, defaultValue) { var properties = {}; var parsedData = {}; try { @@ -339,15 +335,19 @@ function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, d } else { parsedData = JSON.parse(userDataElement.value); } - } catch (e) {} if (!(groupName in parsedData)) { parsedData[groupName] = {} } + delete parsedData[groupName][keyName]; - if (checkBoxElement.checked !== defaultValue) { - parsedData[groupName][keyName] = checkBoxElement.checked; + if (values instanceof Element) { + if (values.checked !== defaultValue) { + parsedData[groupName][keyName] = values.checked; + } + } else { + parsedData[groupName][keyName] = values; } if (Object.keys(parsedData[groupName]).length == 0) { @@ -584,7 +584,12 @@ function loaded() { var elCollisionSoundURL = document.getElementById("property-collision-sound-url"); var elGrabbable = document.getElementById("property-grabbable"); + var elCloneable = document.getElementById("property-cloneable"); + var elCloneableGroup = document.getElementById("group-cloneable-group"); + var elCloneableLifetime = document.getElementById("property-cloneable-lifetime"); + var elCloneableLimit = document.getElementById("property-cloneable-limit") + var elWantsTrigger = document.getElementById("property-wants-trigger"); var elIgnoreIK = document.getElementById("property-ignore-ik"); @@ -1160,9 +1165,24 @@ function loaded() { elCloneable.addEventListener('change', function () { userDataChanger("grabbableKey", "cloneable", elCloneable, elUserData, false); if (elCloneable.checked) { - + var cloneProperties = { + lifetime: 300, + limit: 10 + }; + userDataChanger("grabbableKey", "cloneable-properties", cloneProperties, elUserData, false); + elCloneableGroup.style.display = "block"; + } else { + userDataChanger("grabbableKey", "cloneable-properties", {}, elUserData, false); + elCloneableGroup.style.display = "none"; } }); + + var numberListener = function (event) { + userDataChanger("grabbableKey", event.target.getAttribute("data-user-data-type"), event.target.value, elUserData, false}); + }; + elCloneableLifetime.addEventListener('change', numberListener); + elCloneableLimit.addEventListener('change', numberListener); + elWantsTrigger.addEventListener('change', function() { userDataChanger("grabbableKey", "wantsTrigger", elWantsTrigger, elUserData, false); }); From 4d98cc436b63af354f05c0a84afa481ba4769e88 Mon Sep 17 00:00:00 2001 From: Menithal Date: Thu, 23 Feb 2017 23:20:21 +0200 Subject: [PATCH 028/133] Finished up Edit.js --- scripts/system/html/entityProperties.html | 6 +-- scripts/system/html/js/entityProperties.js | 43 +++++++++++++++------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 25cd4417d5..e775be9e3a 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -297,7 +297,7 @@
- +
@@ -310,8 +310,8 @@ Cloneable Settings
-
-
+
+
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 7212fd9b9e..629b9dc4e9 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -586,9 +586,10 @@ function loaded() { var elGrabbable = document.getElementById("property-grabbable"); var elCloneable = document.getElementById("property-cloneable"); + var elCloneableGroup = document.getElementById("group-cloneable-group"); var elCloneableLifetime = document.getElementById("property-cloneable-lifetime"); - var elCloneableLimit = document.getElementById("property-cloneable-limit") + var elCloneableLimit = document.getElementById("property-cloneable-limit"); var elWantsTrigger = document.getElementById("property-wants-trigger"); var elIgnoreIK = document.getElementById("property-ignore-ik"); @@ -853,6 +854,7 @@ function loaded() { elCollideOtherAvatar.checked = properties.collidesWith.indexOf("otherAvatar") > -1; elGrabbable.checked = properties.dynamic; + elWantsTrigger.checked = false; elIgnoreIK.checked = true; var parsedUserData = {} @@ -869,8 +871,27 @@ function loaded() { if ("ignoreIK" in parsedUserData["grabbableKey"]) { elIgnoreIK.checked = parsedUserData["grabbableKey"].ignoreIK; } + if ("cloneable" in parsedUserData["grabbableKey"]) { + elCloneable.checked = parsedUserData["grabbableKey"].cloneable; + + elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; + elCloneableLimit.value = elCloneable.checked ? 10: 0; + elCloneableLifetime.value = elCloneable.checked ? 300: 0; + } else { + elCloneable.checked = false; + elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; + elCloneableLimit.value = 0; + elCloneableLifetime.value = 0; + } + if ("cloneLifetime" in parsedUserData["grabbableKey"]) { + elCloneableLifetime.value = parsedUserData["grabbableKey"].cloneLifetime; + } + if ("cloneLimit" in parsedUserData["grabbableKey"]) { + elCloneableLimit.value = parsedUserData["grabbableKey"].cloneLimit; + } } - } catch (e) {} + } catch (e) { + } elCollisionSoundURL.value = properties.collisionSoundURL; elLifetime.value = properties.lifetime; @@ -1162,23 +1183,19 @@ function loaded() { elGrabbable.addEventListener('change', function() { userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, properties.dynamic); }); - elCloneable.addEventListener('change', function () { - userDataChanger("grabbableKey", "cloneable", elCloneable, elUserData, false); - if (elCloneable.checked) { - var cloneProperties = { - lifetime: 300, - limit: 10 - }; - userDataChanger("grabbableKey", "cloneable-properties", cloneProperties, elUserData, false); + elCloneable.addEventListener('change', function (event) { + if (event.target.checked) { + userDataChanger("grabbableKey", "cloneLifetime", 300, elUserData, -1); + userDataChanger("grabbableKey", "cloneLimit", 10, elUserData, -1); elCloneableGroup.style.display = "block"; } else { - userDataChanger("grabbableKey", "cloneable-properties", {}, elUserData, false); elCloneableGroup.style.display = "none"; } + userDataChanger("grabbableKey", "cloneable", event.target, elUserData, null); }); - + var numberListener = function (event) { - userDataChanger("grabbableKey", event.target.getAttribute("data-user-data-type"), event.target.value, elUserData, false}); + userDataChanger("grabbableKey", event.target.getAttribute("data-user-data-type"), parseInt(event.target.value), elUserData, false); }; elCloneableLifetime.addEventListener('change', numberListener); elCloneableLimit.addEventListener('change', numberListener); From 6d59144a4f6be81935376fb8893a1d1c04ea6363 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 23 Feb 2017 17:42:02 -0800 Subject: [PATCH 029/133] Trying to fix the emissive for overlay in front ? --- interface/src/ui/overlays/OverlaysPayload.cpp | 6 +++++- libraries/render-utils/src/RenderPipelines.cpp | 9 +++++---- libraries/render-utils/src/overlay3D_model.slf | 5 +++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 277a86e93f..4aa3edbe6c 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -62,7 +62,11 @@ namespace render { if (overlay->is3D()) { auto overlay3D = std::dynamic_pointer_cast(overlay); if (overlay3D->isAA()) - return (overlay3D->getDrawInFront() ? LAYER_3D_FRONT : LAYER_3D); + if (overlay3D->getDrawInFront()) { + return LAYER_3D_FRONT; + } else { + return LAYER_3D; + } else return LAYER_NO_AA; } else { diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 19284814fc..cbbd1cd193 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -71,6 +71,7 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); + auto vertexModel = gpu::Shader::createVertex(std::string(model_vert)); auto pixel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag)); auto pixelUnlit = gpu::Shader::createPixel(std::string(overlay3D_unlit_frag)); @@ -81,7 +82,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit); auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); - auto opaqueMaterialProgram = gpu::Shader::createProgram(vertex, pixelMaterial); + auto opaqueMaterialProgram = gpu::Shader::createProgram(vertexModel, pixelMaterial); for (int i = 0; i < 16; i++) { bool isCulled = (i & 1); @@ -113,9 +114,9 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; - plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); + plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withMaterial().withoutUnlit().build(), opaqueMaterialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withUnlit().withoutMaterial().build(), unlitProgram, state, &batchSetter); } } diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index dcc5eac58c..cd4179b112 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -112,9 +112,10 @@ void main(void) { opacity); color.rgb += emissive; - + color.rgb = vec3(0.5, 0.5, 1.0); // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 0.9); + //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, From 4a4c914ca8df6b1e7d7d66885789deac94263d31 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 23 Feb 2017 18:53:22 -0800 Subject: [PATCH 030/133] First cut at new styling --- .../images/Audio-Loudness-Icons/vol-0.svg | 12 ++++++ .../images/Audio-Loudness-Icons/vol-1.svg | 13 ++++++ .../images/Audio-Loudness-Icons/vol-2.svg | 16 ++++++++ .../images/Audio-Loudness-Icons/vol-3.svg | 19 +++++++++ .../images/Audio-Loudness-Icons/vol-4.svg | 21 ++++++++++ interface/resources/qml/hifi/Pal.qml | 40 +++++++++++-------- scripts/system/pal.js | 19 ++++++++- 7 files changed, 122 insertions(+), 18 deletions(-) create mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-0.svg create mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-1.svg create mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-2.svg create mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-3.svg create mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-4.svg diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-0.svg b/interface/resources/images/Audio-Loudness-Icons/vol-0.svg new file mode 100755 index 0000000000..72f247c238 --- /dev/null +++ b/interface/resources/images/Audio-Loudness-Icons/vol-0.svg @@ -0,0 +1,12 @@ + + + + + diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-1.svg b/interface/resources/images/Audio-Loudness-Icons/vol-1.svg new file mode 100755 index 0000000000..9570b9ae6c --- /dev/null +++ b/interface/resources/images/Audio-Loudness-Icons/vol-1.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-2.svg b/interface/resources/images/Audio-Loudness-Icons/vol-2.svg new file mode 100755 index 0000000000..a2175be39e --- /dev/null +++ b/interface/resources/images/Audio-Loudness-Icons/vol-2.svg @@ -0,0 +1,16 @@ + + + + + + + diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-3.svg b/interface/resources/images/Audio-Loudness-Icons/vol-3.svg new file mode 100755 index 0000000000..21b1095941 --- /dev/null +++ b/interface/resources/images/Audio-Loudness-Icons/vol-3.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-4.svg b/interface/resources/images/Audio-Loudness-Icons/vol-4.svg new file mode 100755 index 0000000000..de0b4027eb --- /dev/null +++ b/interface/resources/images/Audio-Loudness-Icons/vol-4.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index e0f2df76ce..4735ae9312 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -13,6 +13,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 +import QtGraphicalEffects 1.0 import "../styles-uit" import "../controls-uit" as HifiControls @@ -163,6 +164,14 @@ Rectangle { onSortIndicatorColumnChanged: sortModel() onSortIndicatorOrderChanged: sortModel() + TableViewColumn { + role: "avgAudioLevel" + title: "VOL" + width: actionButtonWidth + movable: false + resizable: false + } + TableViewColumn { id: displayNameHeader role: "displayName" @@ -185,13 +194,6 @@ Rectangle { movable: false resizable: false } - TableViewColumn { - role: "avgAudioLevel" - title: "VOL" - width: actionButtonWidth - movable: false - resizable: false - } TableViewColumn { visible: iAmAdmin role: "mute" @@ -226,7 +228,8 @@ Rectangle { id: itemCell property bool isCheckBox: styleData.role === "personalMute" || styleData.role === "ignore" property bool isButton: styleData.role === "mute" || styleData.role === "kick" - property bool isText: styleData.role == "avgAudioLevel" + property bool isAvgAudio: styleData.role === "avgAudioLevel" + // This NameCard refers to the cell that contains an avatar's // DisplayName and UserName NameCard { @@ -236,7 +239,7 @@ Rectangle { userName: model ? model.userName : "" audioLevel: model ? model.audioLevel : 0.0 avgAudioLevel: model ? model.avgAudioLevel : 0.0 - visible: !isCheckBox && !isButton && !isText + visible: !isCheckBox && !isButton && !isAvgAudio uuid: model ? model.sessionId : "" selected: styleData.selected isAdmin: model && model.admin @@ -246,14 +249,19 @@ Rectangle { // Anchors anchors.left: parent.left } - Text { + Image { + visible: isAvgAudio + function getImage() { + var fileName = "../../../images/Audio-Loudness-Icons/vol-"; + fileName += (4.0*(model ? model.avgAudioLevel : 0.0)).toFixed(0); + fileName += ".svg"; + return fileName; + } id: avgAudioVolume - text: model ? (10 * model.avgAudioLevel).toFixed(0) : 0.0 - visible: isText - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: parent.width - height: parent.height + width: hifi.dimensions.tableHeaderHeight + fillMode: Image.PreserveAspectFit + source: getImage() + anchors.verticalCenter: parent.verticalCenter } // This CheckBox belongs in the columns that contain the stateful action buttons ("Mute" & "Ignore" for now) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index e9f5ba0a67..fe4eea48a4 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -197,6 +197,17 @@ HighlightedEntity.updateOverlays = function updateHighlightedEntities() { }); }; +/* this contains current gain for a given node (by session id). More efficient than + * querying it, plus there isn't a getGain function so why write one */ +var sessionGains = {}; +function convertDbToLinear(decibels) { + // +20db = 10x, 0dB = 1x, -10dB = 0.1x, etc... + // but, your perception is that something 2x as loud is +10db + // so we go from -60 to +20 or 1/64x to 4x. For now, we can + // maybe scale the signal this way?? + return Math.pow(2, decibels/10.0); +} + function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. var data; switch (message.method) { @@ -242,6 +253,8 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See UserActivityLogger.palAction("avatar_gain_changed", data['sessionId']); } else { Users.setAvatarGain(data['sessionId'], data['gain']); + sessionGains[data['sessionId']] = convertDbToLinear(data['gain']); + print("set " + data['sessionId'] + " to " + sessionGains[data['sessionId']]); } break; case 'displayNameUpdate': @@ -576,6 +589,7 @@ function scaleAudio(val) { } return audioLevel; } + function getAudioLevel(id) { // the VU meter should work similarly to the one in AvatarInputs: log scale, exponentially averaged // But of course it gets the data at a different rate, so we tweak the averaging ratio and frequency @@ -594,9 +608,10 @@ function getAudioLevel(id) { // natural log, so to get log base 2, just divide by ln(2). audioLevel = scaleAudio(Math.log(data.accumulatedLevel + 1) / LOG2); avgAudioLevel = scaleAudio(Math.log(data.longAccumulatedLevel + 1) / LOG2); - + // scale avgAudioLevel given that there can be a gain (4x to 1/64x) + avgAudioLevel = Math.min(1.0, avgAudioLevel *(sessionGains[id] || 0.75)); + data.avgAudioLevel = avgAudioLevel; data.audioLevel = audioLevel; - data.averageAudioLevel = avgAudioLevel; } return [audioLevel, avgAudioLevel]; } From d9a716bf3de4bc95ddd0d98f5ecd0e5a3487cc10 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 24 Feb 2017 18:42:52 +1300 Subject: [PATCH 031/133] If someone else is grabbing entity you want to grab show their grab beam --- .../system/controllers/handControllerGrab.js | 62 ++++++++++++++++--- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index ea76490b7b..5064705f78 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -419,10 +419,10 @@ function entityIsGrabbedByOther(entityID) { } if (tag.slice(0, 5) == "grab-") { // we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. - return true; + return tag.slice(5, 42); } } - return false; + return null; } function propsArePhysical(props) { @@ -790,10 +790,10 @@ function MyController(hand) { // for visualizations this.overlayLine = null; - - // for lights - this.overlayLine = null; this.searchSphere = null; + this.otherGrabbingLine = null; + + this.otherGrabbingUUID = null; this.waitForTriggerRelease = false; @@ -1050,6 +1050,29 @@ function MyController(hand) { } }; + this.otherGrabbingLineOn = function(avatarPosition, entityPosition, color) { + if (this.otherGrabbingLine === null) { + var lineProperties = { + lineWidth: 5, + start: avatarPosition, + end: entityPosition, + color: color, + glow: 1.0, + ignoreRayIntersection: true, + drawInFront: true, + visible: true, + alpha: 1 + }; + this.otherGrabbingLine = Overlays.addOverlay("line3d", lineProperties); + } else { + Overlays.editOverlay(this.otherGrabbingLine, { + start: avatarPosition, + end: entityPosition, + color: color + }); + } + }; + this.evalLightWorldTransform = function(modelPos, modelRot) { var MODEL_LIGHT_POSITION = { @@ -1093,14 +1116,20 @@ function MyController(hand) { } }; - this.turnOffVisualizations = function() { + this.otherGrabbingLineOff = function() { + if (this.otherGrabbingLine !== null) { + Overlays.deleteOverlay(this.otherGrabbingLine); + } + this.otherGrabbingLine = null; + }; + this.turnOffVisualizations = function() { this.overlayLineOff(); this.grabPointSphereOff(); this.lineOff(); this.searchSphereOff(); + this.otherGrabbingLineOff(); restore2DMode(); - }; this.triggerPress = function(value) { @@ -1504,7 +1533,8 @@ function MyController(hand) { return false; } - if (entityIsGrabbedByOther(entityID)) { + this.otherGrabbingUUID = entityIsGrabbedByOther(entityID); + if (this.otherGrabbingUUID !== null) { // don't distance grab something that is already grabbed. if (debug) { print("distance grab is skipping '" + props.name + "': already grabbed by another."); @@ -1683,6 +1713,7 @@ function MyController(hand) { } else { // potentialFarTriggerEntity = entity; } + this.otherGrabbingLineOff(); } else if (this.entityIsDistanceGrabbable(rayPickInfo.entityID, handPosition)) { if (this.triggerSmoothedGrab() && !isEditing() && farGrabEnabled && farSearching) { this.grabbedEntity = entity; @@ -1692,7 +1723,21 @@ function MyController(hand) { } else { // potentialFarGrabEntity = entity; } + this.otherGrabbingLineOff(); + } else if (this.otherGrabbingUUID !== null) { + if (this.triggerSmoothedGrab() && !isEditing() && farGrabEnabled && farSearching) { + var avatar = AvatarList.getAvatar(this.otherGrabbingUUID); + var IN_FRONT_OF_AVATAR = { x: 0, y: 0, z: 0.2 }; + var startPosition = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.rotation, IN_FRONT_OF_AVATAR)); + this.otherGrabbingLineOn(startPosition, rayPickInfo.properties.position, COLORS_GRAB_DISTANCE_HOLD); + } else { + this.otherGrabbingLineOff(); + } + } else { + this.otherGrabbingLineOff(); } + } else { + this.otherGrabbingLineOff(); } this.updateEquipHaptics(potentialEquipHotspot, handPosition); @@ -2268,6 +2313,7 @@ function MyController(hand) { this.lineOff(); this.overlayLineOff(); this.searchSphereOff(); + this.otherGrabbingLineOff(); this.dropGestureReset(); this.clearEquipHaptics(); From 10151c3f5b23f5a9302f9aadd2db13cfdc23f1a7 Mon Sep 17 00:00:00 2001 From: Menithal Date: Fri, 24 Feb 2017 08:04:03 +0200 Subject: [PATCH 032/133] Added Multi-userdata field updater --- scripts/system/html/js/entityProperties.js | 112 +++++++++++++-------- 1 file changed, 71 insertions(+), 41 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 629b9dc4e9..abffdaee96 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -27,6 +27,7 @@ var EDITOR_TIMEOUT_DURATION = 1500; var colorPickers = []; var lastEntityID = null; + debugPrint = function(message) { EventBridge.emitWebEvent( JSON.stringify({ @@ -325,49 +326,65 @@ function setUserDataFromEditor(noUpdate) { } } } -function userDataChanger(groupName, keyName, values, userDataElement, defaultValue) { - var properties = {}; - var parsedData = {}; - try { - if ($('#userdata-editor').css('height') !== "0px") { - //if there is an expanded, we want to use its json. - parsedData = getEditorJSON(); - } else { - parsedData = JSON.parse(userDataElement.value); +function multiUserDataChanger(groupName, keyPair, userDataElement, defaults) { + var properties = {}; + var parsedData = {}; + try { + if ($('#userdata-editor').css('height') !== "0px") { + //if there is an expanded, we want to use its json. + parsedData = getEditorJSON(); + } else { + parsedData = JSON.parse(userDataElement.value); + } + } catch (e) {} + + if (!(groupName in parsedData)) { + parsedData[groupName] = {} + } + var keys = Object.keys(keyPair); + keys.forEach(function (key) { + delete parsedData[groupName][key]; + if (keyPair[key] instanceof Element) { + if(keyPair[key].type === "checkbox") { + if (keyPair[key].checked !== defaults[key]) { + parsedData[groupName][key] = keyPair[key].checked; + } + } else { + var val = isNaN(keyPair[key].value) ? keyPair[key].value : parseInt(keyPair[key].value); + if (val !== defaults[key]) { + parsedData[groupName][key] = val; } - } catch (e) {} - - if (!(groupName in parsedData)) { - parsedData[groupName] = {} - } - - delete parsedData[groupName][keyName]; - if (values instanceof Element) { - if (values.checked !== defaultValue) { - parsedData[groupName][keyName] = values.checked; } } else { - parsedData[groupName][keyName] = values; + parsedData[groupName][key] = keyPair[key]; } + }); - if (Object.keys(parsedData[groupName]).length == 0) { - delete parsedData[groupName]; - } - if (Object.keys(parsedData).length > 0) { - properties['userData'] = JSON.stringify(parsedData); - } else { - properties['userData'] = ''; - } + if (Object.keys(parsedData[groupName]).length == 0) { + delete parsedData[groupName]; + } + if (Object.keys(parsedData).length > 0) { + properties['userData'] = JSON.stringify(parsedData); + } else { + properties['userData'] = ''; + } - userDataElement.value = properties['userData']; + userDataElement.value = properties['userData']; - EventBridge.emitWebEvent( - JSON.stringify({ - id: lastEntityID, - type: "update", - properties: properties, - }) - ); + EventBridge.emitWebEvent( + JSON.stringify({ + id: lastEntityID, + type: "update", + properties: properties, + }) + ); + +} +function userDataChanger(groupName, keyName, values, userDataElement, defaultValue) { + var val = {}, def = {}; + val[keyName] = values; + def[keyName] = defaultValue; + multiUserDataChanger(groupName, val, userDataElement, def); }; function setTextareaScrolling(element) { @@ -873,15 +890,18 @@ function loaded() { } if ("cloneable" in parsedUserData["grabbableKey"]) { elCloneable.checked = parsedUserData["grabbableKey"].cloneable; - elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; elCloneableLimit.value = elCloneable.checked ? 10: 0; elCloneableLifetime.value = elCloneable.checked ? 300: 0; + elDynamic.checked = elCloneable.checked ? false: properties.dynamic; + } else { elCloneable.checked = false; + elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; elCloneableLimit.value = 0; elCloneableLifetime.value = 0; + } if ("cloneLifetime" in parsedUserData["grabbableKey"]) { elCloneableLifetime.value = parsedUserData["grabbableKey"].cloneLifetime; @@ -1184,14 +1204,24 @@ function loaded() { userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, properties.dynamic); }); elCloneable.addEventListener('change', function (event) { - if (event.target.checked) { - userDataChanger("grabbableKey", "cloneLifetime", 300, elUserData, -1); - userDataChanger("grabbableKey", "cloneLimit", 10, elUserData, -1); + var checked = event.target.checked; + if (checked) { + multiUserDataChanger("grabbableKey", + {cloneLifetime: elCloneableLifetime, cloneLimit: elCloneableLimit, cloneable: event.target}, + elUserData, + {cloneLifetime: 300, cloneLimit: 10, cloneable: false}); elCloneableGroup.style.display = "block"; + EventBridge.emitWebEvent( + '{"id":' + lastEntityID + ', "type":"update", "properties":{"dynamic":false}}' + ); + EventBridge.emitWebEvent( + '{"id":' + lastEntityID + ', "type":"update", "properties":{"grabbable":true}}' + ); } else { elCloneableGroup.style.display = "none"; } - userDataChanger("grabbableKey", "cloneable", event.target, elUserData, null); + + userDataChanger("grabbableKey", "cloneable", checked, elUserData, null); }); var numberListener = function (event) { From 67031850aab6e723a230b8d06507c90b6a9790f1 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 24 Feb 2017 00:05:54 -0800 Subject: [PATCH 033/133] Deep dive into the shape key and filters and the PLumber construction --- libraries/render-utils/src/RenderPipelines.cpp | 4 ++-- libraries/render/src/render/ShapePipeline.cpp | 4 ++++ libraries/render/src/render/ShapePipeline.h | 7 ------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index cbbd1cd193..59d8baacf8 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -84,7 +84,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); auto opaqueMaterialProgram = gpu::Shader::createProgram(vertexModel, pixelMaterial); - for (int i = 0; i < 16; i++) { + for (int i = 0; i < 8; i++) { bool isCulled = (i & 1); bool isBiased = (i & 2); bool isOpaque = (i & 4); @@ -115,7 +115,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build(), simpleProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withMaterial().withoutUnlit().build(), opaqueMaterialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withoutUnlit().withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withUnlit().withoutMaterial().build(), unlitProgram, state, &batchSetter); } } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 48e8ee43d5..cec1971165 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -39,6 +39,10 @@ void ShapePlumber::addPipelineHelper(const Filter& filter, ShapeKey key, int bit } } else { // Add the brand new pipeline and cache its location in the lib + auto precedent = _pipelineMap.find(key); + if (precedent != _pipelineMap.end()) { + qCDebug(renderlogging) << "Key already assigned: " << key; + } _pipelineMap.insert(PipelineMap::value_type(key, pipeline)); } } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index e55c1d4bc4..c7e494ee4c 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -29,7 +29,6 @@ public: SPECULAR, UNLIT, SKINNED, - STEREO, DEPTH_ONLY, DEPTH_BIAS, WIREFRAME, @@ -61,7 +60,6 @@ public: Builder& withSpecular() { _flags.set(SPECULAR); return (*this); } Builder& withUnlit() { _flags.set(UNLIT); return (*this); } Builder& withSkinned() { _flags.set(SKINNED); return (*this); } - Builder& withStereo() { _flags.set(STEREO); return (*this); } Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); } Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } @@ -112,9 +110,6 @@ public: Builder& withSkinned() { _flags.set(SKINNED); _mask.set(SKINNED); return (*this); } Builder& withoutSkinned() { _flags.reset(SKINNED); _mask.set(SKINNED); return (*this); } - Builder& withStereo() { _flags.set(STEREO); _mask.set(STEREO); return (*this); } - Builder& withoutStereo() { _flags.reset(STEREO); _mask.set(STEREO); return (*this); } - Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } Builder& withoutDepthOnly() { _flags.reset(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } @@ -146,7 +141,6 @@ public: bool isUnlit() const { return _flags[UNLIT]; } bool isTranslucent() const { return _flags[TRANSLUCENT]; } bool isSkinned() const { return _flags[SKINNED]; } - bool isStereo() const { return _flags[STEREO]; } bool isDepthOnly() const { return _flags[DEPTH_ONLY]; } bool isDepthBiased() const { return _flags[DEPTH_BIAS]; } bool isWireFrame() const { return _flags[WIREFRAME]; } @@ -183,7 +177,6 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) { << "isUnlit:" << key.isUnlit() << "isTranslucent:" << key.isTranslucent() << "isSkinned:" << key.isSkinned() - << "isStereo:" << key.isStereo() << "isDepthOnly:" << key.isDepthOnly() << "isDepthBiased:" << key.isDepthBiased() << "isWireFrame:" << key.isWireFrame() From e1aad8bd63950baa11b5e520924d07a633f1af49 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 24 Feb 2017 00:35:10 -0800 Subject: [PATCH 034/133] Deep dive into the shape key and filters and the PLumber construction --- .../src/model-networking/TextureCache.cpp | 8 ------- .../src/model-networking/TextureCache.h | 4 ---- libraries/render-utils/src/DeferredBuffer.slh | 21 ------------------- libraries/render-utils/src/GeometryCache.cpp | 15 ------------- .../render-utils/src/RenderPipelines.cpp | 7 ++----- libraries/render/src/render/ShapePipeline.cpp | 5 ----- libraries/render/src/render/ShapePipeline.h | 3 --- 7 files changed, 2 insertions(+), 61 deletions(-) diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index f371207981..8a4e85cfe6 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -154,14 +154,6 @@ const gpu::TexturePointer& TextureCache::getBlackTexture() { return _blackTexture; } - -const gpu::TexturePointer& TextureCache::getNormalFittingTexture() { - if (!_normalFittingTexture) { - _normalFittingTexture = getImageTexture(PathUtils::resourcesPath() + "images/normalFittingScale.dds"); - } - return _normalFittingTexture; -} - /// Extra data for creating textures. class TextureExtra { public: diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index cb509490c6..77311afae6 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -124,9 +124,6 @@ public: /// Returns the a black texture (useful for a default). const gpu::TexturePointer& getBlackTexture(); - // Returns a map used to compress the normals through a fitting scale algorithm - const gpu::TexturePointer& getNormalFittingTexture(); - /// Returns a texture version of an image file static gpu::TexturePointer getImageTexture(const QString& path, Type type = Type::DEFAULT_TEXTURE, QVariantMap options = QVariantMap()); @@ -151,7 +148,6 @@ private: gpu::TexturePointer _grayTexture; gpu::TexturePointer _blueTexture; gpu::TexturePointer _blackTexture; - gpu::TexturePointer _normalFittingTexture; }; #endif // hifi_TextureCache_h diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index a4b69bd70e..a13c2ec5d1 100644 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -65,25 +65,4 @@ float packUnlit() { return FRAG_PACK_UNLIT; } - - <@endif@> diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index c277b9be64..e0dee7b953 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -414,8 +414,6 @@ _nextID(0) { // Set the defaults needed for a simple program batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } ); GeometryCache::_simpleTransparentPipeline = @@ -424,8 +422,6 @@ _nextID(0) { // Set the defaults needed for a simple program batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } ); GeometryCache::_simpleWirePipeline = @@ -1770,7 +1766,6 @@ static void buildWebShader(const std::string& vertShaderText, const std::string& shaderPointerOut = gpu::Shader::createProgram(VS, PS); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); gpu::Shader::makeProgram(*shaderPointerOut, slotBindings); auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_NONE); @@ -1784,9 +1779,6 @@ static void buildWebShader(const std::string& vertShaderText, const std::string& void GeometryCache::bindOpaqueWebBrowserProgram(gpu::Batch& batch, bool isAA) { batch.setPipeline(getOpaqueWebBrowserProgram(isAA)); - // Set a default normal map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } gpu::PipelinePointer GeometryCache::getOpaqueWebBrowserProgram(bool isAA) { @@ -1802,9 +1794,6 @@ gpu::PipelinePointer GeometryCache::getOpaqueWebBrowserProgram(bool isAA) { void GeometryCache::bindTransparentWebBrowserProgram(gpu::Batch& batch, bool isAA) { batch.setPipeline(getTransparentWebBrowserProgram(isAA)); - // Set a default normal map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } gpu::PipelinePointer GeometryCache::getTransparentWebBrowserProgram(bool isAA) { @@ -1827,9 +1816,6 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool tra batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); } - // Set a default normal map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased) { @@ -1846,7 +1832,6 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); gpu::Shader::makeProgram(*_simpleShader, slotBindings); gpu::Shader::makeProgram(*_unlitShader, slotBindings); }); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 59d8baacf8..158daad54c 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -114,9 +114,9 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; - plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build(), simpleProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withoutUnlit().withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withUnlit().withoutMaterial().build(), unlitProgram, state, &batchSetter); + plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); } } @@ -325,9 +325,6 @@ void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { // Set a default albedo map batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); - // Set a default normal map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); // Set a default material if (pipeline.locations->materialBufferUnit >= 0) { diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index cec1971165..1c8e73f5d7 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -69,16 +69,11 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slot::NORMAL_FITTING)); gpu::Shader::makeProgram(*program, slotBindings); auto locations = std::make_shared(); - locations->normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); - if (program->getTextures().findLocation("normalFittingMap") > -1) { - locations->normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); - } locations->albedoTextureUnit = program->getTextures().findLocation("albedoMap"); locations->roughnessTextureUnit = program->getTextures().findLocation("roughnessMap"); locations->normalTextureUnit = program->getTextures().findLocation("normalMap"); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index c7e494ee4c..1e0f1cad76 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -213,8 +213,6 @@ public: OCCLUSION, SCATTERING, LIGHT_AMBIENT, - - NORMAL_FITTING = 10, }; }; @@ -226,7 +224,6 @@ public: int metallicTextureUnit; int emissiveTextureUnit; int occlusionTextureUnit; - int normalFittingMapUnit; int lightingModelBufferUnit; int skinClusterBufferUnit; int materialBufferUnit; From 5257194c4825406920c9aa614a7d7e9e5f2a703f Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 24 Feb 2017 01:11:59 -0800 Subject: [PATCH 035/133] SImplify the overlay PLumber --- libraries/render-utils/src/RenderPipelines.cpp | 7 ++++--- libraries/render-utils/src/overlay3D_model.slf | 4 ++-- libraries/render-utils/src/overlay3D_translucent.slf | 3 ++- libraries/render/src/render/ShapePipeline.h | 1 + 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 158daad54c..508b035a5a 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -114,9 +114,10 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; - plumber.addPipeline(builder.withoutUnlit().withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); + + plumber.addPipeline(builder.withoutUnlit().withMaterial().build().key(), opaqueMaterialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build().key(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withUnlit().withoutMaterial().build().key(), unlitProgram, state, &batchSetter); } } diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index cd4179b112..979a6f2201 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -112,9 +112,9 @@ void main(void) { opacity); color.rgb += emissive; - color.rgb = vec3(0.5, 0.5, 1.0); + // color.rgb = vec3(0.5, 0.5, 1.0); // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 0.9); + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index 0343567127..9f00cdf982 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -82,7 +82,8 @@ void main(void) { fragRoughness, fragOpacity); - color.xyz += vec3(1.0, 0.0, 0.0) * fragOpacity; + color.xyz += vec3(0.0, 1.0, 0.0) * fragOpacity; + color.w = 1.0; // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 1e0f1cad76..0c77a15184 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -128,6 +128,7 @@ public: Flags _mask{0}; }; Filter(const Filter::Builder& builder) : Filter(builder._flags, builder._mask) {} + ShapeKey key() const { return ShapeKey(_flags); } protected: friend class ShapePlumber; Flags _flags{0}; From 2458f95c42398d904fa7d6e7e0829d864169bca0 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 24 Feb 2017 10:31:55 -0800 Subject: [PATCH 036/133] more of a peak loudness with decay, now --- scripts/system/pal.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index fe4eea48a4..bd8a2f5b53 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -197,7 +197,7 @@ HighlightedEntity.updateOverlays = function updateHighlightedEntities() { }); }; -/* this contains current gain for a given node (by session id). More efficient than +/* this contains current gain for a given node (by session id). More efficient than * querying it, plus there isn't a getGain function so why write one */ var sessionGains = {}; function convertDbToLinear(decibels) { @@ -205,7 +205,7 @@ function convertDbToLinear(decibels) { // but, your perception is that something 2x as loud is +10db // so we go from -60 to +20 or 1/64x to 4x. For now, we can // maybe scale the signal this way?? - return Math.pow(2, decibels/10.0); + return Math.pow(2, decibels/10.0); } function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. @@ -571,10 +571,10 @@ function receiveMessage(channel, messageString, senderID) { } var AVERAGING_RATIO = 0.05; -var LONG_AVERAGING_RATIO = 0.75; var LOUDNESS_FLOOR = 11.0; var LOUDNESS_SCALE = 2.8 / 5.0; var LOG2 = Math.log(2.0); +var AUDIO_PEAK_DECAY = 0.03; var myData = {}; // we're not includied in ExtendedOverlay.get. function scaleAudio(val) { @@ -602,16 +602,19 @@ function getAudioLevel(id) { // we will do exponential moving average by taking some the last loudness and averaging data.accumulatedLevel = AVERAGING_RATIO * (data.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatar.audioLoudness); - data.longAccumulatedLevel = LONG_AVERAGING_RATIO * (data.longAccumulatedLevel || 0) + (1 - LONG_AVERAGING_RATIO) * (avatar.audioLoudness); // add 1 to insure we don't go log() and hit -infinity. Math.log is // natural log, so to get log base 2, just divide by ln(2). audioLevel = scaleAudio(Math.log(data.accumulatedLevel + 1) / LOG2); - avgAudioLevel = scaleAudio(Math.log(data.longAccumulatedLevel + 1) / LOG2); - // scale avgAudioLevel given that there can be a gain (4x to 1/64x) - avgAudioLevel = Math.min(1.0, avgAudioLevel *(sessionGains[id] || 0.75)); + + // decay avgAudioLevel + avgAudioLevel = Math.max((1-AUDIO_PEAK_DECAY) * (data.avgAudioLevel || 0), audioLevel); + data.avgAudioLevel = avgAudioLevel; data.audioLevel = audioLevel; + + // now scale for the gain + avgAudioLevel = Math.min(1.0, avgAudioLevel *(sessionGains[id] || 0.75)); } return [audioLevel, avgAudioLevel]; } From a98824f48300179684c5e3817545cbf67de1bfc6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 25 Feb 2017 08:13:15 +1300 Subject: [PATCH 037/133] Code review --- scripts/system/controllers/handControllerGrab.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 5064705f78..fe0fe19ae3 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -417,9 +417,11 @@ function entityIsGrabbedByOther(entityID) { // we see a grab-*uuid* shaped tag, but it's our tag, so that's okay. continue; } - if (tag.slice(0, 5) == "grab-") { + var GRAB_PREFIX_LENGTH = 5; + var UUID_LENGTH = 38; + if (tag.slice(0, GRAB_PREFIX_LENGTH) == "grab-") { // we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. - return tag.slice(5, 42); + return tag.slice(GRAB_PREFIX_LENGTH, GRAB_PREFIX_LENGTH + UUID_LENGTH - 1); } } return null; From d6f0d8c96051179741f61b8f5bfae65cce4122be Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 24 Feb 2017 11:45:03 -0800 Subject: [PATCH 038/133] styling changes, first pass --- interface/resources/qml/hifi/Pal.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 4735ae9312..91889fcf91 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -30,7 +30,7 @@ Rectangle { property int myCardHeight: 90 property int rowHeight: 70 property int actionButtonWidth: 55 - property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 5 : 3) - 4 - hifi.dimensions.scrollbarBackgroundWidth + property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 4.5 : 2.5) - 4 - hifi.dimensions.scrollbarBackgroundWidth property var myData: ({displayName: "", userName: "", audioLevel: 0.0, avgAudioLevel: 0.0, admin: true}) // valid dummy until set property var ignored: ({}); // Keep a local list of ignored avatars & their data. Necessary because HashMap is slow to respond after ignoring. property var userModelData: [] // This simple list is essentially a mirror of the userModel listModel without all the extra complexities. @@ -167,7 +167,7 @@ Rectangle { TableViewColumn { role: "avgAudioLevel" title: "VOL" - width: actionButtonWidth + width: actionButtonWidth/2 movable: false resizable: false } @@ -397,7 +397,7 @@ Rectangle { anchors.left: table.left anchors.top: table.top anchors.topMargin: 1 - anchors.leftMargin: nameCardWidth/2 + displayNameHeaderMetrics.width/2 + 6 + anchors.leftMargin: actionButtonWidth/2 + nameCardWidth/2 + displayNameHeaderMetrics.width/2 + 6 RalewayRegular { id: helpText text: "[?]" From 1b501487fd9eb019cd2894aeb8caba9c49ab623e Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 24 Feb 2017 16:03:28 -0800 Subject: [PATCH 039/133] simple shader checks --- libraries/render-utils/src/overlay3D_model.slf | 6 ++---- scripts/system/pal.js | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index 979a6f2201..75198cdfe4 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -112,10 +112,8 @@ void main(void) { opacity); color.rgb += emissive; - // color.rgb = vec3(0.5, 0.5, 1.0); - // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); - //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 36ecc1f084..962923eeef 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -175,7 +175,8 @@ function HighlightedEntity(id, entityProperties) { }, lineWidth: 1.0, ignoreRayIntersection: true, - drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. + //drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. + drawInFront: true // Arguable. For now, let's not distract with mysterious wires around the scene. }); HighlightedEntity.overlays.push(this); } From 9ffdc03dc9eae75a71df822d1ce6f0cc8ef67d1c Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 24 Feb 2017 18:25:24 -0800 Subject: [PATCH 040/133] setting the shaeKeys for the overly properly because most of them are CustomPipleline --- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- libraries/render-utils/src/MeshPartPayload.h | 3 ++- libraries/render-utils/src/overlay3D_model.slf | 7 +++++-- libraries/render-utils/src/overlay3D_translucent.slf | 4 ++-- 10 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index ae0173f054..b51f83ec87 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -263,7 +263,7 @@ void Circle3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Circle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 8af4c1d908..3cb3c6115d 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -116,7 +116,7 @@ void Cube3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Cube3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 45d63d9cf1..2350ec36ab 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -116,7 +116,7 @@ void Image3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Image3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline(); if (_emissive) { builder.withUnlit(); } diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index 2556bc84aa..d64f6db9df 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -61,7 +61,7 @@ void Shape3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Shape3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 07c2861f16..0c3dd48094 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -58,7 +58,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Sphere3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 2e2d586abc..41dabe83fd 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -132,7 +132,7 @@ void Text3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Text3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index bfc37ccf60..96051beb2b 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -275,7 +275,7 @@ void Web3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Web3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index c585c95025..fa8742c40c 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -118,7 +118,8 @@ public: private: mutable quint64 _fadeStartTime { 0 }; - mutable uint8_t _fadeState { FADE_WAITING_TO_START }; + //mutable uint8_t _fadeState { FADE_WAITING_TO_START }; + mutable uint8_t _fadeState { FADE_COMPLETE }; }; namespace render { diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index 75198cdfe4..6c21f95a91 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -112,8 +112,11 @@ void main(void) { opacity); color.rgb += emissive; - - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + color.rgb += vec3(1, 0.0, 0.0); + // Apply standard tone mapping + // _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); + _fragColor = vec4(albedo, 0.5); + //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index 9f00cdf982..3604fd88c5 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -82,8 +82,8 @@ void main(void) { fragRoughness, fragOpacity); - color.xyz += vec3(0.0, 1.0, 0.0) * fragOpacity; - color.w = 1.0; + // color.xyz += vec3(0.0, 1.0, 0.0) * fragOpacity; + // color.w = 1.0; // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); From a53d5e8fbddd2ea03d30528fea17e6914e0b9b83 Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 25 Feb 2017 13:00:37 -0800 Subject: [PATCH 041/133] adjusted the PLumber shape keys to coever non material shapes in main pass --- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- libraries/render-utils/src/MeshPartPayload.h | 4 ++-- libraries/render-utils/src/RenderDeferredTask.cpp | 6 ++---- libraries/render-utils/src/RenderPipelines.cpp | 9 +++++++++ libraries/render-utils/src/overlay3D_model.slf | 6 +++--- libraries/render-utils/src/overlay3D_translucent.slf | 3 --- 12 files changed, 23 insertions(+), 19 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index b51f83ec87..ae0173f054 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -263,7 +263,7 @@ void Circle3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Circle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit().withOwnPipeline(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 3cb3c6115d..8af4c1d908 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -116,7 +116,7 @@ void Cube3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Cube3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 2350ec36ab..45d63d9cf1 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -116,7 +116,7 @@ void Image3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Image3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (_emissive) { builder.withUnlit(); } diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index d64f6db9df..2556bc84aa 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -61,7 +61,7 @@ void Shape3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Shape3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 0c3dd48094..07c2861f16 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -58,7 +58,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Sphere3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 41dabe83fd..2e2d586abc 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -132,7 +132,7 @@ void Text3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Text3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 96051beb2b..bfc37ccf60 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -275,7 +275,7 @@ void Web3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Web3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index fa8742c40c..9d021f4f34 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -118,8 +118,8 @@ public: private: mutable quint64 _fadeStartTime { 0 }; - //mutable uint8_t _fadeState { FADE_WAITING_TO_START }; - mutable uint8_t _fadeState { FADE_COMPLETE }; + mutable uint8_t _fadeState { FADE_WAITING_TO_START }; + // mutable uint8_t _fadeState { FADE_COMPLETE }; }; namespace render { diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 55a9c8b9e4..5d03cac58f 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -75,7 +75,6 @@ RenderDeferredTask::RenderDeferredTask(RenderFetchCullSortTask::Output items) { // GPU jobs: Start preparing the primary, deferred and lighting buffer const auto primaryFramebuffer = addJob("PreparePrimaryBuffer"); - // const auto fullFrameRangeTimer = addJob("BeginRangeTimer"); const auto opaqueRangeTimer = addJob("BeginOpaqueRangeTimer", "DrawOpaques"); const auto prepareDeferredInputs = PrepareDeferred::Inputs(primaryFramebuffer, lightingModel).hasVarying(); @@ -167,6 +166,8 @@ RenderDeferredTask::RenderDeferredTask(RenderFetchCullSortTask::Output items) { // Bounds do not draw on stencil buffer, so they must come last addJob("DrawMetaBounds", metas); + addJob("DrawOverlaysOpaques", overlayOpaques); + addJob("DrawOverlaysTransparents", overlayTransparents); // Debugging Deferred buffer job const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer)); @@ -207,9 +208,6 @@ RenderDeferredTask::RenderDeferredTask(RenderFetchCullSortTask::Output items) { // Blit! addJob("Blit", primaryFramebuffer); - - // addJob("RangeTimer", fullFrameRangeTimer); - } void BeginGPURangeTimer::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::RangeTimerPointer& timer) { diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 508b035a5a..93bc7b77df 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -156,6 +156,9 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); + addPipeline( + Key::Builder().withUnlit(), + modelVertex, modelUnlitPixel); addPipeline( Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); @@ -169,9 +172,15 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withTranslucent(), modelVertex, modelTranslucentPixel); + addPipeline( + Key::Builder().withTranslucent(), + modelVertex, modelTranslucentPixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withUnlit(), modelVertex, modelTranslucentUnlitPixel); + addPipeline( + Key::Builder().withTranslucent().withUnlit(), + modelVertex, modelTranslucentUnlitPixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index 6c21f95a91..42c08d21bc 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -114,9 +114,9 @@ void main(void) { color.rgb += emissive; color.rgb += vec3(1, 0.0, 0.0); // Apply standard tone mapping - // _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); - _fragColor = vec4(albedo, 0.5); - //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); + //_fragColor = vec4(albedo, 0.5); + // _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index 3604fd88c5..9bdac2d21f 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -82,9 +82,6 @@ void main(void) { fragRoughness, fragOpacity); - // color.xyz += vec3(0.0, 1.0, 0.0) * fragOpacity; - // color.w = 1.0; - // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); } From 69949cd6b56c18bd173b9a59a209038c8e41d24f Mon Sep 17 00:00:00 2001 From: Menithal Date: Sun, 26 Feb 2017 18:49:13 +0200 Subject: [PATCH 042/133] Finalized Grab-Clone action --- .../system/controllers/handControllerGrab.js | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index ea76490b7b..7f67c11a7c 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -266,6 +266,27 @@ CONTROLLER_STATE_MACHINE[STATE_OVERLAY_STYLUS_TOUCHING] = { }; CONTROLLER_STATE_MACHINE[STATE_OVERLAY_LASER_TOUCHING] = CONTROLLER_STATE_MACHINE[STATE_OVERLAY_STYLUS_TOUCHING]; +// Object assign polyfill +if (typeof Object.assign != 'function') { + Object.assign = function(target, varArgs) { + 'use strict'; + if (target == null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + var to = Object(target); + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + if (nextSource != null) { + for (var nextKey in nextSource) { + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + }; +} function distanceBetweenPointAndEntityBoundingBox(point, entityProps) { var entityXform = new Xform(entityProps.rotation, entityProps.position); @@ -1437,7 +1458,18 @@ function MyController(hand) { return true; }; + this.entityIsCloneable = function(entityID) { + var entityProps = entityPropertiesCache.getGrabbableProps(entityID); + var props = entityPropertiesCache.getProps(entityID); + if (!props) { + return false; + } + if (entityProps.hasOwnProperty("cloneable")/*&& props.locked*/) { + return entityProps.cloneable; + } + return false; + } this.entityIsGrabbable = function(entityID) { var grabbableProps = entityPropertiesCache.getGrabbableProps(entityID); var props = entityPropertiesCache.getProps(entityID); @@ -1517,7 +1549,7 @@ function MyController(hand) { this.entityIsNearGrabbable = function(entityID, handPosition, maxDistance) { - if (!this.entityIsGrabbable(entityID)) { + if (!this.entityIsCloneable(entityID) && !this.entityIsGrabbable(entityID)) { return false; } @@ -2359,6 +2391,55 @@ function MyController(hand) { reparentProps.localPosition = this.offsetPosition; reparentProps.localRotation = this.offsetRotation; } + + if (grabbedProperties.userData.length > 0) { + try{ + var userData = JSON.parse(grabbedProperties.userData); + var grabInfo = userData.grabbableKey; + if (grabInfo && grabInfo.cloneable) { + + var worldEntities = Entities.findEntitiesInBox(Vec3.subtract(MyAvatar.position, {x:25,y:25, z:25}), {x:50, y: 50, z: 50}) + var count = 0; + worldEntities.forEach(function(item) { + var item = Entities.getEntityProperties(item, ["name"]); + if (item.name === grabbedProperties.name) { + count++; + } + }) + var cloneableProps = Entities.getEntityProperties(grabbedProperties.id); + var lifetime = grabInfo.cloneLifetime ? grabInfo.cloneLifetime : 300; + var limit = grabInfo.cloneLimit ? grabInfo.cloneLimit : 10; + var cUserData = Object.assign({}, userData); + var cProperties = Object.assign({}, cloneableProps); + + if (count > limit) { + delete cloneableProps; + delete lifetime; + delete cUserData; + delete cProperties; + return; + } + + delete cUserData.grabbableKey.cloneLifetime; + delete cUserData.grabbableKey.cloneable; + delete cUserData.grabbableKey.cloneLimit; + delete cProperties.id + cUserData.grabbableKey.triggerable = true; + cUserData.grabbableKey.grabbable = true; + cProperties.lifetime = lifetime; + cProperties.userData = JSON.stringify(cUserData); + this.grabbedEntity = Entities.addEntity(cProperties); + grabbedProperties = Entities.getEntityProperties(this.grabbedEntity); + var _this = this; + Script.setTimeout(function () { + // This is needed to wait for the grabbed entity to have been instanciated. + _this.callEntityMethodOnGrabbed("startEquip"); + },400); + } + }catch(e) { + print("ERROR: " + e); + } + } Entities.editEntity(this.grabbedEntity, reparentProps); if (this.thisHandIsParent(grabbedProperties)) { From 1d8be2aeaa682c3fa33b65077f6eb3543c09a995 Mon Sep 17 00:00:00 2001 From: Menithal Date: Sun, 26 Feb 2017 19:17:46 +0200 Subject: [PATCH 043/133] Added missing dynamic --- scripts/system/controllers/handControllerGrab.js | 5 +++++ scripts/system/html/entityProperties.html | 4 ++++ scripts/system/html/js/entityProperties.js | 12 +++++++----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 7f67c11a7c..4b469798ab 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2409,6 +2409,7 @@ function MyController(hand) { var cloneableProps = Entities.getEntityProperties(grabbedProperties.id); var lifetime = grabInfo.cloneLifetime ? grabInfo.cloneLifetime : 300; var limit = grabInfo.cloneLimit ? grabInfo.cloneLimit : 10; + var dynamic = grabInfo.cloneDynamic ? grabInfo.cloneDynamic : false; var cUserData = Object.assign({}, userData); var cProperties = Object.assign({}, cloneableProps); @@ -2422,8 +2423,12 @@ function MyController(hand) { delete cUserData.grabbableKey.cloneLifetime; delete cUserData.grabbableKey.cloneable; + delete cUserData.grabbableKey.cloneDynamic; delete cUserData.grabbableKey.cloneLimit; delete cProperties.id + + cProperties.dynamic = dynamic; + cProperties.locked = false; cUserData.grabbableKey.triggerable = true; cUserData.grabbableKey.grabbable = true; cProperties.lifetime = lifetime; diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index e775be9e3a..a0497d6a92 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -312,6 +312,10 @@
+
+ + +
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index abffdaee96..2c77d54e85 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -603,7 +603,7 @@ function loaded() { var elGrabbable = document.getElementById("property-grabbable"); var elCloneable = document.getElementById("property-cloneable"); - + var elCloneableDynamic = document.getElementById("property-cloneable-dynamic"); var elCloneableGroup = document.getElementById("group-cloneable-group"); var elCloneableLifetime = document.getElementById("property-cloneable-lifetime"); var elCloneableLimit = document.getElementById("property-cloneable-limit"); @@ -893,15 +893,14 @@ function loaded() { elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; elCloneableLimit.value = elCloneable.checked ? 10: 0; elCloneableLifetime.value = elCloneable.checked ? 300: 0; + elCloneableDynamic.checked = parsedUserData["grabbableKey"].cloneDynamic ? parsedUserData["grabbableKey"].cloneDynamic : properties.dynamic; elDynamic.checked = elCloneable.checked ? false: properties.dynamic; - } else { elCloneable.checked = false; - + elCloneableDynamic.checked = false; elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; elCloneableLimit.value = 0; elCloneableLifetime.value = 0; - } if ("cloneLifetime" in parsedUserData["grabbableKey"]) { elCloneableLifetime.value = parsedUserData["grabbableKey"].cloneLifetime; @@ -1203,11 +1202,14 @@ function loaded() { elGrabbable.addEventListener('change', function() { userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, properties.dynamic); }); + elCloneableDynamic.addEventListener('change', function (event){ + userDataChanger("grabbableKey", "cloneDynamic", event.target, elUserData, -1); + }); elCloneable.addEventListener('change', function (event) { var checked = event.target.checked; if (checked) { multiUserDataChanger("grabbableKey", - {cloneLifetime: elCloneableLifetime, cloneLimit: elCloneableLimit, cloneable: event.target}, + {cloneLifetime: elCloneableLifetime, cloneLimit: elCloneableLimit, cloneDynamic: elCloneableDynamic, cloneable: event.target}, elUserData, {cloneLifetime: 300, cloneLimit: 10, cloneable: false}); elCloneableGroup.style.display = "block"; From 7472efc6376f0abf87aa8536ff79b9eff4b2b75d Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 23 Feb 2017 18:52:10 -0800 Subject: [PATCH 044/133] don't count NoData avatars as having been broadcast, fix avatars slightly out of view from freezing --- .../src/avatars/AvatarMixerSlave.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 8d9a5e6951..dd25aa4c4b 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -384,18 +384,20 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { if (includeThisAvatar) { numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122()); numAvatarDataBytes += avatarPacketList->write(bytes); - _stats.numOthersIncluded++; - // increment the number of avatars sent to this reciever - nodeData->incrementNumAvatarsSentLastFrame(); + if (detail != AvatarData::NoData) { + _stats.numOthersIncluded++; - // set the last sent sequence number for this sender on the receiver - nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(), - otherNodeData->getLastReceivedSequenceNumber()); + // increment the number of avatars sent to this reciever + nodeData->incrementNumAvatarsSentLastFrame(); - // remember the last time we sent details about this other node to the receiver - nodeData->setLastBroadcastTime(otherNode->getUUID(), start); + // set the last sent sequence number for this sender on the receiver + nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(), + otherNodeData->getLastReceivedSequenceNumber()); + // remember the last time we sent details about this other node to the receiver + nodeData->setLastBroadcastTime(otherNode->getUUID(), start); + } } avatarPacketList->endSegment(); From 709c2e4240b038ecc109b4e189957569d8876a5c Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 27 Feb 2017 02:52:00 -0800 Subject: [PATCH 045/133] Fixing the emissive on overlayfor models --- .../render-utils/src/RenderDeferredTask.cpp | 19 +++-- .../render-utils/src/RenderPipelines.cpp | 12 ++- .../render-utils/src/overlay3D_model.slf | 70 +++------------- .../src/overlay3D_model_translucent.slf | 83 +++++++++++++++++++ .../utilities/render/deferredLighting.qml | 24 +++++- 5 files changed, 135 insertions(+), 73 deletions(-) create mode 100644 libraries/render-utils/src/overlay3D_model_translucent.slf diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 5d03cac58f..676d176cca 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -153,22 +153,25 @@ RenderDeferredTask::RenderDeferredTask(RenderFetchCullSortTask::Output items) { const auto toneMappingInputs = render::Varying(ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer)); addJob("ToneMapping", toneMappingInputs); + { // DEbug the bounds of the rendered items, still look at the zbuffer + addJob("DrawMetaBounds", metas); + addJob("DrawOpaqueBounds", opaques); + addJob("DrawTransparentBounds", transparents); + } + // Overlays const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).hasVarying(); const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).hasVarying(); addJob("DrawOverlay3DOpaque", overlayOpaquesInputs, true); addJob("DrawOverlay3DTransparent", overlayTransparentsInputs, false); + { // DEbug the bounds of the rendered OVERLAY items, still look at the zbuffer + addJob("DrawOverlayOpaqueBounds", overlayOpaques); + addJob("DrawOverlayTransparentBounds", overlayTransparents); + } - // Debugging stages + // Debugging stages { - - - // Bounds do not draw on stencil buffer, so they must come last - addJob("DrawMetaBounds", metas); - addJob("DrawOverlaysOpaques", overlayOpaques); - addJob("DrawOverlaysTransparents", overlayTransparents); - // Debugging Deferred buffer job const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer)); addJob("DebugDeferredBuffer", debugFramebuffers); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 93bc7b77df..d753c679c6 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -51,6 +51,7 @@ #include "overlay3D_vert.h" #include "overlay3D_frag.h" #include "overlay3D_model_frag.h" +#include "overlay3D_model_translucent_frag.h" #include "overlay3D_translucent_frag.h" #include "overlay3D_unlit_frag.h" #include "overlay3D_translucent_unlit_frag.h" @@ -72,17 +73,19 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); auto vertexModel = gpu::Shader::createVertex(std::string(model_vert)); - auto pixel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); + auto pixel = gpu::Shader::createPixel(std::string(overlay3D_frag)); auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag)); auto pixelUnlit = gpu::Shader::createPixel(std::string(overlay3D_unlit_frag)); auto pixelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_translucent_unlit_frag)); - auto pixelMaterial = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); + auto pixelModel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); + auto pixelModelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_model_translucent_frag)); auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel); auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit); auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); - auto opaqueMaterialProgram = gpu::Shader::createProgram(vertexModel, pixelMaterial); + auto materialOpaqueProgram = gpu::Shader::createProgram(vertexModel, pixelModel); + auto materialTranslucentProgram = gpu::Shader::createProgram(vertexModel, pixelModelTranslucent); for (int i = 0; i < 8; i++) { bool isCulled = (i & 1); @@ -114,8 +117,9 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; + auto materialProgram = isOpaque ? materialOpaqueProgram : materialTranslucentProgram; - plumber.addPipeline(builder.withoutUnlit().withMaterial().build().key(), opaqueMaterialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withMaterial().build().key(), materialProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build().key(), simpleProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withUnlit().withoutMaterial().build().key(), unlitProgram, state, &batchSetter); } diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index 42c08d21bc..bb0d84a513 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -11,15 +11,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - -<@include model/Light.slh@> -<$declareLightBuffer()$> -<$declareLightAmbientBuffer()$> - -<@include LightingModel.slh@> - -<@include LightDirectional.slh@> -<$declareLightingDirectional()$> +<@include DeferredGlobalLight.slh@> +<$declareEvalSkyboxGlobalColor()$> <@include model/Material.slh@> @@ -29,35 +22,6 @@ <@include MaterialTextures.slh@> <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> -vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) { - - // Need the light now - Light light = getLight(); - vec3 lightDirection = getLightDirection(light); - vec3 lightIrradiance = getLightIrradiance(light); - - LightAmbient ambient = getLightAmbient(); - - TransformCamera cam = getTransformCamera(); - vec3 fragNormal; - <$transformEyeToWorldDir(cam, normal, fragNormal)$> - vec3 fragEyeVectorView = normalize(-position); - vec3 fragEyeDir; - <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> - - vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient); - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); - color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled(); - color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled(); - - return vec4(color, opacity); -} - - in vec2 _texCoord0; in vec2 _texCoord1; in vec4 _position; @@ -98,27 +62,13 @@ void main(void) { vec3 fragPosition = _position.xyz; - vec3 fragNormal = normalize(_normal); + //vec3 fragNormal = normalize(_normal); TransformCamera cam = getTransformCamera(); + vec3 fragNormal; + <$transformEyeToWorldDir(cam, _normal, fragNormal)$>; - vec4 color = evalGlobalColor(occlusionTex, - fragPosition, - fragNormal, - albedo, - metallic, - fresnel, - roughness, - opacity); - - color.rgb += emissive; - color.rgb += vec3(1, 0.0, 0.0); - // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); - //_fragColor = vec4(albedo, 0.5); - // _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); - - /*_fragColor = vec4(evalGlobalLightingAlphaBlended( + vec4 color = vec4(evalSkyboxGlobalColor( cam._viewInverse, 1.0, occlusionTex, @@ -127,10 +77,12 @@ void main(void) { albedo, fresnel, metallic, - emissive, - roughness, opacity), + roughness), opacity); + // And emissive + color.rgb += emissive * isEmissiveEnabled(); + // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);*/ + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); } \ No newline at end of file diff --git a/libraries/render-utils/src/overlay3D_model_translucent.slf b/libraries/render-utils/src/overlay3D_model_translucent.slf new file mode 100644 index 0000000000..748eea329c --- /dev/null +++ b/libraries/render-utils/src/overlay3D_model_translucent.slf @@ -0,0 +1,83 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// overlay3D_model_transparent.slf +// +// Created by Sam Gateau on 2/27/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 +// + +<@include DeferredGlobalLight.slh@> +<$declareEvalGlobalLightingAlphaBlended()$> + +<@include model/Material.slh@> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec4 _position; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float metallic = getMaterialMetallic(mat); + vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value + if (metallic <= 0.5) { + metallic = 0.0; + } else { + fresnel = albedo; + metallic = 1.0; + } + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + + vec3 fragPosition = _position.xyz; + + TransformCamera cam = getTransformCamera(); + vec3 fragNormal; + <$transformEyeToWorldDir(cam, _normal, fragNormal)$> + + vec4 color = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + occlusionTex, + fragPosition, + fragNormal, + albedo, + fresnel, + metallic, + emissive, + roughness, opacity), + opacity); + + // Apply standard tone mapping + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); +} \ No newline at end of file diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 0ac4cbc5b5..99a9f258e3 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -159,13 +159,33 @@ Column { } } - Row { + Column { id: metas CheckBox { - text: "Draw Meta Bounds" + text: "Metas" checked: Render.getConfig("DrawMetaBounds")["enabled"] onCheckedChanged: { Render.getConfig("DrawMetaBounds")["enabled"] = checked } } + CheckBox { + text: "Opaques" + checked: Render.getConfig("DrawOpaqueBounds")["enabled"] + onCheckedChanged: { Render.getConfig("DrawOpaqueBounds")["enabled"] = checked } + } + CheckBox { + text: "Transparents" + checked: Render.getConfig("DrawTransparentBounds")["enabled"] + onCheckedChanged: { Render.getConfig("DrawTransparentBounds")["enabled"] = checked } + } + CheckBox { + text: "Overlay Opaques" + checked: Render.getConfig("DrawOverlayOpaqueBounds")["enabled"] + onCheckedChanged: { Render.getConfig("DrawOverlayOpaqueBounds")["enabled"] = checked } + } + CheckBox { + text: "Overlay Transparents" + checked: Render.getConfig("DrawOverlayTransparentBounds")["enabled"] + onCheckedChanged: { Render.getConfig("DrawOverlayTransparentBounds")["enabled"] = checked } + } } } From 2ceb3d85bd6481179f3c14270169f6013fdf13c4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 24 Feb 2017 16:03:22 -0800 Subject: [PATCH 046/133] increase max renderable web entity FPS to 30 --- libraries/entities-renderer/src/RenderableWebEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 972c23d534..8c30c01e50 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -113,7 +113,7 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // and the current rendering load) - _webSurface->setMaxFps(10); + _webSurface->setMaxFps(30); // The lifetime of the QML surface MUST be managed by the main thread // Additionally, we MUST use local variables copied by value, rather than From d18936ea1864063ede40cb8cae4c9a66caa8b038 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 27 Feb 2017 09:43:02 -0800 Subject: [PATCH 047/133] only force youtube web entities to 30 FPS --- .../entities-renderer/src/RenderableWebEntityItem.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 8c30c01e50..7cd1b62e3b 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -113,7 +113,14 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // and the current rendering load) - _webSurface->setMaxFps(30); + + // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. + if (QUrl(_sourceUrl).host().endsWith("youtube.com", Qt::CaseInsensitive)) { + _webSurface->setMaxFps(30); + } else { + _webSurface->setMaxFps(10); + } + // The lifetime of the QML surface MUST be managed by the main thread // Additionally, we MUST use local variables copied by value, rather than From 80af749b6949cbd66ba9309cce51019d611457d7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 27 Feb 2017 11:09:17 -0800 Subject: [PATCH 048/133] change max FPS for youtube on URL change --- .../src/RenderableWebEntityItem.cpp | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 7cd1b62e3b..6c44794c3e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -37,6 +37,8 @@ static uint64_t MAX_NO_RENDER_INTERVAL = 30 * USECS_PER_SECOND; static int MAX_WINDOW_SIZE = 4096; static float OPAQUE_ALPHA_THRESHOLD = 0.99f; +static int DEFAULT_MAX_FPS = 10; +static int YOUTUBE_MAX_FPS = 30; EntityItemPointer RenderableWebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity{ new RenderableWebEntityItem(entityID) }; @@ -113,14 +115,7 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // and the current rendering load) - - // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. - if (QUrl(_sourceUrl).host().endsWith("youtube.com", Qt::CaseInsensitive)) { - _webSurface->setMaxFps(30); - } else { - _webSurface->setMaxFps(10); - } - + _webSurface->setMaxFps(DEFAULT_MAX_FPS); // The lifetime of the QML surface MUST be managed by the main thread // Additionally, we MUST use local variables copied by value, rather than @@ -263,12 +258,22 @@ void RenderableWebEntityItem::loadSourceURL() { _sourceUrl.toLower().endsWith(".htm") || _sourceUrl.toLower().endsWith(".html")) { _contentType = htmlContent; _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "qml/controls/")); + + // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. + if (sourceUrl.host().endsWith("youtube.com", Qt::CaseInsensitive)) { + _webSurface->setMaxFps(YOUTUBE_MAX_FPS); + } else { + _webSurface->setMaxFps(DEFAULT_MAX_FPS); + } + _webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) { context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject)); }); _webSurface->getRootItem()->setProperty("url", _sourceUrl); _webSurface->getRootContext()->setContextProperty("desktop", QVariant()); + + } else { _contentType = qmlContent; _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath())); From e7c8085bc8ff5c796a73502289a8e4d7473a4817 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 27 Feb 2017 12:44:23 -0700 Subject: [PATCH 049/133] switch to using glyph button --- .../images/Audio-Loudness-Icons/vol-0.svg | 12 ------- .../images/Audio-Loudness-Icons/vol-1.svg | 13 ------- .../images/Audio-Loudness-Icons/vol-2.svg | 16 --------- .../images/Audio-Loudness-Icons/vol-3.svg | 19 ---------- .../images/Audio-Loudness-Icons/vol-4.svg | 21 ----------- interface/resources/qml/hifi/Pal.qml | 36 ++++++------------- .../qml/styles-uit/HifiConstants.qml | 10 ++++++ 7 files changed, 20 insertions(+), 107 deletions(-) delete mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-0.svg delete mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-1.svg delete mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-2.svg delete mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-3.svg delete mode 100755 interface/resources/images/Audio-Loudness-Icons/vol-4.svg diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-0.svg b/interface/resources/images/Audio-Loudness-Icons/vol-0.svg deleted file mode 100755 index 72f247c238..0000000000 --- a/interface/resources/images/Audio-Loudness-Icons/vol-0.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-1.svg b/interface/resources/images/Audio-Loudness-Icons/vol-1.svg deleted file mode 100755 index 9570b9ae6c..0000000000 --- a/interface/resources/images/Audio-Loudness-Icons/vol-1.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-2.svg b/interface/resources/images/Audio-Loudness-Icons/vol-2.svg deleted file mode 100755 index a2175be39e..0000000000 --- a/interface/resources/images/Audio-Loudness-Icons/vol-2.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-3.svg b/interface/resources/images/Audio-Loudness-Icons/vol-3.svg deleted file mode 100755 index 21b1095941..0000000000 --- a/interface/resources/images/Audio-Loudness-Icons/vol-3.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-4.svg b/interface/resources/images/Audio-Loudness-Icons/vol-4.svg deleted file mode 100755 index de0b4027eb..0000000000 --- a/interface/resources/images/Audio-Loudness-Icons/vol-4.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index a7651e24d9..1db83a0223 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -214,13 +214,6 @@ Rectangle { movable: false resizable: false } - //TableViewColumn { - // role: "personalMute" - // title: "MUTE" - // width: actionButtonWidth - // movable: false - // resizable: false - //} TableViewColumn { role: "ignore" title: "IGNORE" @@ -283,12 +276,19 @@ Rectangle { // Anchors anchors.left: parent.left } - HifiControls.Button { + HifiControls.GlyphButton { + function getGlyph() { + var fileName = "vol_"; + if (model["personalMute"]) { + fileName += "x_"; + } + fileName += (4.0*(model ? model.avgAudioLevel : 0.0)).toFixed(0); + return hifi.glyphs[fileName]; + } id: avgAudioVolume visible: isAvgAudio + glyph: getGlyph() width: 32 - height: 32 - iconSource: getImage() anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter onClicked: { @@ -298,22 +298,6 @@ Rectangle { Users["personalMute"](model.sessionId, newValue) UserActivityLogger["palAction"](newValue ? "personalMute" : "un-personalMute", model.sessionId) } - HiFiGlyphs { - function getGlyph() { - var fileName = "vol-"; - if (model["personalMute"]) { - fileName += "x-"; - } - fileName += (4.0*(model ? model.avgAudioLevel : 0.0)).toFixed(0); - return hifi.glyphs[fileName]; - } - text: getGlyph() - size: parent.height*1.3 - anchors.fill: parent - horizontalAlignment: Text.AlignHCenter - color: enabled ? hifi.buttons.textColor[actionButton.color] - : hifi.buttons.disabledTextColor[actionButton.colorScheme] - } } // This CheckBox belongs in the columns that contain the stateful action buttons ("Mute" & "Ignore" for now) // KNOWN BUG with the Checkboxes: When clicking in the center of the sorting header, the checkbox diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index e261e2198f..031e80283e 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -318,5 +318,15 @@ Item { readonly property string deg: "\\" readonly property string px: "|" readonly property string editPencil: "\ue00d" + readonly property string vol_0: "\ue00e" + readonly property string vol_1: "\ue00f" + readonly property string vol_2: "\ue010" + readonly property string vol_3: "\ue011" + readonly property string vol_4: "\ue012" + readonly property string vol_x_0: "\ue013" + readonly property string vol_x_1: "\ue014" + readonly property string vol_x_2: "\ue015" + readonly property string vol_x_3: "\ue016" + readonly property string vol_x_4: "\ue017" } } From 3bf3f16a6ab53576d2d11d6dae901a8d0918e144 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 27 Feb 2017 12:56:03 -0700 Subject: [PATCH 050/133] whitespace --- interface/resources/qml/hifi/Pal.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 1db83a0223..f8b2f6ed25 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -32,7 +32,7 @@ Rectangle { property int rowHeight: 70 property int actionButtonWidth: 55 property int actionButtonAllowance: actionButtonWidth * 2 - property int minNameCardWidth: palContainer.width - (actionButtonAllowance * 2 ) - 4 - hifi.dimensions.scrollbarBackgroundWidth + property int minNameCardWidth: palContainer.width - (actionButtonAllowance * 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth property int nameCardWidth: minNameCardWidth + (iAmAdmin ? 0 : actionButtonAllowance) property var myData: ({displayName: "", userName: "", audioLevel: 0.0, avgAudioLevel: 0.0, admin: true}) // valid dummy until set property var ignored: ({}); // Keep a local list of ignored avatars & their data. Necessary because HashMap is slow to respond after ignoring. From f4a3627b767294133ef060ad5e74630721d29093 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Feb 2017 09:47:36 +1300 Subject: [PATCH 051/133] Make other avatar's grab beam start at more natural position --- scripts/system/controllers/handControllerGrab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index fe0fe19ae3..1ab06927ac 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1729,7 +1729,7 @@ function MyController(hand) { } else if (this.otherGrabbingUUID !== null) { if (this.triggerSmoothedGrab() && !isEditing() && farGrabEnabled && farSearching) { var avatar = AvatarList.getAvatar(this.otherGrabbingUUID); - var IN_FRONT_OF_AVATAR = { x: 0, y: 0, z: 0.2 }; + var IN_FRONT_OF_AVATAR = { x: 0, y: 0.2, z: 0.4 }; // Up from hips and in front of avatar. var startPosition = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.rotation, IN_FRONT_OF_AVATAR)); this.otherGrabbingLineOn(startPosition, rayPickInfo.properties.position, COLORS_GRAB_DISTANCE_HOLD); } else { From 08cae1d3f23c74b34a4bcb9349b0a8b68a3fc61e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Feb 2017 10:02:06 +1300 Subject: [PATCH 052/133] Make other avatar's grab beam finish at entity's centroid --- scripts/system/controllers/handControllerGrab.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 1ab06927ac..cdfb33ee06 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1731,7 +1731,11 @@ function MyController(hand) { var avatar = AvatarList.getAvatar(this.otherGrabbingUUID); var IN_FRONT_OF_AVATAR = { x: 0, y: 0.2, z: 0.4 }; // Up from hips and in front of avatar. var startPosition = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.rotation, IN_FRONT_OF_AVATAR)); - this.otherGrabbingLineOn(startPosition, rayPickInfo.properties.position, COLORS_GRAB_DISTANCE_HOLD); + var finishPisition = Vec3.sum(rayPickInfo.properties.position, // Entity's centroid. + Vec3.multiplyQbyV(rayPickInfo.properties.rotation , + Vec3.multiplyVbyV(rayPickInfo.properties.dimensions, + Vec3.subtract(DEFAULT_REGISTRATION_POINT, rayPickInfo.properties.registrationPoint)))); + this.otherGrabbingLineOn(startPosition, finishPisition, COLORS_GRAB_DISTANCE_HOLD); } else { this.otherGrabbingLineOff(); } From 6fcc096bcf57cd2d3429906e3ceec3e16dd5e140 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Feb 2017 10:14:38 +1300 Subject: [PATCH 053/133] Fix JavaScript error --- scripts/system/controllers/handControllerGrab.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index cdfb33ee06..3df7b91b6a 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -413,13 +413,13 @@ function entityIsGrabbedByOther(entityID) { var actionID = actionIDs[actionIndex]; var actionArguments = Entities.getActionArguments(entityID, actionID); var tag = actionArguments.tag; - if (tag == getTag()) { + if (tag === getTag()) { // we see a grab-*uuid* shaped tag, but it's our tag, so that's okay. continue; } var GRAB_PREFIX_LENGTH = 5; var UUID_LENGTH = 38; - if (tag.slice(0, GRAB_PREFIX_LENGTH) == "grab-") { + if (tag && tag.slice(0, GRAB_PREFIX_LENGTH) == "grab-") { // we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. return tag.slice(GRAB_PREFIX_LENGTH, GRAB_PREFIX_LENGTH + UUID_LENGTH - 1); } From 9fbde41dc45508324ac1feef09f647cc51b39c44 Mon Sep 17 00:00:00 2001 From: Menithal Date: Mon, 27 Feb 2017 23:27:48 +0200 Subject: [PATCH 054/133] Styling formating and Rebuild attempt --- .../system/controllers/handControllerGrab.js | 99 ++++++++++--------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 4b469798ab..ad6adf7722 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1465,7 +1465,7 @@ function MyController(hand) { return false; } - if (entityProps.hasOwnProperty("cloneable")/*&& props.locked*/) { + if (entityProps.hasOwnProperty("cloneable")) { return entityProps.cloneable; } return false; @@ -2393,57 +2393,58 @@ function MyController(hand) { } if (grabbedProperties.userData.length > 0) { - try{ - var userData = JSON.parse(grabbedProperties.userData); - var grabInfo = userData.grabbableKey; - if (grabInfo && grabInfo.cloneable) { + try{ + var userData = JSON.parse(grabbedProperties.userData); + var grabInfo = userData.grabbableKey; + if (grabInfo && grabInfo.cloneable) { + // Check if + var worldEntities = Entities.findEntitiesInBox(Vec3.subtract(MyAvatar.position, {x:25,y:25, z:25}), {x:50, y: 50, z: 50}) + var count = 0; + worldEntities.forEach(function(item) { + var item = Entities.getEntityProperties(item, ["name"]); + if (item.name === grabbedProperties.name) { + count++; + } + }) + var cloneableProps = Entities.getEntityProperties(grabbedProperties.id); + var lifetime = grabInfo.cloneLifetime ? grabInfo.cloneLifetime : 300; + var limit = grabInfo.cloneLimit ? grabInfo.cloneLimit : 10; + var dynamic = grabInfo.cloneDynamic ? grabInfo.cloneDynamic : false; + var cUserData = Object.assign({}, userData); + var cProperties = Object.assign({}, cloneableProps); - var worldEntities = Entities.findEntitiesInBox(Vec3.subtract(MyAvatar.position, {x:25,y:25, z:25}), {x:50, y: 50, z: 50}) - var count = 0; - worldEntities.forEach(function(item) { - var item = Entities.getEntityProperties(item, ["name"]); - if (item.name === grabbedProperties.name) { - count++; + if (count > limit) { + delete cloneableProps; + delete lifetime; + delete cUserData; + delete cProperties; + return; + } + + delete cUserData.grabbableKey.cloneLifetime; + delete cUserData.grabbableKey.cloneable; + delete cUserData.grabbableKey.cloneDynamic; + delete cUserData.grabbableKey.cloneLimit; + delete cProperties.id + + cProperties.dynamic = dynamic; + cProperties.locked = false; + cUserData.grabbableKey.triggerable = true; + cUserData.grabbableKey.grabbable = true; + cProperties.lifetime = lifetime; + cProperties.userData = JSON.stringify(cUserData); + this.grabbedEntity = Entities.addEntity(cProperties); + grabbedProperties = Entities.getEntityProperties(this.grabbedEntity); + var _this = this; + + Script.setTimeout(function () { + // This is needed to wait for the grabbed entity to have been instanciated. + _this.callEntityMethodOnGrabbed("startEquip"); + },400); } - }) - var cloneableProps = Entities.getEntityProperties(grabbedProperties.id); - var lifetime = grabInfo.cloneLifetime ? grabInfo.cloneLifetime : 300; - var limit = grabInfo.cloneLimit ? grabInfo.cloneLimit : 10; - var dynamic = grabInfo.cloneDynamic ? grabInfo.cloneDynamic : false; - var cUserData = Object.assign({}, userData); - var cProperties = Object.assign({}, cloneableProps); - - if (count > limit) { - delete cloneableProps; - delete lifetime; - delete cUserData; - delete cProperties; - return; - } - - delete cUserData.grabbableKey.cloneLifetime; - delete cUserData.grabbableKey.cloneable; - delete cUserData.grabbableKey.cloneDynamic; - delete cUserData.grabbableKey.cloneLimit; - delete cProperties.id - - cProperties.dynamic = dynamic; - cProperties.locked = false; - cUserData.grabbableKey.triggerable = true; - cUserData.grabbableKey.grabbable = true; - cProperties.lifetime = lifetime; - cProperties.userData = JSON.stringify(cUserData); - this.grabbedEntity = Entities.addEntity(cProperties); - grabbedProperties = Entities.getEntityProperties(this.grabbedEntity); - var _this = this; - Script.setTimeout(function () { - // This is needed to wait for the grabbed entity to have been instanciated. - _this.callEntityMethodOnGrabbed("startEquip"); - },400); + }catch(e) { + print("ERROR: " + e); } - }catch(e) { - print("ERROR: " + e); - } } Entities.editEntity(this.grabbedEntity, reparentProps); From b1639ee3aafb07c96e1e516c74446bbe99737a9e Mon Sep 17 00:00:00 2001 From: Matti Lahtinen Date: Mon, 27 Feb 2017 23:40:06 +0200 Subject: [PATCH 055/133] Removed a Stray Print json that would spam logs. --- scripts/system/edit.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 7731edd622..bfa5ee478b 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1618,7 +1618,6 @@ var PropertiesTool = function (opts) { print('Edit.js received web event that was not valid json.') return; } - print(JSON.stringify(data)) var i, properties, dY, diff, newPosition; if (data.type === "print") { if (data.message) { From c04fd0ec66d31d6a0476be57d81cdc8fbc59e358 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 27 Feb 2017 16:07:05 -0800 Subject: [PATCH 056/133] smaller glyph size --- interface/resources/qml/hifi/Pal.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index f8b2f6ed25..99700bc0f2 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -289,6 +289,7 @@ Rectangle { visible: isAvgAudio glyph: getGlyph() width: 32 + size: height anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter onClicked: { From 9527c51ff1d944b26e8b2e79db346e5cae0919c0 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 27 Feb 2017 13:32:24 -0800 Subject: [PATCH 057/133] Backing up from the rgba format to go back to a rgb 888 just to repair the broken normals on Seth's Avatar --- libraries/model/src/model/TextureMap.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index d1fbaf767a..7ac8083d9c 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -336,8 +336,7 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm const double pStrength = 2.0; int width = image.width(); int height = image.height(); - // THe end result image for normal map is RGBA32 even though the A is not used - QImage result(width, height, QImage::Format_RGBA8888); + QImage result(width, height, QImage::Format_RGB888); for (int i = 0; i < width; i++) { const int iNextClamped = clampPixelCoordinate(i + 1, width - 1); @@ -377,21 +376,19 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm glm::normalize(v); // convert to rgb from the value obtained computing the filter - QRgb qRgbValue = qRgb(mapComponent(v.x), mapComponent(v.y), mapComponent(v.z)); + QRgb qRgbValue = qRgba(mapComponent(v.x), mapComponent(v.y), mapComponent(v.z), 1.0); result.setPixel(i, j, qRgbValue); } } gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - - gpu::Element formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - gpu::Element formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->setSource(srcImageName); theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); - generateMips(theTexture, image, formatMip, true); } return theTexture; From 5b6f953ac270d60aab93ae08cfa2302dafee1161 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Feb 2017 17:35:13 +1300 Subject: [PATCH 058/133] Add hand controller state of distance-rotating for second grab hand --- .../system/controllers/handControllerGrab.js | 138 ++++++++++++++---- 1 file changed, 109 insertions(+), 29 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index d313d1cfa1..0bc0600c81 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -205,14 +205,15 @@ var HARDWARE_MOUSE_ID = 0; // Value reserved for hardware mouse. var STATE_OFF = 0; var STATE_SEARCHING = 1; var STATE_DISTANCE_HOLDING = 2; -var STATE_NEAR_GRABBING = 3; -var STATE_NEAR_TRIGGER = 4; -var STATE_FAR_TRIGGER = 5; -var STATE_HOLD = 6; -var STATE_ENTITY_STYLUS_TOUCHING = 7; -var STATE_ENTITY_LASER_TOUCHING = 8; -var STATE_OVERLAY_STYLUS_TOUCHING = 9; -var STATE_OVERLAY_LASER_TOUCHING = 10; +var STATE_DISTANCE_ROTATING = 3; +var STATE_NEAR_GRABBING = 4; +var STATE_NEAR_TRIGGER = 5; +var STATE_FAR_TRIGGER = 6; +var STATE_HOLD = 7; +var STATE_ENTITY_STYLUS_TOUCHING = 8; +var STATE_ENTITY_LASER_TOUCHING = 9; +var STATE_OVERLAY_STYLUS_TOUCHING = 10; +var STATE_OVERLAY_LASER_TOUCHING = 11; var CONTROLLER_STATE_MACHINE = {}; @@ -231,6 +232,11 @@ CONTROLLER_STATE_MACHINE[STATE_DISTANCE_HOLDING] = { enterMethod: "distanceHoldingEnter", updateMethod: "distanceHolding" }; +CONTROLLER_STATE_MACHINE[STATE_DISTANCE_ROTATING] = { + name: "distance_rotating", + enterMethod: "distanceRotatingEnter", + updateMethod: "distanceRotating" +}; CONTROLLER_STATE_MACHINE[STATE_NEAR_GRABBING] = { name: "near_grabbing", enterMethod: "nearGrabbingEnter", @@ -869,7 +875,8 @@ function MyController(hand) { newState !== STATE_OVERLAY_LASER_TOUCHING)) { return; } - setGrabCommunications((newState === STATE_DISTANCE_HOLDING) || (newState === STATE_NEAR_GRABBING)); + setGrabCommunications((newState === STATE_DISTANCE_HOLDING) || (newState === STATE_DISTANCE_ROTATING) + || (newState === STATE_NEAR_GRABBING)); if (WANT_DEBUG || WANT_DEBUG_STATE) { var oldStateName = stateToName(this.state); var newStateName = stateToName(newState); @@ -1439,9 +1446,10 @@ function MyController(hand) { var props = entityPropertiesCache.getProps(hotspot.entityID); var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME); - var okToEquipFromOtherHand = ((this.getOtherHandController().state == STATE_NEAR_GRABBING || - this.getOtherHandController().state == STATE_DISTANCE_HOLDING) && - this.getOtherHandController().grabbedThingID == hotspot.entityID); + var otherHandControllerState = this.getOtherHandController().state; + var okToEquipFromOtherHand = ((otherHandControllerState === STATE_NEAR_GRABBING + || otherHandControllerState === STATE_DISTANCE_HOLDING || otherHandControllerState === STATE_DISTANCE_ROTATING) + && this.getOtherHandController().grabbedThingID === hotspot.entityID); var hasParent = true; if (props.parentID === NULL_UUID) { hasParent = false; @@ -1731,7 +1739,11 @@ function MyController(hand) { this.grabbedThingID = entity; this.grabbedIsOverlay = false; this.grabbedDistance = rayPickInfo.distance; - this.setState(STATE_DISTANCE_HOLDING, "distance hold '" + name + "'"); + if (this.getOtherHandController().state === STATE_DISTANCE_HOLDING) { + this.setState(STATE_DISTANCE_ROTATING, "distance rotate '" + name + "'"); + } else { + this.setState(STATE_DISTANCE_HOLDING, "distance hold '" + name + "'"); + } return; } else { // potentialFarGrabEntity = entity; @@ -2036,6 +2048,19 @@ function MyController(hand) { return (dimensions.x * dimensions.y * dimensions.z) * density; }; + this.ensureDynamic = function () { + // if we distance hold something and keep it very still before releasing it, it ends up + // non-dynamic in bullet. If it's too still, give it a little bounce so it will fall. + var props = Entities.getEntityProperties(this.grabbedThingID, ["velocity", "dynamic", "parentID"]); + if (props.dynamic && props.parentID == NULL_UUID) { + var velocity = props.velocity; + if (Vec3.length(velocity) < 0.05) { // see EntityMotionState.cpp DYNAMIC_LINEAR_VELOCITY_THRESHOLD + velocity = { x: 0.0, y: 0.2, z: 0.0 }; + Entities.editEntity(this.grabbedThingID, { velocity: velocity }); + } + } + }; + this.distanceHoldingEnter = function() { this.clearEquipHaptics(); this.grabPointSphereOff(); @@ -2102,25 +2127,20 @@ function MyController(hand) { this.previousRoomControllerPosition = roomControllerPosition; }; - this.ensureDynamic = function() { - // if we distance hold something and keep it very still before releasing it, it ends up - // non-dynamic in bullet. If it's too still, give it a little bounce so it will fall. - var props = Entities.getEntityProperties(this.grabbedThingID, ["velocity", "dynamic", "parentID"]); - if (props.dynamic && props.parentID == NULL_UUID) { - var velocity = props.velocity; - if (Vec3.length(velocity) < 0.05) { // see EntityMotionState.cpp DYNAMIC_LINEAR_VELOCITY_THRESHOLD - velocity = { x: 0.0, y: 0.2, z:0.0 }; - Entities.editEntity(this.grabbedThingID, { velocity: velocity }); - } - } - }; - this.distanceHolding = function(deltaTime, timestamp) { if (!this.triggerClicked) { this.callEntityMethodOnGrabbed("releaseGrab"); this.ensureDynamic(); this.setState(STATE_OFF, "trigger released"); + if (this.getOtherHandController().state === STATE_DISTANCE_ROTATING) { + this.getOtherHandController().setState(STATE_SEARCHING, "trigger released on holding controller"); + // Can't set state of other controller to STATE_DISTANCE_HOLDING because then either: + // (a) The entity would jump to line up with the formerly rotating controller's orientation, or + // (b) The grab beam would need an orientation offset to the controller's true orientation. + // Neither of these options is good, so instead set STATE_SEARCHING and subsequently let the formerly distance + // rotating controller start distance holding the entity if it happens to be pointing at the entity. + } return; } @@ -2209,11 +2229,11 @@ function MyController(hand) { } this.maybeScale(grabbedProperties); + // visualizations - var rayPickInfo = this.calcRayPickInfo(this.hand); - - this.overlayLineOn(rayPickInfo.searchRay.origin, Vec3.subtract(grabbedProperties.position, this.offsetPosition), COLORS_GRAB_DISTANCE_HOLD); + this.overlayLineOn(rayPickInfo.searchRay.origin, Vec3.subtract(grabbedProperties.position, this.offsetPosition), + COLORS_GRAB_DISTANCE_HOLD); var distanceToObject = Vec3.length(Vec3.subtract(MyAvatar.position, this.currentObjectPosition)); var success = Entities.updateAction(this.grabbedThingID, this.actionID, { @@ -2232,6 +2252,66 @@ function MyController(hand) { this.previousRoomControllerPosition = roomControllerPosition; }; + this.distanceRotatingEnter = function() { + this.clearEquipHaptics(); + this.grabPointSphereOff(); + + this.shouldScale = false; + + var controllerLocation = getControllerWorldLocation(this.handToController(), true); + var worldControllerPosition = controllerLocation.position; + var worldControllerRotation = controllerLocation.orientation; + + // transform the position into room space + var worldToSensorMat = Mat4.inverse(MyAvatar.getSensorToWorldMatrix()); + var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition); + + var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, GRABBABLE_PROPERTIES); + var now = Date.now(); + + // add the action and initialize some variables + this.currentObjectPosition = grabbedProperties.position; + this.currentObjectRotation = grabbedProperties.rotation; + this.currentObjectTime = now; + this.currentCameraOrientation = Camera.orientation; + + this.grabRadius = this.grabbedDistance; + this.grabRadialVelocity = 0.0; + + // offset between controller vector at the grab radius and the entity position + var targetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation)); + targetPosition = Vec3.sum(targetPosition, worldControllerPosition); + this.offsetPosition = Vec3.subtract(this.currentObjectPosition, targetPosition); + + // TODO + + Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); + this.turnOffVisualizations(); + this.previousRoomControllerPosition = roomControllerPosition; + }; + + this.distanceRotating = function(deltaTime, timestamp) { + + if (!this.triggerClicked) { + this.callEntityMethodOnGrabbed("releaseGrab"); + this.ensureDynamic(); + this.setState(STATE_OFF, "trigger released"); + return; + } + + // TODO + + var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, GRABBABLE_PROPERTIES); + + // TODO + + var rayPickInfo = this.calcRayPickInfo(this.hand); + this.overlayLineOn(rayPickInfo.searchRay.origin, Vec3.subtract(grabbedProperties.position, this.offsetPosition), + COLORS_GRAB_DISTANCE_HOLD); + + // TODO + } + this.setupHoldAction = function() { this.actionID = Entities.addAction("hold", this.grabbedThingID, { hand: this.hand === RIGHT_HAND ? "right" : "left", From 28768d4a781a267e15bc51ecca84c13be7748702 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Feb 2017 22:22:34 +1300 Subject: [PATCH 059/133] Rotate the entity by twice the rotating controller's rotation --- .../system/controllers/handControllerGrab.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 0bc0600c81..2910092293 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2283,7 +2283,8 @@ function MyController(hand) { targetPosition = Vec3.sum(targetPosition, worldControllerPosition); this.offsetPosition = Vec3.subtract(this.currentObjectPosition, targetPosition); - // TODO + // Initial controller rotation. + this.previousWorldControllerRotation = worldControllerRotation; Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); this.turnOffVisualizations(); @@ -2299,17 +2300,24 @@ function MyController(hand) { return; } - // TODO - var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, GRABBABLE_PROPERTIES); - // TODO + // Delta rotation of grabbing controller since last update. + var worldControllerRotation = getControllerWorldLocation(this.handToController(), true).orientation; + var controllerRotationDelta = Quat.multiply(worldControllerRotation, Quat.inverse(this.previousWorldControllerRotation)); + + // Rotate entity by twice the delta rotation. + controllerRotationDelta = Quat.multiply(controllerRotationDelta, controllerRotationDelta); + + // Perform the rotation in the translation controller's action update. + this.getOtherHandController().currentObjectRotation = Quat.multiply(controllerRotationDelta, + this.getOtherHandController().currentObjectRotation); var rayPickInfo = this.calcRayPickInfo(this.hand); this.overlayLineOn(rayPickInfo.searchRay.origin, Vec3.subtract(grabbedProperties.position, this.offsetPosition), COLORS_GRAB_DISTANCE_HOLD); - // TODO + this.previousWorldControllerRotation = worldControllerRotation; } this.setupHoldAction = function() { From e3f2f3c5bc830064d6aef54f8259bffca4f6cd2d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Feb 2017 23:04:23 +1300 Subject: [PATCH 060/133] Tidying --- .../system/controllers/handControllerGrab.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 2910092293..2dfa7e6948 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2256,29 +2256,15 @@ function MyController(hand) { this.clearEquipHaptics(); this.grabPointSphereOff(); - this.shouldScale = false; - var controllerLocation = getControllerWorldLocation(this.handToController(), true); var worldControllerPosition = controllerLocation.position; var worldControllerRotation = controllerLocation.orientation; - // transform the position into room space - var worldToSensorMat = Mat4.inverse(MyAvatar.getSensorToWorldMatrix()); - var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition); - var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, GRABBABLE_PROPERTIES); - var now = Date.now(); - - // add the action and initialize some variables this.currentObjectPosition = grabbedProperties.position; - this.currentObjectRotation = grabbedProperties.rotation; - this.currentObjectTime = now; - this.currentCameraOrientation = Camera.orientation; - this.grabRadius = this.grabbedDistance; - this.grabRadialVelocity = 0.0; - // offset between controller vector at the grab radius and the entity position + // Offset between controller vector at the grab radius and the entity position. var targetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation)); targetPosition = Vec3.sum(targetPosition, worldControllerPosition); this.offsetPosition = Vec3.subtract(this.currentObjectPosition, targetPosition); @@ -2288,7 +2274,6 @@ function MyController(hand) { Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); this.turnOffVisualizations(); - this.previousRoomControllerPosition = roomControllerPosition; }; this.distanceRotating = function(deltaTime, timestamp) { From d8d17be0e06206ce94839765d747259feba505a3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Feb 2017 23:22:07 +1300 Subject: [PATCH 061/133] Rotate about translation grab position --- scripts/system/controllers/handControllerGrab.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 2dfa7e6948..08877e2b10 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2298,6 +2298,11 @@ function MyController(hand) { this.getOtherHandController().currentObjectRotation = Quat.multiply(controllerRotationDelta, this.getOtherHandController().currentObjectRotation); + // Rotate about the translation controller's target position. + this.offsetPosition = Vec3.multiplyQbyV(controllerRotationDelta, this.offsetPosition); + this.getOtherHandController().offsetPosition = Vec3.multiplyQbyV(controllerRotationDelta, + this.getOtherHandController().offsetPosition); + var rayPickInfo = this.calcRayPickInfo(this.hand); this.overlayLineOn(rayPickInfo.searchRay.origin, Vec3.subtract(grabbedProperties.position, this.offsetPosition), COLORS_GRAB_DISTANCE_HOLD); From d0c2c26a8e77209d6cba4c4a5c97538a4678d268 Mon Sep 17 00:00:00 2001 From: Matti Lahtinen Date: Tue, 28 Feb 2017 16:37:08 +0200 Subject: [PATCH 062/133] One last gotcha from the conflict resolution. --- scripts/system/controllers/handControllerGrab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 14d737de55..fd13b74f7d 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2497,7 +2497,7 @@ function MyController(hand) { cProperties.lifetime = lifetime; cProperties.userData = JSON.stringify(cUserData); this.grabbedThingID = Entities.addEntity(cProperties); - grabbedProperties = Entities.getEntityProperties(this.grabbedEntity); + grabbedProperties = Entities.getEntityProperties(this.grabbedThingID); var _this = this; Script.setTimeout(function () { From 1fc57ce9a68a40de030890c7e2aefb73b3de5375 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 28 Feb 2017 11:51:40 -0700 Subject: [PATCH 063/133] alan's feedback --- scripts/system/pal.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index a609de43a1..67aa94a2f7 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -634,7 +634,7 @@ var AVERAGING_RATIO = 0.05; var LOUDNESS_FLOOR = 11.0; var LOUDNESS_SCALE = 2.8 / 5.0; var LOG2 = Math.log(2.0); -var AUDIO_PEAK_DECAY = 0.03; +var AUDIO_PEAK_DECAY = 0.02; var myData = {}; // we're not includied in ExtendedOverlay.get. function scaleAudio(val) { @@ -673,8 +673,9 @@ function getAudioLevel(id) { data.avgAudioLevel = avgAudioLevel; data.audioLevel = audioLevel; - // now scale for the gain - avgAudioLevel = Math.min(1.0, avgAudioLevel *(sessionGains[id] || 0.75)); + // now scale for the gain. Also, asked to boost the low end, so one simple way is + // to take sqrt of the value. Lets try that, see how it feels. + avgAudioLevel = Math.min(1.0, Math.sqrt(avgAudioLevel *(sessionGains[id] || 0.75))); } return [audioLevel, avgAudioLevel]; } From 2635657456a097bfc99d28eb44711f3b7a6b0797 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 28 Feb 2017 13:24:25 -0700 Subject: [PATCH 064/133] zappoman's feedback, plus added const corrrectness to computeLoudness --- assignment-client/src/Agent.cpp | 4 +++- assignment-client/src/Agent.h | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 5211c3beaa..9c830ef391 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -380,6 +380,8 @@ void Agent::executeScript() { audioTransform.setTranslation(scriptedAvatar->getPosition()); audioTransform.setRotation(headOrientation); + computeLoudness(&audio); + QByteArray encodedBuffer; if (_encoder) { _encoder->encode(audio, encodedBuffer); @@ -571,7 +573,7 @@ void Agent::encodeFrameOfZeros(QByteArray& encodedZeros) { } } -void Agent::computeLoudness(QByteArray* decodedBuffer) { +void Agent::computeLoudness(const QByteArray* decodedBuffer) { float loudness = 0.0f; auto scriptedAvatar = DependencyManager::get(); if (decodedBuffer) { diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 7f04b4746f..ce7393011f 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -68,10 +68,10 @@ private slots: void handleAudioPacket(QSharedPointer message); void handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode); void handleJurisdictionPacket(QSharedPointer message, SharedNodePointer senderNode); - void handleSelectedAudioFormat(QSharedPointer message); + void handleSelectedAudioFormat(QSharedPointer message); void nodeActivated(SharedNodePointer activatedNode); - + void processAgentAvatar(); void processAgentAvatarAudio(); @@ -82,7 +82,7 @@ private: void negotiateAudioFormat(); void selectAudioFormat(const QString& selectedCodecName); void encodeFrameOfZeros(QByteArray& encodedZeros); - void computeLoudness(QByteArray* decodedBuffer); + void computeLoudness(const QByteArray* decodedBuffer); std::unique_ptr _scriptEngine; EntityEditPacketSender _entityEditSender; @@ -104,10 +104,10 @@ private: bool _isAvatar = false; QTimer* _avatarIdentityTimer = nullptr; QHash _outgoingScriptAudioSequenceNumbers; - + CodecPluginPointer _codec; QString _selectedCodecName; - Encoder* _encoder { nullptr }; + Encoder* _encoder { nullptr }; QThread _avatarAudioTimerThread; bool _flushEncoder { false }; }; From 8562a294fa0d666f13c26e56b9520924b0782cee Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 28 Feb 2017 13:24:41 -0800 Subject: [PATCH 065/133] cleanup some extra spacing --- libraries/entities-renderer/src/RenderableWebEntityItem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 6c44794c3e..d7d7013f59 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -269,11 +269,10 @@ void RenderableWebEntityItem::loadSourceURL() { _webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) { context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject)); }); + _webSurface->getRootItem()->setProperty("url", _sourceUrl); _webSurface->getRootContext()->setContextProperty("desktop", QVariant()); - - } else { _contentType = qmlContent; _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath())); From 148100b26f7b1b359ab4792660ae9de7b1caa4c9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 28 Feb 2017 15:10:20 -0800 Subject: [PATCH 066/133] fix bug drawing avatar above ground --- interface/src/avatar/SkeletonModel.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 476abf8d4b..88590a6f69 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -179,9 +179,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig->updateFromEyeParameters(eyeParams); } else { - // no need to call Model::updateRig() because otherAvatars get their joint state - // copied directly from AvtarData::_jointData (there are no Rig animations to blend) - _needsUpdateClusterMatrices = true; + Model::updateRig(deltaTime, parentTransform); // This is a little more work than we really want. // From 6ac85aee7e22f1fd29b0ae257f9b0a033d0213f4 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 28 Feb 2017 18:12:35 -0800 Subject: [PATCH 067/133] Adding support for the unliti materials too for overlay's --- .../render-utils/src/RenderPipelines.cpp | 8 ++++ .../src/overlay3D_model_translucent_unlit.slf | 43 ++++++++++++++++++ .../src/overlay3D_model_unlit.slf | 44 +++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 libraries/render-utils/src/overlay3D_model_translucent_unlit.slf create mode 100644 libraries/render-utils/src/overlay3D_model_unlit.slf diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index d753c679c6..3b279ff6d9 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -55,6 +55,8 @@ #include "overlay3D_translucent_frag.h" #include "overlay3D_unlit_frag.h" #include "overlay3D_translucent_unlit_frag.h" +#include "overlay3D_model_unlit_frag.h" +#include "overlay3D_model_translucent_unlit_frag.h" using namespace render; @@ -79,6 +81,8 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto pixelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_translucent_unlit_frag)); auto pixelModel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); auto pixelModelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_model_translucent_frag)); + auto pixelModelUnlit = gpu::Shader::createPixel(std::string(overlay3D_model_unlit_frag)); + auto pixelModelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_model_translucent_unlit_frag)); auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel); auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); @@ -86,6 +90,8 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); auto materialOpaqueProgram = gpu::Shader::createProgram(vertexModel, pixelModel); auto materialTranslucentProgram = gpu::Shader::createProgram(vertexModel, pixelModelTranslucent); + auto materialUnlitOpaqueProgram = gpu::Shader::createProgram(vertexModel, pixelModel); + auto materialUnlitTranslucentProgram = gpu::Shader::createProgram(vertexModel, pixelModelTranslucent); for (int i = 0; i < 8; i++) { bool isCulled = (i & 1); @@ -118,8 +124,10 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; auto materialProgram = isOpaque ? materialOpaqueProgram : materialTranslucentProgram; + auto materialUnlitProgram = isOpaque ? materialUnlitOpaqueProgram : materialUnlitTranslucentProgram; plumber.addPipeline(builder.withMaterial().build().key(), materialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withMaterial().withUnlit().build().key(), materialUnlitProgram, state, &batchSetter); plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build().key(), simpleProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withUnlit().withoutMaterial().build().key(), unlitProgram, state, &batchSetter); } diff --git a/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf b/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf new file mode 100644 index 0000000000..3dd8138272 --- /dev/null +++ b/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf @@ -0,0 +1,43 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// overlay3D-model_transparent_unlit.slf +// fragment shader +// +// Created by Sam Gateau on 2/28/2017. +// Copyright 2015 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 LightingModel.slh@> +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO)$> + +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + vec4 color = vec4(albedo * isUnlitEnabled(), opacity); + + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); +} \ No newline at end of file diff --git a/libraries/render-utils/src/overlay3D_model_unlit.slf b/libraries/render-utils/src/overlay3D_model_unlit.slf new file mode 100644 index 0000000000..80c2bb971e --- /dev/null +++ b/libraries/render-utils/src/overlay3D_model_unlit.slf @@ -0,0 +1,44 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// overlay3D-model_unlit.slf +// fragment shader +// +// Created by Sam Gateau on 2/28/2017. +// Copyright 2015 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 LightingModel.slh@> +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO)$> + +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + vec4 color = vec4(albedo * isUnlitEnabled(), opacity); + + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); +} From 1c3840dc788f4a828d748c9ae3b011bf5f1e37d2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 1 Mar 2017 10:05:24 -0800 Subject: [PATCH 068/133] Add Hifi-Hand-Drop so scripts can cause grabbed items to be dropped --- scripts/system/controllers/handControllerGrab.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index d313d1cfa1..d982a032cc 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -3287,6 +3287,7 @@ Messages.subscribe('Hifi-Hand-Disabler'); Messages.subscribe('Hifi-Hand-Grab'); Messages.subscribe('Hifi-Hand-RayPick-Blacklist'); Messages.subscribe('Hifi-Object-Manipulation'); +Messages.subscribe('Hifi-Hand-Drop'); var handleHandMessages = function(channel, message, sender) { var data; @@ -3372,6 +3373,15 @@ var handleHandMessages = function(channel, message, sender) { } catch (e) { print("WARNING: handControllerGrab.js -- error parsing Hifi-Hand-RayPick-Blacklist message: " + message); } + } else if (channel === 'Hifi-Hand-Drop') { + if (message === 'left') { + leftController.release(); + } else if (message === 'right') { + rightController.release(); + } else if (message === 'both') { + leftController.release(); + rightController.release(); + } } } }; From 55d049ff5caba783d1cbd9be59da2c53e52b518a Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 1 Mar 2017 12:43:45 -0700 Subject: [PATCH 069/133] style updates --- interface/resources/fonts/hifi-glyphs.ttf | Bin 27900 -> 28048 bytes interface/resources/qml/hifi/NameCard.qml | 5 ++++- interface/resources/qml/hifi/Pal.qml | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/resources/fonts/hifi-glyphs.ttf b/interface/resources/fonts/hifi-glyphs.ttf index f6efa8e03952a0b2e926c966a08da697e53d8b79..0d724788143efe22b55d56347e0138961ee55d45 100755 GIT binary patch delta 3431 zcmcJSU2Icj9LAsjIqx~|>F3(6r>EQ6jeVWNHbzU=wczHI1coTchYLa&g8}=WQR1#7nm7`@Gf@MgNX%{|MvWH+H9;MwT{qa6WM8yR`u3v9 z`+I)x|2gOU^BukLJ((Z?E}Vdft074tqt#8KLkb!gyfMr{rh{U#h zyr~tSod9+mNVoSlG=2LrAiM_%OqpRxpd7v|u`A>h};Lu4!{Tt{G0n*AW906BX-?*_iukjB!1Y};9u3bz` zds{e>>a`vbPkB>FqYwQUz!3~$7(><%Vhi<-)UlVSpttJN z>gwu~)z@o!Rs>dz)wa}LU3ntX5^WwClXh<($=juqwPxofQ$QFyaGlOU$66p?t`W=R zFcp&)Xb@srKnv8xl8FbYk(%g1iW@qYwWK#f`oyP3sBe&B$wV@dX3WQBZ;*U0C67Fe zd32|bDH>6MmS0+%$7EtISu7GIHOv*}agijuxv9`Trg{ckDiQNky9HbE8@7Ui0Oui_ z-LG@s_`h5hm|JGWVvp?Mc8Hk`lakx;#>H$o5ZBEz*&m24Z12ipf5`6-%@g2Aw5%*z z27qNioYX?+;70>?pv^kn8Z;LyAQ0EHFcc+`1cljbKBmf&L-cW{2MdQeP6%8KA_ihxe$GTP}DtiyWCBa;x>) zo?y5-Cs#%o&GZ|M=F|@07|tvKI_cKxw$S5?GCV7{JQn9%lD8o*s-$%xs*#qH}Oy8MXkGq$it5qhjJRC6bAUNY&~aDG|?A4A<0&elc_- z+cC`0ljUxjET+KiVxkYmpYyp`J~wGt5hcg?mn0~@JcELozlLwl)sD|DGBwP(NFxk#(vIWsPRBb-aa2|t#>KrLD^090}9WtnYm2Oo>NpTSJ-3|I*Hjl&UEh7OdOg;CpTUcG^;8rifod^ zy%l{#5*55MpS;dOU`wa5j^uIa{Q1W>8{DBfzypvOccY$Fn1q zy^II)7Z>=9yv^IwJ6qr-f+*SqCsW8?;UPgF*~9D(#igjprBPu{&ir^$@NN|J&AZv1Ym0c9L&6~W1B@kuiZd#%ofFtYbcN)!}{8B7O6wTOYTTq1lbjiiOh?RBp}CNunc?u>3XhbQu!!BuC8@}7FK2E^lBK;7Av%V8;i6#UIMq~EM5ENf&GRQK_b?unCAseHYwBMJ{ z^L&2a=YDa3=jY(jzGkwj*hNp58nFpGLRVo5M2B8nhtyd4rDF^ShR6#gTC>r z&Yb{l2e7R#+nZ}{zitA;IY4Ml_YUUn-Gc~Zz5rlLXI|O+*~KT{0HhJ1XS6@nyGQ-D z<2Hbw0VMkSQ${aqq!EC;0K)y*p+gmIzB+&|0JxhO=FKee>I!O<`_JRExzZ@{5s|1wRhOtdv1?8D z9ntQhsJM^2!+>asBUTXCHWzu?vPg(~HGKw|eKYFZ>I-_k!GEfKfY{@Wp-^MUg2?is zJLwF(SdLC~nU{71j9KSe6iziHl3-(sQp$W>vNMnDkescvOuc8q&N#1-9f1;?%++K| zxKfcM*%RI|70AO_l=2QwO*-sH&hn_w+N0mB*i~UP@dBgyvHBYk3EV9ycAL}Y69SBh z3S&-Q@j;&Ge>W3`;o)3N612G;^sTMgQ#tKO!=>T$?_ekljr6w44}hP$9yOE*i`4>S}BP%Hnz=u4~PtCtInF zeDNmV)C1z>zPMB!;y$n6H(4`Q-Q-)wuP2s8q+-*=*D}E-Fs~sI=e9*QXKd>6UqYwH zS1Jxqv3nwJN0}^_k1I~+`1kkw=Vgi$aivOecE3RPk34gUesU z4sPRuK(fFTTN!iF_}z&!GEHoAOKs5ts~>G{Uz=Cu0dAG1p~k9P=X!`H!&D|W#Y(aY zjp)J?Is&W08A;+VinMb#lYxJwqi#d`IN z+;Z#S=62c5M0MS+X(6wk2g+t Date: Wed, 1 Mar 2017 22:07:02 +0200 Subject: [PATCH 070/133] Various Properties --- scripts/system/html/entityProperties.html | 2 +- scripts/system/html/js/entityProperties.js | 149 +++++++++++---------- 2 files changed, 78 insertions(+), 73 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index a0497d6a92..5022dbd6a6 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -305,7 +305,7 @@ -
+