From 5288314d02c16bae5cd4e477b3e1637cdf6ae1a5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 13 Jun 2019 17:42:32 -0700 Subject: [PATCH 01/63] Drafting ways to rescale in forward --- .../scripting/RenderScriptingInterface.cpp | 52 ++++++++++- .../src/scripting/RenderScriptingInterface.h | 17 ++-- .../src/DeferredLightingEffect.cpp | 2 +- .../render-utils/src/DeferredLightingEffect.h | 11 ++- libraries/render-utils/src/RenderCommonTask.h | 2 + .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../render-utils/src/RenderForwardTask.cpp | 90 ++++++++++++------- .../render-utils/src/RenderForwardTask.h | 39 ++++++-- .../utilities/render/luci/RenderSettings.qml | 7 ++ 9 files changed, 166 insertions(+), 56 deletions(-) diff --git a/interface/src/scripting/RenderScriptingInterface.cpp b/interface/src/scripting/RenderScriptingInterface.cpp index 608f1d30e9..4e07d77c0b 100644 --- a/interface/src/scripting/RenderScriptingInterface.cpp +++ b/interface/src/scripting/RenderScriptingInterface.cpp @@ -37,7 +37,7 @@ void RenderScriptingInterface::loadSettings() { forceAntialiasingEnabled(_antialiasingEnabled); } -RenderScriptingInterface::RenderMethod RenderScriptingInterface::getRenderMethod() { +RenderScriptingInterface::RenderMethod RenderScriptingInterface::getRenderMethod() const { return (RenderMethod) _renderMethod; } @@ -64,7 +64,7 @@ QStringList RenderScriptingInterface::getRenderMethodNames() const { return refrenderMethodNames; } -bool RenderScriptingInterface::getShadowsEnabled() { +bool RenderScriptingInterface::getShadowsEnabled() const { return _shadowsEnabled; } @@ -88,7 +88,7 @@ void RenderScriptingInterface::forceShadowsEnabled(bool enabled) { }); } -bool RenderScriptingInterface::getAmbientOcclusionEnabled() { +bool RenderScriptingInterface::getAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } @@ -112,7 +112,7 @@ void RenderScriptingInterface::forceAmbientOcclusionEnabled(bool enabled) { }); } -bool RenderScriptingInterface::getAntialiasingEnabled() { +bool RenderScriptingInterface::getAntialiasingEnabled() const { return _antialiasingEnabled; } @@ -145,3 +145,47 @@ void RenderScriptingInterface::forceAntialiasingEnabled(bool enabled) { } +float RenderScriptingInterface::getViewportResolutionScale() const { + return _viewportResolutionScale; +} + +void RenderScriptingInterface::setViewportResolutionScale(float scale) { + if (_viewportResolutionScale != scale) { + forceViewportResolutionScale(scale); + emit settingsChanged(); + } +} + +void RenderScriptingInterface::forceViewportResolutionScale(float scale) { + _renderSettingLock.withWriteLock([&] { + _viewportResolutionScale = (scale); + // _antialiasingEnabledSetting.set(enabled); + + auto renderConfig = qApp->getRenderEngine()->getConfiguration(); + assert(renderConfig); + auto deferredView = renderConfig->getConfig("RenderMainView.RenderDeferredTask"); + // mainView can be null if we're rendering in forward mode + if (deferredView) { + deferredView->setProperty("resolutionScale", _viewportResolutionScale); + } + auto forwardView = renderConfig->getConfig("RenderMainView.RenderForwardTask"); + // mainView can be null if we're rendering in forward mode + if (forwardView) { + forwardView->setProperty("resolutionScale", _viewportResolutionScale); + } +/* + auto mainViewJitterCamConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.JitterCam"); + auto mainViewAntialiasingConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.Antialiasing"); + if (mainViewJitterCamConfig && mainViewAntialiasingConfig) { + Menu::getInstance()->setIsOptionChecked(MenuOption::AntiAliasing, enabled); + if (enabled) { + mainViewJitterCamConfig->play(); + mainViewAntialiasingConfig->setDebugFXAA(false); + } + else { + mainViewJitterCamConfig->none(); + mainViewAntialiasingConfig->setDebugFXAA(true); + } + }*/ + }); +} diff --git a/interface/src/scripting/RenderScriptingInterface.h b/interface/src/scripting/RenderScriptingInterface.h index 39a88d4aad..11a071c86a 100644 --- a/interface/src/scripting/RenderScriptingInterface.h +++ b/interface/src/scripting/RenderScriptingInterface.h @@ -29,6 +29,7 @@ class RenderScriptingInterface : public QObject { Q_PROPERTY(bool shadowsEnabled READ getShadowsEnabled WRITE setShadowsEnabled NOTIFY settingsChanged) Q_PROPERTY(bool ambientOcclusionEnabled READ getAmbientOcclusionEnabled WRITE setAmbientOcclusionEnabled NOTIFY settingsChanged) Q_PROPERTY(bool antialiasingEnabled READ getAntialiasingEnabled WRITE setAntialiasingEnabled NOTIFY settingsChanged) + Q_PROPERTY(float viewportResolutionScale READ getViewportResolutionScale WRITE setViewportResolutionScale NOTIFY settingsChanged) public: RenderScriptingInterface(); @@ -66,7 +67,7 @@ public slots: * @function Render.getRenderMethod * @returns {number} "DEFERRED" or "FORWARD" */ - RenderMethod getRenderMethod(); + RenderMethod getRenderMethod() const; /**jsdoc * Sets the current render method @@ -88,7 +89,7 @@ public slots: * @function Render.getShadowsEnabled * @returns {bool} true if shadows are enabled, otherwise false */ - bool getShadowsEnabled(); + bool getShadowsEnabled() const; /**jsdoc * Enables or disables shadows @@ -102,7 +103,7 @@ public slots: * @function Render.getAmbientOcclusionEnabled * @returns {bool} true if ambient occlusion is enabled, otherwise false */ - bool getAmbientOcclusionEnabled(); + bool getAmbientOcclusionEnabled() const; /**jsdoc * Enables or disables ambient occlusion @@ -116,7 +117,7 @@ public slots: * @function Render.getAntialiasingEnabled * @returns {bool} true if anti-aliasing is enabled, otherwise false */ - bool getAntialiasingEnabled(); + bool getAntialiasingEnabled() const; /**jsdoc * Enables or disables anti-aliasing @@ -130,14 +131,14 @@ public slots: * @function Render.getViewportResolutionScale * @returns {number} */ - // float getViewportResolutionScale(); + float getViewportResolutionScale() const; /**jsdoc * Sets the current viewport resolution scale * @function Render.setViewportResolutionScale * @param {number} resolutionScale - between epsilon and 1.0 */ - // void setViewportResolutionScale(float resolutionScale); + void setViewportResolutionScale(float resolutionScale); signals: void settingsChanged(); @@ -150,7 +151,8 @@ private: int _renderMethod{ RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED }; bool _shadowsEnabled{ true }; bool _ambientOcclusionEnabled{ false }; - bool _antialiasingEnabled { true }; + bool _antialiasingEnabled{ true }; + float _viewportResolutionScale{ 1.0f }; // Actual settings saved on disk Setting::Handle _renderMethodSetting { "renderMethod", RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED }; @@ -163,6 +165,7 @@ private: void forceShadowsEnabled(bool enabled); void forceAmbientOcclusionEnabled(bool enabled); void forceAntialiasingEnabled(bool enabled); + void forceViewportResolutionScale(float scale); static std::once_flag registry_flag; }; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 82b7f3102a..94c9dccfdd 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -313,7 +313,7 @@ gpu::FramebufferPointer PreparePrimaryFramebuffer::createFramebuffer(const char* } void PreparePrimaryFramebuffer::configure(const Config& config) { - _resolutionScale = config.resolutionScale; + _resolutionScale = config.getResolutionScale(); } void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, Output& primaryFramebuffer) { diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 1cc6ca4767..314d6fd4f6 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -89,13 +89,18 @@ private: class PreparePrimaryFramebufferConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(float resolutionScale MEMBER resolutionScale NOTIFY dirty) + Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale) public: - - float resolutionScale{ 1.0f }; + float getResolutionScale() const { return resolutionScale; } + void setResolutionScale(float scale) { + resolutionScale = std::max(0.1f, std::min(1.0f, resolutionScale)); + } signals: void dirty(); + +protected: + float resolutionScale{ 1.0f }; }; class PreparePrimaryFramebuffer { diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index 4f72600d34..8fd7f22a21 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -13,6 +13,8 @@ #include "LightStage.h" #include "LightingModel.h" + + class BeginGPURangeTimer { public: using JobModel = render::Job::ModelO; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 624869bbf5..deafce0419 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -99,7 +99,7 @@ void RenderDeferredTask::configure(const Config& config) { auto upsamplePrimaryBufferConfig = config.getConfig("PrimaryBufferUpscale"); assert(preparePrimaryBufferConfig); assert(upsamplePrimaryBufferConfig); - preparePrimaryBufferConfig->setProperty("resolutionScale", config.resolutionScale); + preparePrimaryBufferConfig->setResolutionScale(config.resolutionScale); upsamplePrimaryBufferConfig->setProperty("factor", 1.0f / config.resolutionScale); } diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index de55f3f4ff..a53b480b9f 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -47,6 +47,16 @@ using namespace render; extern void initForwardPipelines(ShapePlumber& plumber); +void RenderForwardTask::configure(const Config& config) { + // Propagate resolution scale to sub jobs who need it + auto preparePrimaryBufferConfig = config.getConfig("PreparePrimaryBuffer"); +// auto upsamplePrimaryBufferConfig = config.getConfig("PrimaryBufferUpscale"); + assert(preparePrimaryBufferConfig); +// assert(upsamplePrimaryBufferConfig); + preparePrimaryBufferConfig->setResolutionScale(config.resolutionScale); + // upsamplePrimaryBufferConfig->setProperty("factor", 1.0f / config.resolutionScale); +} + void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { task.addJob("SetRenderMethodTask", render::Args::FORWARD); @@ -87,16 +97,19 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // First job, alter faded fadeEffect->build(task, opaques); - // Prepare objects shared by several jobs - const auto deferredFrameTransform = task.addJob("DeferredFrameTransform"); // GPU jobs: Start preparing the main framebuffer - const auto framebuffer = task.addJob("PrepareFramebuffer"); + const auto scaledPrimaryFramebuffer = task.addJob("PreparePrimaryBuffer"); - task.addJob("PrepareForward", lightFrame); + // Prepare deferred, generate the shared Deferred Frame Transform. Only valid with the scaled frame buffer + const auto deferredFrameTransform = task.addJob("DeferredFrameTransform"); + + // Prepare Forward Framebuffer pass + const auto prepareForwardInputs = PrepareForward::Inputs(scaledPrimaryFramebuffer, lightFrame).asVarying(); + task.addJob("PrepareForward", prepareForwardInputs); // draw a stencil mask in hidden regions of the framebuffer. - task.addJob("PrepareStencil", framebuffer); + task.addJob("PrepareStencil", scaledPrimaryFramebuffer); // Draw opaques forward const auto opaqueInputs = DrawForward::Inputs(opaques, lightingModel).asVarying(); @@ -130,7 +143,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // Just resolve the msaa const auto resolveInputs = - ResolveFramebuffer::Inputs(framebuffer, static_cast(nullptr)).asVarying(); + ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, static_cast(nullptr)).asVarying(); const auto resolvedFramebuffer = task.addJob("Resolve", resolveInputs); //auto resolvedFramebuffer = task.addJob("Resolve", framebuffer); @@ -157,35 +170,38 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // task.addJob("Blit", framebuffer); } -void PrepareFramebuffer::configure(const Config& config) { +gpu::FramebufferPointer PreparePrimaryFramebufferMSAA::createFramebuffer(const char* name, const glm::uvec2& frameSize, int numSamples) { + gpu::FramebufferPointer framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(name)); + + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); + + auto colorFormat = gpu::Element::COLOR_SRGBA_32; + auto colorTexture = + gpu::Texture::createRenderBufferMultisample(colorFormat, frameSize.x, frameSize.y, numSamples, defaultSampler); + framebuffer->setRenderBuffer(0, colorTexture); + + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format + auto depthTexture = + gpu::Texture::createRenderBufferMultisample(depthFormat, frameSize.x, frameSize.y, numSamples, defaultSampler); + framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); + + return framebuffer; +} + +void PreparePrimaryFramebufferMSAA::configure(const Config& config) { + _resolutionScale = config.getResolutionScale(); _numSamples = config.getNumSamples(); } -void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { +void PreparePrimaryFramebufferMSAA::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); + glm::uvec2 scaledFrameSize(glm::vec2(frameSize) * _resolutionScale); // Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering - if (_framebuffer && (_framebuffer->getSize() != frameSize || _framebuffer->getNumSamples() != _numSamples)) { - _framebuffer.reset(); + if (!_framebuffer || (_framebuffer->getSize() != scaledFrameSize) || (_framebuffer->getNumSamples() != _numSamples)) { + _framebuffer = createFramebuffer("forward", scaledFrameSize, _numSamples); } - - if (!_framebuffer) { - _framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward")); - - int numSamples = _numSamples; - - auto colorFormat = gpu::Element::COLOR_SRGBA_32; - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); - auto colorTexture = - gpu::Texture::createRenderBufferMultisample(colorFormat, frameSize.x, frameSize.y, numSamples, defaultSampler); - _framebuffer->setRenderBuffer(0, colorTexture); - - auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format - auto depthTexture = - gpu::Texture::createRenderBufferMultisample(depthFormat, frameSize.x, frameSize.y, numSamples, defaultSampler); - _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); - } - +/* auto args = renderContext->args; gpu::doInBatch("PrepareFramebuffer::run", args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); @@ -196,7 +212,7 @@ void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::Fra batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH | gpu::Framebuffer::BUFFER_STENCIL, vec4(vec3(0), 0), 1.0, 0, true); - }); + });*/ framebuffer = _framebuffer; } @@ -204,18 +220,30 @@ void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::Fra void PrepareForward::run(const RenderContextPointer& renderContext, const Inputs& inputs) { RenderArgs* args = renderContext->args; + auto primaryFramebuffer = inputs.get0(); + auto lightStageFrame = inputs.get1(); + gpu::doInBatch("RenderForward::Draw::run", args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; + batch.enableStereo(false); + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + batch.setFramebuffer(primaryFramebuffer); + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH | + gpu::Framebuffer::BUFFER_STENCIL, + vec4(vec3(0), 0), 1.0, 0, true); + graphics::LightPointer keySunLight; auto lightStage = args->_scene->getStage(); if (lightStage) { - keySunLight = lightStage->getCurrentKeyLight(*inputs); + keySunLight = lightStage->getCurrentKeyLight(*lightStageFrame); } graphics::LightPointer keyAmbiLight; if (lightStage) { - keyAmbiLight = lightStage->getCurrentAmbientLight(*inputs); + keyAmbiLight = lightStage->getCurrentAmbientLight(*lightStageFrame); } if (keySunLight) { diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index 40d004ddb2..d4eb96d1e9 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -17,39 +17,57 @@ #include "AssembleLightingStageTask.h" #include "LightingModel.h" +class RenderForwardTaskConfig : public render::Task::Config { + Q_OBJECT + Q_PROPERTY(float resolutionScale MEMBER resolutionScale NOTIFY dirty) +public: + float resolutionScale{ 1.f }; + +signals: + void dirty(); +}; + class RenderForwardTask { public: using Input = render::VaryingSet3; - using JobModel = render::Task::ModelI; + using Config = RenderForwardTaskConfig; + using JobModel = render::Task::ModelI; RenderForwardTask() {} + void configure(const Config& config); void build(JobModel& task, const render::Varying& input, render::Varying& output); }; -class PrepareFramebufferConfig : public render::Job::Config { +class PreparePrimaryFramebufferMSAAConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples NOTIFY dirty) + Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale) + Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples) public: + float getResolutionScale() const { return resolutionScale; } + void setResolutionScale(float scale) { + resolutionScale = std::max(0.1f, std::min(1.0f, resolutionScale)); + } + int getNumSamples() const { return numSamples; } void setNumSamples(int num) { numSamples = std::max(1, std::min(32, num)); - emit dirty(); } signals: void dirty(); protected: + float resolutionScale{ 1.0f }; int numSamples{ 4 }; }; -class PrepareFramebuffer { +class PreparePrimaryFramebufferMSAA { public: - using Inputs = gpu::FramebufferPointer; - using Config = PrepareFramebufferConfig; - using JobModel = render::Job::ModelO; + using Output = gpu::FramebufferPointer; + using Config = PreparePrimaryFramebufferMSAAConfig; + using JobModel = render::Job::ModelO; void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, @@ -57,12 +75,15 @@ public: private: gpu::FramebufferPointer _framebuffer; + float _resolutionScale{ 1.0f }; int _numSamples; + + static gpu::FramebufferPointer createFramebuffer(const char* name, const glm::uvec2& frameSize, int numSamples); }; class PrepareForward { public: - using Inputs = LightStage::FramePointer; + using Inputs = render::VaryingSet2 ; using JobModel = render::Job::ModelI; void run(const render::RenderContextPointer& renderContext, diff --git a/scripts/developer/utilities/render/luci/RenderSettings.qml b/scripts/developer/utilities/render/luci/RenderSettings.qml index 906c117b3a..4da63bbcd1 100644 --- a/scripts/developer/utilities/render/luci/RenderSettings.qml +++ b/scripts/developer/utilities/render/luci/RenderSettings.qml @@ -30,5 +30,12 @@ Column { object: Render property: "shadowsEnabled" } + Prop.PropScalar { + label: "Viewport Resolution Scale" + object: Render + property: "viewportResolutionScale" + min: 0.1 + max: 1.0 + } } From 12f8c7486ba9418a28283a51c11cbbf2a4fef8bb Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 14 Jun 2019 00:48:07 -0700 Subject: [PATCH 02/63] getting rescaling to work for forward yop --- .../render-utils/src/DeferredLightingEffect.h | 2 +- .../render-utils/src/RenderCommonTask.cpp | 21 +++++++++ libraries/render-utils/src/RenderCommonTask.h | 11 +++++ .../render-utils/src/RenderForwardTask.cpp | 42 +++++++++-------- .../render-utils/src/RenderForwardTask.h | 2 +- libraries/render/src/render/ResampleTask.cpp | 47 +++++++++++++++++++ libraries/render/src/render/ResampleTask.h | 19 ++++++++ .../utilities/render/luci/RenderSettings.qml | 2 +- 8 files changed, 124 insertions(+), 22 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 314d6fd4f6..e0248e584e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -93,7 +93,7 @@ class PreparePrimaryFramebufferConfig : public render::Job::Config { public: float getResolutionScale() const { return resolutionScale; } void setResolutionScale(float scale) { - resolutionScale = std::max(0.1f, std::min(1.0f, resolutionScale)); + resolutionScale = std::max(0.1f, std::min(2.0f, scale)); } signals: diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 18532b7a66..5c20d33983 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -205,6 +205,27 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer }); } +void NewFramebuffer::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { + RenderArgs* args = renderContext->args; + // auto frameSize = input; + output.reset(); + + glm::uvec2 frameSize(args->_viewport.z, args->_viewport.w); + + if (_outputFramebuffer && _outputFramebuffer->getSize() != frameSize) { + _outputFramebuffer.reset(); + } + + if (!_outputFramebuffer) { + _outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("newFramebuffer.out")); + auto colorFormat = gpu::Element::COLOR_SRGBA_32; + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); + auto colorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); + _outputFramebuffer->setRenderBuffer(0, colorTexture); + } + + output = _outputFramebuffer; +} void ResolveFramebuffer::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { RenderArgs* args = renderContext->args; diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index 8fd7f22a21..2d2ec0031a 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -95,6 +95,17 @@ public: }; +class NewFramebuffer { +public: + using Input = glm::uvec2; + using Output = gpu::FramebufferPointer; + using JobModel = render::Job::ModelIO; + + void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); +private: + gpu::FramebufferPointer _outputFramebuffer; +}; + class ResolveFramebuffer { public: using Inputs = render::VaryingSet2; diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index a53b480b9f..d1c727f78d 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -50,11 +51,11 @@ extern void initForwardPipelines(ShapePlumber& plumber); void RenderForwardTask::configure(const Config& config) { // Propagate resolution scale to sub jobs who need it auto preparePrimaryBufferConfig = config.getConfig("PreparePrimaryBuffer"); -// auto upsamplePrimaryBufferConfig = config.getConfig("PrimaryBufferUpscale"); + auto upsamplePrimaryBufferConfig = config.getConfig("PrimaryBufferUpscale"); assert(preparePrimaryBufferConfig); -// assert(upsamplePrimaryBufferConfig); + assert(upsamplePrimaryBufferConfig); preparePrimaryBufferConfig->setResolutionScale(config.resolutionScale); - // upsamplePrimaryBufferConfig->setProperty("factor", 1.0f / config.resolutionScale); + upsamplePrimaryBufferConfig->setProperty("factor", 1.0f / config.resolutionScale); } void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { @@ -141,24 +142,35 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend task.addJob("DrawZoneStack", debugZoneInputs); } + + const auto newResolvedFramebuffer = task.addJob("MakeResolvingFramebuffer"); // Just resolve the msaa const auto resolveInputs = - ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, static_cast(nullptr)).asVarying(); + // ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, static_cast(nullptr)).asVarying(); + ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, newResolvedFramebuffer).asVarying(); const auto resolvedFramebuffer = task.addJob("Resolve", resolveInputs); - //auto resolvedFramebuffer = task.addJob("Resolve", framebuffer); + // auto resolvedFramebuffer = task.addJob("Resolve", framebuffer); #if defined(Q_OS_ANDROID) #else + + // Upscale to finale resolution + const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", resolvedFramebuffer); + // Lighting Buffer ready for tone mapping // Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify // the output FBO as null, which causes the tonemapping to target the blit framebuffer - const auto toneMappingInputs = ToneMappingDeferred::Inputs(resolvedFramebuffer, static_cast(nullptr)).asVarying(); + // const auto toneMappingInputs = ToneMappingDeferred::Inputs(resolvedFramebuffer, static_cast(nullptr)).asVarying(); + const auto toneMappingInputs = ToneMappingDeferred::Inputs(primaryFramebuffer, static_cast(nullptr)).asVarying(); + // const auto toneMappingInputs = ToneMappingDeferred::Inputs(resolvedFramebuffer, newResolvedFramebuffer).asVarying(); task.addJob("ToneMapping", toneMappingInputs); + + #endif // Layered Overlays // Composite the HUD and HUD overlays - task.addJob("HUD", resolvedFramebuffer); + task.addJob("HUD", primaryFramebuffer); const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying(); @@ -201,20 +213,12 @@ void PreparePrimaryFramebufferMSAA::run(const RenderContextPointer& renderContex if (!_framebuffer || (_framebuffer->getSize() != scaledFrameSize) || (_framebuffer->getNumSamples() != _numSamples)) { _framebuffer = createFramebuffer("forward", scaledFrameSize, _numSamples); } -/* - auto args = renderContext->args; - gpu::doInBatch("PrepareFramebuffer::run", args->_context, [&](gpu::Batch& batch) { - batch.enableStereo(false); - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - batch.setFramebuffer(_framebuffer); - batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH | - gpu::Framebuffer::BUFFER_STENCIL, - vec4(vec3(0), 0), 1.0, 0, true); - });*/ framebuffer = _framebuffer; + + // Set viewport for the rest of the scaled passes + renderContext->args->_viewport.z = scaledFrameSize.x; + renderContext->args->_viewport.w = scaledFrameSize.y; } void PrepareForward::run(const RenderContextPointer& renderContext, const Inputs& inputs) { diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index d4eb96d1e9..8cca5ec912 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -47,7 +47,7 @@ class PreparePrimaryFramebufferMSAAConfig : public render::Job::Config { public: float getResolutionScale() const { return resolutionScale; } void setResolutionScale(float scale) { - resolutionScale = std::max(0.1f, std::min(1.0f, resolutionScale)); + resolutionScale = std::max(0.1f, std::min(2.0f, scale)); } int getNumSamples() const { return numSamples; } diff --git a/libraries/render/src/render/ResampleTask.cpp b/libraries/render/src/render/ResampleTask.cpp index ed4d0ddfd0..efded25306 100644 --- a/libraries/render/src/render/ResampleTask.cpp +++ b/libraries/render/src/render/ResampleTask.cpp @@ -135,3 +135,50 @@ void Upsample::run(const RenderContextPointer& renderContext, const gpu::Framebu args->_viewport = viewport; } } + +gpu::PipelinePointer Upsample2::_pipeline; + +void Upsample2::configure(const Config& config) { + _factor = config.factor; +} + +void Upsample2::run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + RenderArgs* args = renderContext->args; + auto sourceFramebuffer = input; + // auto srcFramebuffer = input.get0(); + // auto dstFramebuffer = input.get1(); + +// resampledFrameBuffer = getResampledFrameBuffer(sourceFramebuffer); + resampledFrameBuffer = args->_blitFramebuffer; + + if (resampledFrameBuffer != sourceFramebuffer) { + if (!_pipeline) { + gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::drawTransformUnitQuadTextureOpaque); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(gpu::State::DepthTest(false, false)); + _pipeline = gpu::Pipeline::create(program, state); + } + const auto bufferSize = resampledFrameBuffer->getSize(); + glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y }; + + gpu::doInBatch("Upsample::run", args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + + batch.setFramebuffer(resampledFrameBuffer); + + batch.setViewportTransform(viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setPipeline(_pipeline); + + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, viewport)); + batch.setResourceTexture(0, sourceFramebuffer->getRenderBuffer(0)); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); + + // Set full final viewport + args->_viewport = viewport; + } +} diff --git a/libraries/render/src/render/ResampleTask.h b/libraries/render/src/render/ResampleTask.h index 25f9c6a3e9..7aef681c77 100644 --- a/libraries/render/src/render/ResampleTask.h +++ b/libraries/render/src/render/ResampleTask.h @@ -67,6 +67,25 @@ namespace render { gpu::FramebufferPointer getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer); }; + + class Upsample2 { + public: + // using Input = render::VaryingSet2; + using Input = gpu::FramebufferPointer; + using Config = UpsampleConfig; + using JobModel = Job::ModelIO; + + Upsample2(float factor = 2.0f) : _factor{ factor } {} + + void configure(const Config& config); + void run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer); + + protected: + + static gpu::PipelinePointer _pipeline; + + float _factor{ 2.0f }; + }; } #endif // hifi_render_ResampleTask_h diff --git a/scripts/developer/utilities/render/luci/RenderSettings.qml b/scripts/developer/utilities/render/luci/RenderSettings.qml index 4da63bbcd1..ff2197de15 100644 --- a/scripts/developer/utilities/render/luci/RenderSettings.qml +++ b/scripts/developer/utilities/render/luci/RenderSettings.qml @@ -35,7 +35,7 @@ Column { object: Render property: "viewportResolutionScale" min: 0.1 - max: 1.0 + max: 2.0 } } From e5a772a9b8e8dde1c4dab175d8817f50aaa9ae72 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 14 Jun 2019 17:54:15 -0700 Subject: [PATCH 03/63] Introducing the HUD layer rendering pass into it s own task and file --- .../render-utils/src/RenderCommonTask.cpp | 28 --------- libraries/render-utils/src/RenderCommonTask.h | 10 ---- .../render-utils/src/RenderDeferredTask.cpp | 15 +---- .../render-utils/src/RenderForwardTask.cpp | 12 ++-- .../render-utils/src/RenderHUDLayerTask.cpp | 60 +++++++++++++++++++ .../render-utils/src/RenderHUDLayerTask.h | 34 +++++++++++ .../utilities/render/luci/RenderSettings.qml | 2 +- 7 files changed, 102 insertions(+), 59 deletions(-) create mode 100644 libraries/render-utils/src/RenderHUDLayerTask.cpp create mode 100644 libraries/render-utils/src/RenderHUDLayerTask.h diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 5c20d33983..90899a6d2a 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -106,34 +106,6 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& } } -void CompositeHUD::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs) { - assert(renderContext->args); - assert(renderContext->args->_context); - - // We do not want to render HUD elements in secondary camera - if (renderContext->args->_renderMode == RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) { - return; - } - - // Grab the HUD texture -#if !defined(DISABLE_QML) - gpu::doInBatch("CompositeHUD", renderContext->args->_context, [&](gpu::Batch& batch) { - glm::mat4 projMat; - Transform viewMat; - renderContext->args->getViewFrustum().evalProjectionMatrix(projMat); - renderContext->args->getViewFrustum().evalViewTransform(viewMat); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat, true); - if (inputs) { - batch.setFramebuffer(inputs); - } - if (renderContext->args->_hudOperator) { - renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE); - } - }); -#endif -} - void Blit::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) { assert(renderContext->args); assert(renderContext->args->_context); diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index 2d2ec0031a..f13bdf1b0b 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -77,16 +77,6 @@ protected: bool _opaquePass { true }; }; -class CompositeHUD { -public: - // IF specified the input Framebuffer is actively set by the batch of this job before calling the HUDOperator. - // If not, the current Framebuffer is left unchanged. - //using Inputs = gpu::FramebufferPointer; - using JobModel = render::Job::ModelI; - - void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs); -}; - class Blit { public: using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index deafce0419..2a898bbaab 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -47,6 +47,7 @@ #include "FadeEffect.h" #include "BloomStage.h" #include "RenderUtilsLogging.h" +#include "RenderHUDLayerTask.h" #include "AmbientOcclusionEffect.h" #include "AntialiasingEffect.h" @@ -232,8 +233,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawInFrontOpaque", inFrontOpaquesInputs, true); task.addJob("DrawInFrontTransparent", inFrontTransparentsInputs, false); - const auto toneAndPostRangeTimer = task.addJob("BeginToneAndPostRangeTimer", "PostToneLayeredAntialiasing"); - // AA job before bloom to limit flickering const auto antialiasingInputs = Antialiasing::Inputs(deferredFrameTransform, lightingFramebuffer, linearDepthTarget, velocityBuffer).asVarying(); task.addJob("Antialiasing", antialiasingInputs); @@ -257,16 +256,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Upscale to finale resolution const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", scaledPrimaryFramebuffer); - // Composite the HUD and HUD overlays - task.addJob("HUD", primaryFramebuffer); - - const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); - const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); - const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying(); - task.addJob("DrawHUDOpaque", hudOpaquesInputs, true); - task.addJob("DrawHUDTransparent", hudTransparentsInputs, false); - - task.addJob("ToneAndPostRangeTimer", toneAndPostRangeTimer); + const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); + task.addJob("RenderHUDLayer", renderHUDLayerInputs); // Blit! task.addJob("Blit", primaryFramebuffer); diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index d1c727f78d..eaa83eba2d 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -33,6 +33,7 @@ #include "FramebufferCache.h" #include "TextureCache.h" #include "RenderCommonTask.h" +#include "RenderHUDLayerTask.h" namespace ru { using render_utils::slot::texture::Texture; @@ -168,14 +169,9 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend #endif - // Layered Overlays - // Composite the HUD and HUD overlays - task.addJob("HUD", primaryFramebuffer); - - const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); - const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying(); - task.addJob("DrawHUDOpaque", hudOpaquesInputs, true); - task.addJob("DrawHUDTransparent", hudTransparentsInputs, false); + // HUD Layer + const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); + task.addJob("RenderHUDLayer", renderHUDLayerInputs); // Disable blit because we do tonemapping and compositing directly to the blit FBO // Blit! diff --git a/libraries/render-utils/src/RenderHUDLayerTask.cpp b/libraries/render-utils/src/RenderHUDLayerTask.cpp new file mode 100644 index 0000000000..a34f3b3e49 --- /dev/null +++ b/libraries/render-utils/src/RenderHUDLayerTask.cpp @@ -0,0 +1,60 @@ +// +// Created by Sam Gateau on 2019/06/14 +// Copyright 2013-2019 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 "RenderHUDLayerTask.h" + +#include +#include "RenderCommonTask.h" + +using namespace render; + +void CompositeHUD::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs) { + assert(renderContext->args); + assert(renderContext->args->_context); + + // We do not want to render HUD elements in secondary camera + if (renderContext->args->_renderMode == RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) { + return; + } + + // Grab the HUD texture +#if !defined(DISABLE_QML) + gpu::doInBatch("CompositeHUD", renderContext->args->_context, [&](gpu::Batch& batch) { + glm::mat4 projMat; + Transform viewMat; + renderContext->args->getViewFrustum().evalProjectionMatrix(projMat); + renderContext->args->getViewFrustum().evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat, true); + if (inputs) { + batch.setFramebuffer(inputs); + } + if (renderContext->args->_hudOperator) { + renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE); + } + }); +#endif +} + +void RenderHUDLayerTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { + const auto& inputs = input.get(); + + const auto& primaryFramebuffer = inputs[0]; + const auto& lightingModel = inputs[1]; + const auto& hudOpaque = inputs[2]; + const auto& hudTransparent = inputs[3]; + + // Composite the HUD and HUD overlays + task.addJob("HUD", primaryFramebuffer); + + // And HUD Layer objects + const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); + const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); + const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying(); + task.addJob("DrawHUDOpaque", hudOpaquesInputs, true); + task.addJob("DrawHUDTransparent", hudTransparentsInputs, false); +} diff --git a/libraries/render-utils/src/RenderHUDLayerTask.h b/libraries/render-utils/src/RenderHUDLayerTask.h new file mode 100644 index 0000000000..78cd009636 --- /dev/null +++ b/libraries/render-utils/src/RenderHUDLayerTask.h @@ -0,0 +1,34 @@ +// +// Created by Sam Gateau on 2019/06/14 +// Copyright 2013-2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_RenderHUDLayerTask_h +#define hifi_RenderHUDLayerTask_h + +#include "LightingModel.h" + + +class CompositeHUD { +public: + // IF specified the input Framebuffer is actively set by the batch of this job before calling the HUDOperator. + // If not, the current Framebuffer is left unchanged. + //using Inputs = gpu::FramebufferPointer; + using JobModel = render::Job::ModelI; + + void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs); +}; + +class RenderHUDLayerTask { +public: + // Framebuffer where to draw, lighting model, opaque items, transparent items + using Input = render::VaryingSet4; + using JobModel = render::Task::ModelI; + + void build(JobModel& task, const render::Varying& input, render::Varying& output); +}; + +#endif // hifi_RenderHUDLayerTask_h \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci/RenderSettings.qml b/scripts/developer/utilities/render/luci/RenderSettings.qml index ff2197de15..06f5512824 100644 --- a/scripts/developer/utilities/render/luci/RenderSettings.qml +++ b/scripts/developer/utilities/render/luci/RenderSettings.qml @@ -35,7 +35,7 @@ Column { object: Render property: "viewportResolutionScale" min: 0.1 - max: 2.0 + max: 1.1 } } From d9f1aa73ba830deb31a66a3609d1cea3b9c7008a Mon Sep 17 00:00:00 2001 From: Preston Bezos Date: Mon, 17 Jun 2019 09:12:32 -0700 Subject: [PATCH 04/63] switched top bar icons and changes input device meter to be in icon instead of in bar --- .../inputDeviceButton/InputDeviceButton.qml | 121 ++++++++---------- .../inputDeviceButton/images/mic-clip-i.svg | 32 ++--- .../inputDeviceButton/images/mic-gate-i.svg | 22 ++-- .../inputDeviceButton/images/mic-mute-a.svg | 26 ++-- .../inputDeviceButton/images/mic-mute-i.svg | 23 ++-- .../inputDeviceButton/images/mic-ptt-i.svg | 23 +++- .../inputDeviceButton/images/mic-unmute-a.svg | 72 +++-------- .../images/mic-unmute-i-old.svg | 9 ++ .../inputDeviceButton/images/mic-unmute-i.svg | 20 ++- .../simplifiedUI/topBar/SimplifiedTopBar.qml | 45 ++++--- .../topBar/images/desktopMode.svg | 18 +-- .../topBar/images/outputDeviceLoud.svg | 18 ++- .../topBar/images/outputDeviceMuted.svg | 27 ++-- .../simplifiedUI/topBar/images/settings.svg | 30 +++-- .../simplifiedUI/topBar/images/status.svg | 3 - .../simplifiedUI/topBar/images/statusAway.svg | 9 ++ .../topBar/images/statusPresent.svg | 7 + .../simplifiedUI/topBar/images/vrMode.svg | 21 ++- 18 files changed, 259 insertions(+), 267 deletions(-) create mode 100644 interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i-old.svg delete mode 100644 interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg create mode 100644 interface/resources/qml/hifi/simplifiedUI/topBar/images/statusAway.svg create mode 100644 interface/resources/qml/hifi/simplifiedUI/topBar/images/statusPresent.svg diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml index c546af218b..751b3775a7 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml @@ -48,18 +48,6 @@ Rectangle { } } - opacity: 0.7 - - onLevelChanged: { - var rectOpacity = (muted && (level >= userSpeakingLevel)) ? 1.0 : 0.7; - if (pushToTalk && !pushingToTalk) { - rectOpacity = (mouseArea.containsMouse) ? 1.0 : 0.7; - } else if (mouseArea.containsMouse && rectOpacity != 1.0) { - rectOpacity = 1.0; - } - micBar.opacity = rectOpacity; - } - color: "#00000000" MouseArea { @@ -116,83 +104,86 @@ Rectangle { Item { id: icon anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.horizontalCenter + anchors.horizontalCenter: parent.horizontalCenter anchors.rightMargin: 2 - width: 13 - height: 21 + width: muted ? 20 : 16 + height: 22 Item { anchors.fill: parent - opacity: mouseArea.containsMouse ? 1.0 : 0.7 Image { id: image + visible: false source: (pushToTalk) ? pushToTalkIcon : muted ? mutedIcon : clipping ? clippingIcon : gated ? gatedIcon : unmutedIcon anchors.fill: parent - fillMode: Image.PreserveAspectFit } ColorOverlay { + opacity: mouseArea.containsMouse ? 1.0 : 0.7 + visible: level === 0 || micBar.muted id: imageOverlay anchors { fill: image } source: image color: pushToTalk ? (pushingToTalk ? colors.unmutedColor : colors.mutedColor) : colors.icon } - } - } - Item { - id: bar + OpacityMask { + id: bar + visible: level > 0 && !micBar.muted + anchors.fill: meterGradient + source: meterGradient + maskSource: image + } - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.horizontalCenter - anchors.leftMargin: 2 - - width: 4 - height: 21 - - Rectangle { // base - id: baseBar - radius: 4 - anchors { fill: parent } - color: colors.gutter + LinearGradient { + id: meterGradient + anchors { fill: parent } + visible: false + start: Qt.point(0, 0) + end: Qt.point(0, parent.height) + rotation: 180 + gradient: Gradient { + GradientStop { + position: 1.0 + color: colors.greenStart + } + GradientStop { + position: 0.5 + color: colors.greenEnd + } + GradientStop { + position: 0.0 + color: colors.yellow + } + } + } } - Rectangle { // mask - id: mask - height: micBar.muted ? parent.height : parent.height * level - color: micBar.muted ? colors.mutedColor : "white" + Item { width: parent.width - radius: 5 - anchors { - bottom: parent.bottom - bottomMargin: 0 - left: parent.left - leftMargin: 0 + height: parent.height-parent.height*level + anchors.top: parent.top + anchors.left: parent.left + clip:true + Image { + id: maskImage + visible: false + source: (pushToTalk) ? pushToTalkIcon : muted ? mutedIcon : + clipping ? clippingIcon : gated ? gatedIcon : unmutedIcon + anchors.top: parent.top + anchors.left: parent.left + width: parent.width + height: parent.parent.height } - } - - LinearGradient { - anchors { fill: mask } - visible: mask.visible && !micBar.muted - source: mask - start: Qt.point(0, 0) - end: Qt.point(0, bar.height) - rotation: 180 - gradient: Gradient { - GradientStop { - position: 0.0 - color: colors.greenStart - } - GradientStop { - position: 0.5 - color: colors.greenEnd - } - GradientStop { - position: 1.0 - color: colors.yellow - } + + ColorOverlay { + visible: level > 0 && !micBar.muted + anchors { fill: maskImage } + source: maskImage + color: "#b2b2b2" } + } } } diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg index 8b694c7f3d..cc2c347d6f 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg @@ -1,20 +1,14 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - + + + + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg index ac70ce66cb..f36461fdd8 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg @@ -1,13 +1,11 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg index eb36c2dd55..09fe385499 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg @@ -1,13 +1,15 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg index ebca81f370..658f129817 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg @@ -1,13 +1,12 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg index 3bf1f1bf9e..6f7e606982 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg @@ -1,8 +1,17 @@ - - -image/svg+xml - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg index 0bd0b0c238..8c8fe36955 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg @@ -1,57 +1,15 @@ - - - - - - image/svg+xml - - - - - - - - - + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i-old.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i-old.svg new file mode 100644 index 0000000000..77a0f30ed6 --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i-old.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg index 121873dd1b..c7858f9ef4 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg @@ -1,13 +1,9 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index 85b3cf149f..e3389e43d0 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -134,7 +134,7 @@ Rectangle { id: avatarButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: 16 + anchors.leftMargin: 2 width: 48 height: width @@ -203,7 +203,7 @@ Rectangle { id: inputDeviceButton anchors.verticalCenter: parent.verticalCenter anchors.left: avatarButtonContainer.right - anchors.leftMargin: 6 + anchors.leftMargin: 2 width: 32 height: width } @@ -213,7 +213,7 @@ Rectangle { id: outputDeviceButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.left: inputDeviceButton.right - anchors.leftMargin: 2 + anchors.leftMargin: 7 width: 32 height: width @@ -225,9 +225,8 @@ Rectangle { AudioScriptingInterface.systemInjectorGain === simplifiedUI.numericConstants.mutedValue source: outputDeviceButton.outputMuted ? "./images/outputDeviceMuted.svg" : "./images/outputDeviceLoud.svg" anchors.centerIn: parent - width: 20 - height: 20 - fillMode: Image.PreserveAspectFit + width: outputDeviceButton.outputMuted ? 25 : 26 + height: 22 visible: false } @@ -276,7 +275,7 @@ Rectangle { id: statusButton property string currentStatus anchors.centerIn: parent - width: 15 + width: 22 height: width radius: width/2 visible: false @@ -297,6 +296,21 @@ Rectangle { } } + Image { + id: statusIcon + source: statusButton.currentStatus === "available" ? "images/statusPresent.svg" : "images/statusAway.svg" + anchors.centerIn: parent + width: statusButton.currentStatus === "busy" ? 13 : 14 + height: statusButton.currentStatus === "busy" ? 2 : 10 + } + + ColorOverlay { + anchors.fill: statusIcon + opacity: statusButton.currentStatus ? (statusButtonMouseArea.containsMouse ? 1.0 : 0.7) : 0.7 + source: statusIcon + color: "#ffffff" + } + MouseArea { id: statusButtonMouseArea anchors.fill: parent @@ -322,8 +336,8 @@ Rectangle { id: hmdButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.right: settingsButtonContainer.left - anchors.rightMargin: 14 - width: 32 + anchors.rightMargin: 8 + width: 48 height: width visible: false @@ -331,9 +345,8 @@ Rectangle { id: displayModeImage source: HMD.active ? "./images/desktopMode.svg" : "./images/vrMode.svg" anchors.centerIn: parent - width: 29 - height: 16 - fillMode: Image.PreserveAspectFit + width: HMD.active ? 25 : 43 + height: 22 visible: false } @@ -392,16 +405,16 @@ Rectangle { id: settingsButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right - anchors.rightMargin: 16 - width: 32 + anchors.rightMargin: 2 + width: 48 height: width Image { id: settingsButtonImage source: "./images/settings.svg" anchors.centerIn: parent - width: 20 - height: 20 + width: 22 + height: 22 fillMode: Image.PreserveAspectFit visible: false } diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg index 8b04caca88..de344c2c82 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg @@ -1,13 +1,7 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg index ebd844c471..3133b320f3 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg @@ -1,3 +1,15 @@ - - - + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg index 4188175c31..38c670d8ad 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg @@ -1,14 +1,15 @@ - - - - - - image/svg+xml - - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg index 04a031d498..7d0594837f 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg @@ -1,13 +1,19 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg deleted file mode 100644 index ebd844c471..0000000000 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusAway.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusAway.svg new file mode 100644 index 0000000000..d5b4798d9e --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusAway.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusPresent.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusPresent.svg new file mode 100644 index 0000000000..af7649ba78 --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusPresent.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg index 57b564813d..1339473beb 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg @@ -1,13 +1,10 @@ - - - - - - image/svg+xml - - - - - - + + + + From bd78dd96a0146221efca082738af2ddd16f190ab Mon Sep 17 00:00:00 2001 From: Preston Bezos Date: Mon, 17 Jun 2019 11:05:47 -0700 Subject: [PATCH 05/63] replaced icons with icons that are on the whole pixel so as not to cause blur --- .../inputDeviceButton/InputDeviceButton.qml | 7 +++-- .../inputDeviceButton/images/mic-clip-i.svg | 12 ++++---- .../inputDeviceButton/images/mic-gate-i.svg | 14 +++++----- .../inputDeviceButton/images/mic-mute-a.svg | 15 ---------- .../inputDeviceButton/images/mic-mute-i.svg | 17 +++++------ .../inputDeviceButton/images/mic-ptt-a.svg | 17 ----------- .../inputDeviceButton/images/mic-ptt-i.svg | 25 ++++++++--------- .../images/mic-ptt-mute-i.svg | 18 ++++++++++++ .../inputDeviceButton/images/mic-unmute-a.svg | 15 ---------- .../images/mic-unmute-i-old.svg | 9 ------ .../inputDeviceButton/images/mic-unmute-i.svg | 2 +- .../simplifiedUI/topBar/SimplifiedTopBar.qml | 10 +------ .../topBar/images/desktopMode.svg | 7 +++-- .../topBar/images/outputDeviceLoud.svg | 21 +++++++------- .../topBar/images/outputDeviceMuted.svg | 21 +++++++------- .../simplifiedUI/topBar/images/settings.svg | 28 +++++++++---------- .../simplifiedUI/topBar/images/vrMode.svg | 12 ++++---- 17 files changed, 101 insertions(+), 149 deletions(-) delete mode 100644 interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg delete mode 100644 interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-a.svg create mode 100644 interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-mute-i.svg delete mode 100644 interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg delete mode 100644 interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i-old.svg diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml index 751b3775a7..45c7b3ad5e 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml @@ -33,6 +33,7 @@ Rectangle { readonly property string unmutedIcon: "images/mic-unmute-i.svg" readonly property string mutedIcon: "images/mic-mute-i.svg" readonly property string pushToTalkIcon: "images/mic-ptt-i.svg" + readonly property string pushToTalkMutedIcon: "images/mic-ptt-mute-i.svg" readonly property string clippingIcon: "images/mic-clip-i.svg" readonly property string gatedIcon: "images/mic-gate-i.svg" @@ -114,7 +115,7 @@ Rectangle { Image { id: image visible: false - source: (pushToTalk) ? pushToTalkIcon : muted ? mutedIcon : + source: (pushToTalk) ? (pushingToTalk ? pushToTalkIcon : pushToTalkMutedIcon) : muted ? mutedIcon : clipping ? clippingIcon : gated ? gatedIcon : unmutedIcon anchors.fill: parent } @@ -125,7 +126,7 @@ Rectangle { id: imageOverlay anchors { fill: image } source: image - color: pushToTalk ? (pushingToTalk ? colors.unmutedColor : colors.mutedColor) : colors.icon + color: pushToTalk ? (pushingToTalk ? colors.icon : colors.mutedColor) : colors.icon } OpacityMask { @@ -169,7 +170,7 @@ Rectangle { Image { id: maskImage visible: false - source: (pushToTalk) ? pushToTalkIcon : muted ? mutedIcon : + source: (pushToTalk) ? (pushingToTalk ? pushToTalkIcon : pushToTalkMutedIcon) : muted ? mutedIcon : clipping ? clippingIcon : gated ? gatedIcon : unmutedIcon anchors.top: parent.top anchors.left: parent.left diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg index cc2c347d6f..f16b9e1a56 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg @@ -1,14 +1,14 @@ + viewBox="0 0 16 22" style="enable-background:new 0 0 16 22;" xml:space="preserve"> - + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg index f36461fdd8..56e0e1df57 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg @@ -1,11 +1,11 @@ - + viewBox="0 0 16 22" style="enable-background:new 0 0 16 22;" xml:space="preserve"> + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg deleted file mode 100644 index 09fe385499..0000000000 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg index 658f129817..a00b7f9a9c 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg @@ -1,12 +1,13 @@ - + viewBox="0 0 20 22" style="enable-background:new 0 0 20 22;" xml:space="preserve"> + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-a.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-a.svg deleted file mode 100644 index 3ce7c0ca51..0000000000 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-a.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - image/svg+xml - - mic-ptt-a - - - - - - - mic-ptt-a - - diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg index 6f7e606982..7dd65c96a0 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg @@ -1,17 +1,16 @@ - + viewBox="0 0 14 22" style="enable-background:new 0 0 14 22;" xml:space="preserve"> + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-mute-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-mute-i.svg new file mode 100644 index 0000000000..fef3e533b4 --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-mute-i.svg @@ -0,0 +1,18 @@ + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg deleted file mode 100644 index 8c8fe36955..0000000000 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i-old.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i-old.svg deleted file mode 100644 index 77a0f30ed6..0000000000 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i-old.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg index c7858f9ef4..dd8bfa087f 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg @@ -1,6 +1,6 @@ - -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) && - topBarInventoryModel.count > 0) { - Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true); - MyAvatar.skeletonModelURL = topBarInventoryModel.get(0).download_url; - } } } @@ -101,8 +95,7 @@ Rectangle { inventoryFullyReceived = true; // If we have an avatar in our inventory AND we haven't already auto-selected an avatar... - if ((!Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatar", false) || - MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) && topBarInventoryModel.count > 0) { + if (!Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatar", false) && topBarInventoryModel.count > 0) { Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true); MyAvatar.skeletonModelURL = topBarInventoryModel.get(0).download_url; } @@ -422,7 +415,6 @@ Rectangle { anchors.centerIn: parent width: 22 height: 22 - fillMode: Image.PreserveAspectFit visible: false } diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg index de344c2c82..dfb1a1a662 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg @@ -1,7 +1,8 @@ - + viewBox="0 0 25 22" style="enable-background:new 0 0 25 22;" xml:space="preserve"> + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg index 3133b320f3..798ce62ccd 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg @@ -1,15 +1,14 @@ - + viewBox="0 0 26 22" style="enable-background:new 0 0 26 22;" xml:space="preserve"> + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg index 38c670d8ad..9b7e3ad613 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg @@ -1,15 +1,14 @@ - + viewBox="0 0 25 22" style="enable-background:new 0 0 25 22;" xml:space="preserve"> + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg index 7d0594837f..910ef353e1 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg @@ -1,19 +1,17 @@ - + viewBox="0 0 22 22" style="enable-background:new 0 0 22 22;" xml:space="preserve"> + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg index 1339473beb..f19989c0b1 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg @@ -1,10 +1,10 @@ - + viewBox="0 0 42 22" style="enable-background:new 0 0 42 22;" xml:space="preserve"> + From 7879dbf68782309715733abd2234dde4dc08b4bc Mon Sep 17 00:00:00 2001 From: Preston Bezos Date: Mon, 17 Jun 2019 13:13:43 -0700 Subject: [PATCH 06/63] changed width of ptt muted icon --- .../hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml index 45c7b3ad5e..238821970b 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml @@ -107,7 +107,7 @@ Rectangle { anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter anchors.rightMargin: 2 - width: muted ? 20 : 16 + width: pushToTalk ? 16 : (muted ? 20 : 16) height: 22 Item { From 538b15dd57c87cb504d37b76659e7990495f0d1c Mon Sep 17 00:00:00 2001 From: Preston Bezos Date: Mon, 17 Jun 2019 13:20:25 -0700 Subject: [PATCH 07/63] caught a couple of edge cases for mic states --- .../simplifiedUI/inputDeviceButton/InputDeviceButton.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml index 238821970b..a7b2088fc9 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml @@ -122,7 +122,7 @@ Rectangle { ColorOverlay { opacity: mouseArea.containsMouse ? 1.0 : 0.7 - visible: level === 0 || micBar.muted + visible: level === 0 || micBar.muted || micBar.clipping id: imageOverlay anchors { fill: image } source: image @@ -131,7 +131,7 @@ Rectangle { OpacityMask { id: bar - visible: level > 0 && !micBar.muted + visible: level > 0 && !micBar.muted && !micBar.clipping anchors.fill: meterGradient source: meterGradient maskSource: image @@ -179,7 +179,7 @@ Rectangle { } ColorOverlay { - visible: level > 0 && !micBar.muted + visible: level > 0 && !micBar.muted && !micBar.clipping anchors { fill: maskImage } source: maskImage color: "#b2b2b2" From 251faf217188e86672f52dd5feea1788e9836251 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 18 Jun 2019 17:08:08 -0700 Subject: [PATCH 08/63] Trying to clean up the solution... --- .../render-utils/src/RenderCommonTask.cpp | 36 ----------------- libraries/render-utils/src/RenderCommonTask.h | 12 ------ .../render-utils/src/RenderDeferredTask.cpp | 10 +++-- .../render-utils/src/RenderForwardTask.cpp | 40 ++++++++++--------- .../render-utils/src/ToneMappingEffect.cpp | 21 ++++++---- .../render-utils/src/ToneMappingEffect.h | 7 ++-- libraries/render/src/render/ResampleTask.cpp | 6 +-- libraries/render/src/render/ResampleTask.h | 6 +-- 8 files changed, 51 insertions(+), 87 deletions(-) diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 90899a6d2a..50338ba6a6 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -228,42 +228,6 @@ void ResolveFramebuffer::run(const render::RenderContextPointer& renderContext, }); } -void ResolveNewFramebuffer::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { - RenderArgs* args = renderContext->args; - auto srcFbo = inputs; - outputs.reset(); - - // Check valid src - if (!srcFbo) { - return; - } - - // Check valid size for sr and dest - auto frameSize(srcFbo->getSize()); - - // Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering - if (_outputFramebuffer && _outputFramebuffer->getSize() != frameSize) { - _outputFramebuffer.reset(); - } - - if (!_outputFramebuffer) { - _outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("resolvedNew.out")); - auto colorFormat = gpu::Element::COLOR_SRGBA_32; - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); - auto colorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); - _outputFramebuffer->setRenderBuffer(0, colorTexture); - } - - gpu::Vec4i rectSrc; - rectSrc.z = frameSize.x; - rectSrc.w = frameSize.y; - gpu::doInBatch("ResolveNew", args->_context, [&](gpu::Batch& batch) { batch.blit(srcFbo, rectSrc, _outputFramebuffer, rectSrc); }); - - outputs = _outputFramebuffer; -} - - - void ExtractFrustums::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { assert(renderContext->args); assert(renderContext->args->_context); diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index f13bdf1b0b..4a0cf3dae4 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -105,18 +105,6 @@ public: void run(const render::RenderContextPointer& renderContext, const Inputs& source, Outputs& dest); }; -class ResolveNewFramebuffer { -public: - using Inputs = gpu::FramebufferPointer; - using Outputs = gpu::FramebufferPointer; - using JobModel = render::Job::ModelIO; - - void run(const render::RenderContextPointer& renderContext, const Inputs& source, Outputs& dest); -private: - gpu::FramebufferPointer _outputFramebuffer; -}; - - class ExtractFrustums { public: diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 2a898bbaab..eb69bad32e 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -242,8 +242,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("Bloom", bloomInputs); // Lighting Buffer ready for tone mapping - const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, scaledPrimaryFramebuffer).asVarying(); - task.addJob("ToneMapping", toneMappingInputs); + const auto toneMappingInputs = ToneMappingDeferred::Input(lightingFramebuffer, scaledPrimaryFramebuffer).asVarying(); + const auto toneMappedBuffer = task.addJob("ToneMapping", toneMappingInputs); // Debugging task is happening in the "over" layer after tone mapping and just before HUD { // Debug the bounds of the rendered items, still look at the zbuffer @@ -254,13 +254,15 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren } // Upscale to finale resolution - const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", scaledPrimaryFramebuffer); + //const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", toneMappedBuffer); + const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", toneMappedBuffer); + // HUD Layer const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); task.addJob("RenderHUDLayer", renderHUDLayerInputs); // Blit! - task.addJob("Blit", primaryFramebuffer); + // task.addJob("Blit", primaryFramebuffer); } RenderDeferredTaskDebug::RenderDeferredTaskDebug() { diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index eaa83eba2d..bf1a270e50 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -52,7 +52,7 @@ extern void initForwardPipelines(ShapePlumber& plumber); void RenderForwardTask::configure(const Config& config) { // Propagate resolution scale to sub jobs who need it auto preparePrimaryBufferConfig = config.getConfig("PreparePrimaryBuffer"); - auto upsamplePrimaryBufferConfig = config.getConfig("PrimaryBufferUpscale"); + auto upsamplePrimaryBufferConfig = config.getConfig("PrimaryBufferUpscale"); assert(preparePrimaryBufferConfig); assert(upsamplePrimaryBufferConfig); preparePrimaryBufferConfig->setResolutionScale(config.resolutionScale); @@ -143,39 +143,43 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend task.addJob("DrawZoneStack", debugZoneInputs); } - - const auto newResolvedFramebuffer = task.addJob("MakeResolvingFramebuffer"); - // Just resolve the msaa - const auto resolveInputs = - // ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, static_cast(nullptr)).asVarying(); - ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, newResolvedFramebuffer).asVarying(); - const auto resolvedFramebuffer = task.addJob("Resolve", resolveInputs); - // auto resolvedFramebuffer = task.addJob("Resolve", framebuffer); - #if defined(Q_OS_ANDROID) -#else + const auto resolveInputs = + ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, static_cast(nullptr)).asVarying(); - // Upscale to finale resolution - const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", resolvedFramebuffer); + // Just resolve the msaa + const auto resolvedFramebuffer = task.addJob("Resolve", resolveInputs); + + const auto toneMappedBuffer = resolvedFramebuffer; +#else + const auto newResolvedFramebuffer = task.addJob("MakeResolvingFramebuffer"); + + const auto resolveInputs = ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, newResolvedFramebuffer).asVarying(); + + // Just resolve the msaa + const auto resolvedFramebuffer = task.addJob("Resolve", resolveInputs); // Lighting Buffer ready for tone mapping // Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify // the output FBO as null, which causes the tonemapping to target the blit framebuffer // const auto toneMappingInputs = ToneMappingDeferred::Inputs(resolvedFramebuffer, static_cast(nullptr)).asVarying(); - const auto toneMappingInputs = ToneMappingDeferred::Inputs(primaryFramebuffer, static_cast(nullptr)).asVarying(); - // const auto toneMappingInputs = ToneMappingDeferred::Inputs(resolvedFramebuffer, newResolvedFramebuffer).asVarying(); - task.addJob("ToneMapping", toneMappingInputs); - + // const auto toneMappingInputs = ToneMappingDeferred::Input(resolvedFramebuffer, static_cast(nullptr)).asVarying(); + const auto toneMappingInputs = ToneMappingDeferred::Input(resolvedFramebuffer, resolvedFramebuffer).asVarying(); + // const auto toneMappingInputs = ToneMappingDeferred::Input(resolvedFramebuffer, newResolvedFramebuffer).asVarying(); + const auto toneMappedBuffer = task.addJob("ToneMapping", toneMappingInputs); #endif + // Upscale to finale resolution + const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", toneMappedBuffer); + // HUD Layer const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); task.addJob("RenderHUDLayer", renderHUDLayerInputs); // Disable blit because we do tonemapping and compositing directly to the blit FBO // Blit! - // task.addJob("Blit", framebuffer); + // task.addJob("Blit", primaryFramebuffer); } gpu::FramebufferPointer PreparePrimaryFramebufferMSAA::createFramebuffer(const char* name, const glm::uvec2& frameSize, int numSamples) { diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index 64a2adb5d4..b7cc5d3d80 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -47,14 +47,13 @@ void ToneMappingEffect::setToneCurve(ToneCurve curve) { } } -void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& lightingBuffer, const gpu::FramebufferPointer& requestedDestinationFramebuffer) { +void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& lightingBuffer, const gpu::FramebufferPointer& destinationFramebuffer) { if (!_blitLightBuffer) { init(args); } - - auto destinationFramebuffer = requestedDestinationFramebuffer; - if (!destinationFramebuffer) { - destinationFramebuffer = args->_blitFramebuffer; + + if (!lightingBuffer || !destinationFramebuffer) { + return; } auto framebufferSize = glm::ivec2(lightingBuffer->getDimensions()); @@ -83,9 +82,15 @@ void ToneMappingDeferred::configure(const Config& config) { _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)config.curve); } -void ToneMappingDeferred::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { +void ToneMappingDeferred::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { + + auto lightingBuffer = input.get0()->getRenderBuffer(0); + auto destFbo = input.get1(); + + if (!destFbo) { + destFbo = renderContext->args->_blitFramebuffer; + } - auto lightingBuffer = inputs.get0()->getRenderBuffer(0); - auto destFbo = inputs.get1(); _toneMappingEffect.render(renderContext->args, lightingBuffer, destFbo); + output = destFbo; } diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index 69694b13f5..faf6e514e9 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -82,12 +82,13 @@ signals: class ToneMappingDeferred { public: // Inputs: lightingFramebuffer, destinationFramebuffer - using Inputs = render::VaryingSet2; + using Input = render::VaryingSet2; + using Output = gpu::FramebufferPointer; using Config = ToneMappingConfig; - using JobModel = render::Job::ModelI; + using JobModel = render::Job::ModelIO; void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); + void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); ToneMappingEffect _toneMappingEffect; }; diff --git a/libraries/render/src/render/ResampleTask.cpp b/libraries/render/src/render/ResampleTask.cpp index efded25306..93b2e0e97d 100644 --- a/libraries/render/src/render/ResampleTask.cpp +++ b/libraries/render/src/render/ResampleTask.cpp @@ -136,13 +136,13 @@ void Upsample::run(const RenderContextPointer& renderContext, const gpu::Framebu } } -gpu::PipelinePointer Upsample2::_pipeline; +gpu::PipelinePointer UpsampleToBlitFramebuffer::_pipeline; -void Upsample2::configure(const Config& config) { +void UpsampleToBlitFramebuffer::configure(const Config& config) { _factor = config.factor; } -void Upsample2::run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer) { +void UpsampleToBlitFramebuffer::run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; diff --git a/libraries/render/src/render/ResampleTask.h b/libraries/render/src/render/ResampleTask.h index 7aef681c77..8b5bbd5c4e 100644 --- a/libraries/render/src/render/ResampleTask.h +++ b/libraries/render/src/render/ResampleTask.h @@ -68,14 +68,14 @@ namespace render { gpu::FramebufferPointer getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer); }; - class Upsample2 { + class UpsampleToBlitFramebuffer { public: // using Input = render::VaryingSet2; using Input = gpu::FramebufferPointer; using Config = UpsampleConfig; - using JobModel = Job::ModelIO; + using JobModel = Job::ModelIO; - Upsample2(float factor = 2.0f) : _factor{ factor } {} + UpsampleToBlitFramebuffer(float factor = 2.0f) : _factor{ factor } {} void configure(const Config& config); void run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer); From b5e4a4737557ab34a8fbf954682a34958e54d92f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 19 Jun 2019 17:33:26 -0700 Subject: [PATCH 09/63] Proper allocation of the resource in forward and starting to remove the ui as we have it --- interface/src/Application.cpp | 7 ----- .../scripting/RenderScriptingInterface.cpp | 18 ++---------- .../src/scripting/RenderScriptingInterface.h | 1 + .../render-utils/src/RenderCommonTask.cpp | 29 +++++++++++++++++++ libraries/render-utils/src/RenderCommonTask.h | 11 +++++++ .../render-utils/src/RenderForwardTask.cpp | 10 ++----- .../utilities/render/luci/RenderSettings.qml | 4 +-- 7 files changed, 49 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f9470782bf..bb093d3fc0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3743,13 +3743,6 @@ void Application::resizeGL() { auto renderResolutionScale = getRenderResolutionScale(); if (displayPlugin->getRenderResolutionScale() != renderResolutionScale) { - auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); - assert(renderConfig); - auto mainView = renderConfig->getConfig("RenderMainView.RenderDeferredTask"); - // mainView can be null if we're rendering in forward mode - if (mainView) { - mainView->setProperty("resolutionScale", renderResolutionScale); - } displayPlugin->setRenderResolutionScale(renderResolutionScale); } diff --git a/interface/src/scripting/RenderScriptingInterface.cpp b/interface/src/scripting/RenderScriptingInterface.cpp index 4e07d77c0b..1a0be3b9b2 100644 --- a/interface/src/scripting/RenderScriptingInterface.cpp +++ b/interface/src/scripting/RenderScriptingInterface.cpp @@ -30,11 +30,13 @@ void RenderScriptingInterface::loadSettings() { _shadowsEnabled = (_shadowsEnabledSetting.get()); _ambientOcclusionEnabled = (_ambientOcclusionEnabledSetting.get()); _antialiasingEnabled = (_antialiasingEnabledSetting.get()); + _viewportResolutionScale = (_viewportResolutionScaleSetting.get()); }); forceRenderMethod((RenderMethod)_renderMethod); forceShadowsEnabled(_shadowsEnabled); forceAmbientOcclusionEnabled(_ambientOcclusionEnabled); forceAntialiasingEnabled(_antialiasingEnabled); + forceViewportResolutionScale(_viewportResolutionScale); } RenderScriptingInterface::RenderMethod RenderScriptingInterface::getRenderMethod() const { @@ -159,7 +161,7 @@ void RenderScriptingInterface::setViewportResolutionScale(float scale) { void RenderScriptingInterface::forceViewportResolutionScale(float scale) { _renderSettingLock.withWriteLock([&] { _viewportResolutionScale = (scale); - // _antialiasingEnabledSetting.set(enabled); + _viewportResolutionScaleSetting.set(scale); auto renderConfig = qApp->getRenderEngine()->getConfiguration(); assert(renderConfig); @@ -173,19 +175,5 @@ void RenderScriptingInterface::forceViewportResolutionScale(float scale) { if (forwardView) { forwardView->setProperty("resolutionScale", _viewportResolutionScale); } -/* - auto mainViewJitterCamConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.JitterCam"); - auto mainViewAntialiasingConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.Antialiasing"); - if (mainViewJitterCamConfig && mainViewAntialiasingConfig) { - Menu::getInstance()->setIsOptionChecked(MenuOption::AntiAliasing, enabled); - if (enabled) { - mainViewJitterCamConfig->play(); - mainViewAntialiasingConfig->setDebugFXAA(false); - } - else { - mainViewJitterCamConfig->none(); - mainViewAntialiasingConfig->setDebugFXAA(true); - } - }*/ }); } diff --git a/interface/src/scripting/RenderScriptingInterface.h b/interface/src/scripting/RenderScriptingInterface.h index 11a071c86a..9b96448c9d 100644 --- a/interface/src/scripting/RenderScriptingInterface.h +++ b/interface/src/scripting/RenderScriptingInterface.h @@ -159,6 +159,7 @@ private: Setting::Handle _shadowsEnabledSetting { "shadowsEnabled", true }; Setting::Handle _ambientOcclusionEnabledSetting { "ambientOcclusionEnabled", false }; Setting::Handle _antialiasingEnabledSetting { "antialiasingEnabled", true }; + Setting::Handle _viewportResolutionScaleSetting { "viewportResolutionScale", 1.0f }; // Force assign both setting AND runtime value to the parameter value void forceRenderMethod(RenderMethod renderMethod); diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 50338ba6a6..39024eaeab 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -199,6 +199,35 @@ void NewFramebuffer::run(const render::RenderContextPointer& renderContext, cons output = _outputFramebuffer; } +void NewOrDefaultFramebuffer::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { + RenderArgs* args = renderContext->args; + // auto frameSize = input; + glm::uvec2 frameSize(args->_viewport.z, args->_viewport.w); + output.reset(); + + // First if the default Framebuffer is the correct size then use it + auto destBlitFbo = args->_blitFramebuffer; + if (destBlitFbo && destBlitFbo->getSize() == frameSize) { + output = destBlitFbo; + return; + } + + // Else use the lodal Framebuffer + if (_outputFramebuffer && _outputFramebuffer->getSize() != frameSize) { + _outputFramebuffer.reset(); + } + + if (!_outputFramebuffer) { + _outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("newFramebuffer.out")); + auto colorFormat = gpu::Element::COLOR_SRGBA_32; + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); + auto colorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); + _outputFramebuffer->setRenderBuffer(0, colorTexture); + } + + output = _outputFramebuffer; +} + void ResolveFramebuffer::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { RenderArgs* args = renderContext->args; auto srcFbo = inputs.get0(); diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index 4a0cf3dae4..0094fc1efd 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -96,6 +96,17 @@ private: gpu::FramebufferPointer _outputFramebuffer; }; +class NewOrDefaultFramebuffer { +public: + using Input = glm::uvec2; + using Output = gpu::FramebufferPointer; + using JobModel = render::Job::ModelIO; + + void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); +private: + gpu::FramebufferPointer _outputFramebuffer; +}; + class ResolveFramebuffer { public: using Inputs = render::VaryingSet2; diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index bf1a270e50..d361aa4a41 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -144,28 +144,24 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend } #if defined(Q_OS_ANDROID) - const auto resolveInputs = - ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, static_cast(nullptr)).asVarying(); // Just resolve the msaa + const auto resolveInputs = ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, static_cast(nullptr)).asVarying(); const auto resolvedFramebuffer = task.addJob("Resolve", resolveInputs); const auto toneMappedBuffer = resolvedFramebuffer; #else - const auto newResolvedFramebuffer = task.addJob("MakeResolvingFramebuffer"); + const auto newResolvedFramebuffer = task.addJob("MakeResolvingFramebuffer"); - const auto resolveInputs = ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, newResolvedFramebuffer).asVarying(); // Just resolve the msaa + const auto resolveInputs = ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, newResolvedFramebuffer).asVarying(); const auto resolvedFramebuffer = task.addJob("Resolve", resolveInputs); // Lighting Buffer ready for tone mapping // Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify // the output FBO as null, which causes the tonemapping to target the blit framebuffer - // const auto toneMappingInputs = ToneMappingDeferred::Inputs(resolvedFramebuffer, static_cast(nullptr)).asVarying(); - // const auto toneMappingInputs = ToneMappingDeferred::Input(resolvedFramebuffer, static_cast(nullptr)).asVarying(); const auto toneMappingInputs = ToneMappingDeferred::Input(resolvedFramebuffer, resolvedFramebuffer).asVarying(); - // const auto toneMappingInputs = ToneMappingDeferred::Input(resolvedFramebuffer, newResolvedFramebuffer).asVarying(); const auto toneMappedBuffer = task.addJob("ToneMapping", toneMappingInputs); #endif diff --git a/scripts/developer/utilities/render/luci/RenderSettings.qml b/scripts/developer/utilities/render/luci/RenderSettings.qml index 06f5512824..06f59dd72f 100644 --- a/scripts/developer/utilities/render/luci/RenderSettings.qml +++ b/scripts/developer/utilities/render/luci/RenderSettings.qml @@ -34,8 +34,8 @@ Column { label: "Viewport Resolution Scale" object: Render property: "viewportResolutionScale" - min: 0.1 - max: 1.1 + min: 0.5 + max: 1.0 } } From a856fdb3ca6272a07c9d89a42ac7d968d606c845 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 21 Jun 2019 10:36:25 -0700 Subject: [PATCH 10/63] getting rid of the resolution Scale on the display plugin --- interface/src/Application.cpp | 7 +------ interface/src/ui/PreferencesDialog.cpp | 4 ++-- interface/src/ui/Stats.cpp | 2 +- libraries/plugins/src/plugins/DisplayPlugin.h | 10 ---------- 4 files changed, 4 insertions(+), 19 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0bec38205e..394c49022f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3743,11 +3743,6 @@ void Application::resizeGL() { DependencyManager::get()->setFrameBufferSize(fromGlm(renderSize)); } - auto renderResolutionScale = getRenderResolutionScale(); - if (displayPlugin->getRenderResolutionScale() != renderResolutionScale) { - displayPlugin->setRenderResolutionScale(renderResolutionScale); - } - // FIXME the aspect ratio for stereo displays is incorrect based on this. float aspectRatio = displayPlugin->getRecommendedAspectRatio(); _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio, @@ -8541,7 +8536,7 @@ void Application::shareSnapshot(const QString& path, const QUrl& href) { } float Application::getRenderResolutionScale() const { - return 1.0f; + return RenderScriptingInterface::getInstance()->getViewportResolutionScale(); } void Application::notifyPacketVersionMismatch() { diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index c660a8670c..bb66a8a646 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -112,8 +112,8 @@ void setupPreferences() { RenderScriptingInterface::getInstance()->setViewportResolutionScale(value); }; - auto scaleSlider = new SpinnerSliderPreference(GRAPHICS_QUALITY, "Viewport Resolution Scale", getter, setter); - scaleSlider->setMin(0.5f); + auto scaleSlider = new SliderPreference(GRAPHICS_QUALITY, "Viewport Resolution Scale", getter, setter); + scaleSlider->setMin(0.25f); scaleSlider->setMax(1.0f); scaleSlider->setStep(0.02f); preferences->addPreference(scaleSlider); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index dc9780adf5..8b9b9743f0 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -377,7 +377,7 @@ void Stats::updateStats(bool force) { auto displayPlugin = qApp->getActiveDisplayPlugin(); if (displayPlugin) { QVector2D dims(displayPlugin->getRecommendedRenderSize().x, displayPlugin->getRecommendedRenderSize().y); - dims *= displayPlugin->getRenderResolutionScale(); + dims *= qApp->getRenderResolutionScale(); STAT_UPDATE(gpuFrameSize, dims); STAT_UPDATE(gpuFrameTimePerPixel, (float)(gpuContext->getFrameTimerGPUAverage()*1000000.0 / double(dims.x()*dims.y()))); } diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 1cad9b1e11..ca4e3bc392 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -147,14 +147,6 @@ public: virtual void submitFrame(const gpu::FramePointer& newFrame) = 0; virtual void captureFrame(const std::string& outputName) const { } - virtual float getRenderResolutionScale() const { - return _renderResolutionScale; - } - - void setRenderResolutionScale(float renderResolutionScale) { - _renderResolutionScale = renderResolutionScale; - } - // The size of the rendering target (may be larger than the device size due to distortion) virtual glm::uvec2 getRecommendedRenderSize() const = 0; @@ -235,8 +227,6 @@ protected: MovingAverage _movingAveragePresent; - float _renderResolutionScale { 1.0f }; - private: QMutex _presentMutex; QWaitCondition _presentCondition; From 250d18d7dfdad838dac7ee4b32763cdf0dfd81c5 Mon Sep 17 00:00:00 2001 From: Anna Date: Fri, 21 Jun 2019 11:11:44 -0700 Subject: [PATCH 11/63] restructured gamma correction so snapshots look correct --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 18 +- .../Basic2DWindowOpenGLDisplayPlugin.h | 1 + .../display-plugins/OpenGLDisplayPlugin.cpp | 174 ++++++++---------- .../src/display-plugins/OpenGLDisplayPlugin.h | 59 +++--- plugins/oculus/src/OculusDisplayPlugin.cpp | 1 + plugins/oculus/src/OculusDisplayPlugin.h | 4 +- 6 files changed, 129 insertions(+), 128 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 4258d4db75..38f7600315 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -109,11 +109,25 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() { return Parent::internalActivate(); } +gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getRenderTexturePipeline() { +#if defined(Q_OS_ANDROID) + return _linearToSRGBPipeline; +#else + +#ifndef USE_GLES + return _SRGBToLinearPipeline; +#else + return _drawTexturePipeline; +#endif + +#endif +} + gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getCompositeScenePipeline() { #if defined(Q_OS_ANDROID) - return _linearToSRGBPipeline; + return _linearToSRGBPipeline; #else - return _SRGBToLinearPipeline; + return _drawTexturePipeline; #endif } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 7f654915e1..ae830b2e28 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -37,6 +37,7 @@ public: virtual void pluginUpdate() override {}; + virtual gpu::PipelinePointer getRenderTexturePipeline() override; virtual gpu::PipelinePointer getCompositeScenePipeline() override; virtual gpu::Element getCompositeFBColorSpace() override; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 73bc1d0aad..c990be6e42 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -59,19 +59,14 @@ class PresentThread : public QThread, public Dependency { using Lock = std::unique_lock; public: - PresentThread() { - connect(qApp, &QCoreApplication::aboutToQuit, [this] { - shutdown(); - }); + connect(qApp, &QCoreApplication::aboutToQuit, [this] { shutdown(); }); setObjectName("Present"); _refreshRateController = std::make_shared(); } - ~PresentThread() { - shutdown(); - } + ~PresentThread() { shutdown(); } auto getRefreshRateController() { return _refreshRateController; } @@ -82,17 +77,16 @@ public: Lock lock(_mutex); _shutdown = true; - _condition.wait(lock, [&] { return !_shutdown; }); + _condition.wait(lock, [&] { return !_shutdown; }); qCDebug(displayPlugins) << "Present thread shutdown"; } } - void setNewDisplayPlugin(OpenGLDisplayPlugin* plugin) { Lock lock(_mutex); if (isRunning()) { _newPluginQueue.push(plugin); - _condition.wait(lock, [=]()->bool { return _newPluginQueue.empty(); }); + _condition.wait(lock, [=]() -> bool { return _newPluginQueue.empty(); }); } } @@ -104,7 +98,6 @@ public: _context->moveToThread(this); } - virtual void run() override { PROFILE_SET_THREAD_NAME("Present Thread"); @@ -120,8 +113,7 @@ public: CHECK_GL_ERROR(); while (!_shutdown) { if (_pendingOtherThreadOperation) { - PROFILE_RANGE(render, "MainThreadOp") - { + PROFILE_RANGE(render, "MainThreadOp") { Lock lock(_mutex); _context->doneCurrent(); // Move the context to the main thread @@ -131,7 +123,6 @@ public: _condition.notify_one(); } - { // Main thread does it's thing while we wait on the lock to release Lock lock(_mutex); @@ -201,7 +192,7 @@ public: #if defined(Q_OS_MAC) _context->doneCurrent(); #endif - + _refreshRateController->sleepThreadIfNeeded(this, currentPlugin->isHmd()); } @@ -235,23 +226,21 @@ public: _condition.notify_one(); } - private: void makeCurrent(); void doneCurrent(); - bool _shutdown { false }; + bool _shutdown{ false }; Mutex _mutex; // Used to allow the main thread to perform context operations Condition _condition; - - QThread* _targetOperationThread { nullptr }; - bool _pendingOtherThreadOperation { false }; - bool _finishedOtherThreadOperation { false }; + QThread* _targetOperationThread{ nullptr }; + bool _pendingOtherThreadOperation{ false }; + bool _finishedOtherThreadOperation{ false }; std::queue _newPluginQueue; - gl::Context* _context { nullptr }; - std::shared_ptr _refreshRateController { nullptr }; + gl::Context* _context{ nullptr }; + std::shared_ptr _refreshRateController{ nullptr }; }; bool OpenGLDisplayPlugin::activate() { @@ -302,7 +291,6 @@ bool OpenGLDisplayPlugin::activate() { return false; } - // This should not return until the new context has been customized // and the old context (if any) has been uncustomized presentThread->setNewDisplayPlugin(this); @@ -334,7 +322,7 @@ void OpenGLDisplayPlugin::deactivate() { _container->showDisplayPluginsTools(false); if (!_container->currentDisplayActions().isEmpty()) { - foreach(auto itemInfo, _container->currentDisplayActions()) { + foreach (auto itemInfo, _container->currentDisplayActions()) { _container->removeMenuItem(itemInfo.first, itemInfo.second); } _container->currentDisplayActions().clear(); @@ -368,12 +356,9 @@ void OpenGLDisplayPlugin::customizeContext() { image = image.convertToFormat(QImage::Format_ARGB32); } if ((image.width() > 0) && (image.height() > 0)) { - - cursorData.texture = gpu::Texture::createStrict( - gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), - image.width(), image.height(), - gpu::Texture::MAX_NUM_MIPS, - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); + cursorData.texture = gpu::Texture::createStrict(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.width(), + image.height(), gpu::Texture::MAX_NUM_MIPS, + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); cursorData.texture->setSource("cursor texture"); auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); cursorData.texture->setUsage(usage.build()); @@ -384,45 +369,39 @@ void OpenGLDisplayPlugin::customizeContext() { } } - if (!_drawTexturePipeline) { + if (!_linearToSRGBPipeline) { gpu::StatePointer blendState = gpu::StatePointer(new gpu::State()); blendState->setDepthTest(gpu::State::DepthTest(false)); - blendState->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, - gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, - gpu::State::ONE); + blendState->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); gpu::StatePointer scissorState = gpu::StatePointer(new gpu::State()); scissorState->setDepthTest(gpu::State::DepthTest(false)); scissorState->setScissorEnable(true); - _drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState); + _drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState); - _linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaLinearToSRGB), scissorState); + _linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaLinearToSRGB), scissorState); - _SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaSRGBToLinear), scissorState); + _SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaSRGBToLinear), scissorState); - _hudPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), blendState); + _hudPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), blendState); - _mirrorHUDPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureMirroredX), blendState); + _mirrorHUDPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureMirroredX), blendState); - _cursorPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTransformedTexture), blendState); + _cursorPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTransformedTexture), blendState); } - updateCompositeFramebuffer(); } void OpenGLDisplayPlugin::uncustomizeContext() { - _drawTexturePipeline.reset(); _linearToSRGBPipeline.reset(); _SRGBToLinearPipeline.reset(); + _cursorPipeline.reset(); _hudPipeline.reset(); _mirrorHUDPipeline.reset(); - _cursorPipeline.reset(); _compositeFramebuffer.reset(); - withPresentThreadLock([&] { _currentFrame.reset(); _lastFrame = nullptr; @@ -433,7 +412,6 @@ void OpenGLDisplayPlugin::uncustomizeContext() { }); } - // Pressing Alt (and Meta) key alone activates the menubar because its style inherits the // SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to // receive keyPress events for the Alt (and Meta) key in a reliable manner. @@ -477,9 +455,7 @@ bool OpenGLDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { } void OpenGLDisplayPlugin::submitFrame(const gpu::FramePointer& newFrame) { - withNonPresentThreadLock([&] { - _newFrameQueue.push(newFrame); - }); + withNonPresentThreadLock([&] { _newFrameQueue.push(newFrame); }); } void OpenGLDisplayPlugin::captureFrame(const std::string& filename) const { @@ -493,10 +469,10 @@ void OpenGLDisplayPlugin::captureFrame(const std::string& filename) const { image = QImage{ 1, 1, QImage::Format_ARGB32 }; auto storedImage = texture->accessStoredMipFace(0, 0); memcpy(image.bits(), storedImage->data(), image.sizeInBytes()); - //if (texture == textureCache->getWhiteTexture()) { - //} else if (texture == textureCache->getBlackTexture()) { - //} else if (texture == textureCache->getBlueTexture()) { - //} else if (texture == textureCache->getGrayTexture()) { + //if (texture == textureCache->getWhiteTexture()) { + //} else if (texture == textureCache->getBlackTexture()) { + //} else if (texture == textureCache->getBlueTexture()) { + //} else if (texture == textureCache->getGrayTexture()) { } else { ivec4 rect = { 0, 0, texture->getWidth(), texture->getHeight() }; framebuffer->setRenderBuffer(0, texture, layer); @@ -514,11 +490,18 @@ void OpenGLDisplayPlugin::captureFrame(const std::string& filename) const { }); } -void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor) { +void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, + const gpu::TexturePointer& texture, + const glm::ivec4& viewport, + const glm::ivec4& scissor) { renderFromTexture(batch, texture, viewport, scissor, nullptr); } -void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& copyFbo /*=gpu::FramebufferPointer()*/) { +void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, + const gpu::TexturePointer& texture, + const glm::ivec4& viewport, + const glm::ivec4& scissor, + const gpu::FramebufferPointer& copyFbo /*=gpu::FramebufferPointer()*/) { auto fbo = gpu::FramebufferPointer(); batch.enableStereo(false); batch.resetViewTransform(); @@ -528,18 +511,18 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur batch.setViewportTransform(viewport); batch.setResourceTexture(0, texture); - batch.setPipeline(_drawTexturePipeline); - + batch.setPipeline(getRenderTexturePipeline()); + batch.draw(gpu::TRIANGLE_STRIP, 4); if (copyFbo) { gpu::Vec4i copyFboRect(0, 0, copyFbo->getWidth(), copyFbo->getHeight()); gpu::Vec4i sourceRect(scissor.x, scissor.y, scissor.x + scissor.z, scissor.y + scissor.w); - float aspectRatio = (float)scissor.w / (float) scissor.z; // height/width + float aspectRatio = (float)scissor.w / (float)scissor.z; // height/width // scale width first int xOffset = 0; int yOffset = 0; int newWidth = copyFbo->getWidth(); - int newHeight = std::round(aspectRatio * (float) copyFbo->getWidth()); + int newHeight = std::round(aspectRatio * (float)copyFbo->getWidth()); if (newHeight > copyFbo->getHeight()) { // ok, so now fill height instead newHeight = copyFbo->getHeight(); @@ -554,7 +537,7 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur batch.resetViewTransform(); batch.setViewportTransform(copyFboRect); batch.setStateScissorRect(copyFboRect); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, {0.0f, 0.0f, 0.0f, 1.0f}); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0.0f, 0.0f, 0.0f, 1.0f }); batch.blit(fbo, sourceRect, copyFbo, copyRect); } } @@ -589,14 +572,11 @@ std::function OpenGL auto hudStereo = isStereo(); auto hudCompositeFramebufferSize = _compositeFramebuffer->getSize(); std::array hudEyeViewports; - for_each_eye([&](Eye eye) { - hudEyeViewports[eye] = eyeViewport(eye); - }); + for_each_eye([&](Eye eye) { hudEyeViewports[eye] = eyeViewport(eye); }); return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { - auto pipeline = mirror ? hudMirrorPipeline : hudPipeline; - if (pipeline && hudTexture) { + if (hudPipeline && hudTexture) { batch.enableStereo(false); - batch.setPipeline(pipeline); + batch.setPipeline(mirror ? hudMirrorPipeline : hudPipeline); batch.setResourceTexture(0, hudTexture); if (hudStereo) { for_each_eye([&](Eye eye) { @@ -635,11 +615,6 @@ void OpenGLDisplayPlugin::compositePointer() { }); } -// Overridden by Basic2DWindowDisplayPlugin and OculusDisplayPlugin -gpu::PipelinePointer OpenGLDisplayPlugin::getCompositeScenePipeline() { - return _drawTexturePipeline; -} - void OpenGLDisplayPlugin::compositeScene() { render([&](gpu::Batch& batch) { batch.enableStereo(false); @@ -682,9 +657,10 @@ void OpenGLDisplayPlugin::internalPresent() { render([&](gpu::Batch& batch) { // Note: _displayTexture must currently be the same size as the display. uvec2 dims = _displayTexture ? uvec2(_displayTexture->getDimensions()) : getSurfacePixels(); - auto viewport = ivec4(uvec2(0), dims); - renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, viewport); - }); + auto viewport = ivec4(uvec2(0), dims); + renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, + viewport); + }); swapBuffers(); _presentRate.increment(); } @@ -723,7 +699,7 @@ void OpenGLDisplayPlugin::present(const std::shared_ptr& compositeLayers(); } - { // If we have any snapshots this frame, handle them + { // If we have any snapshots this frame, handle them PROFILE_RANGE_EX(render, "snapshotOperators", 0xffff00ff, frameId) while (!_currentFrame->snapshotOperators.empty()) { auto& snapshotOperator = _currentFrame->snapshotOperators.front(); @@ -765,7 +741,7 @@ float OpenGLDisplayPlugin::presentRate() const { return _presentRate.rate(); } -std::function OpenGLDisplayPlugin::getRefreshRateOperator() { +std::function OpenGLDisplayPlugin::getRefreshRateOperator() { return [](int targetRefreshRate) { auto refreshRateController = DependencyManager::get()->getRefreshRateController(); refreshRateController->setRefreshRateLimitPeriod(targetRefreshRate); @@ -781,7 +757,6 @@ float OpenGLDisplayPlugin::renderRate() const { return _renderRate.rate(); } - void OpenGLDisplayPlugin::swapBuffers() { static auto context = _container->getPrimaryWidget()->context(); context->swapBuffers(); @@ -818,7 +793,7 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) { } auto bestSize = size; uvec2 corner(0); - if (aspectRatio != 0.0f) { // Pick out the largest piece of the center that produces the requested width/height aspectRatio + if (aspectRatio != 0.0f) { // Pick out the largest piece of the center that produces the requested width/height aspectRatio if (ceil(size.y * aspectRatio) < size.x) { bestSize.x = round(size.y * aspectRatio); } else { @@ -869,9 +844,7 @@ void OpenGLDisplayPlugin::assertIsPresentThread() const { } bool OpenGLDisplayPlugin::beginFrameRender(uint32_t frameIndex) { - withNonPresentThreadLock([&] { - _compositeHUDAlpha = _hudAlpha; - }); + withNonPresentThreadLock([&] { _compositeHUDAlpha = _hudAlpha; }); return Parent::beginFrameRender(frameIndex); } @@ -909,27 +882,25 @@ void OpenGLDisplayPlugin::render(std::function f) { OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { } -// Added this to allow desktop composite framebuffer to be RGBA while mobile is SRGBA -// Overridden by Basic2DWindowDisplayPlugin -// FIXME: Eventually it would be ideal to have both framebuffers be of the same type -gpu::Element OpenGLDisplayPlugin::getCompositeFBColorSpace() { - return gpu::Element::COLOR_RGBA_32; -} - void OpenGLDisplayPlugin::updateCompositeFramebuffer() { auto renderSize = glm::uvec2(getRecommendedRenderSize()); if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { - _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", getCompositeFBColorSpace(), renderSize.x, renderSize.y)); + _compositeFramebuffer = + gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, + renderSize.x, renderSize.y)); + // _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_SRGBA_32, renderSize.x, renderSize.y)); } } -void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, QOpenGLFramebufferObject* target, GLsync* fenceSync) { +void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, + QOpenGLFramebufferObject* target, + GLsync* fenceSync) { #if !defined(USE_GLES) auto glBackend = const_cast(*this).getGLBackend(); withOtherThreadContext([&] { GLuint sourceTexture = glBackend->getTextureID(networkTexture->getGPUTexture()); GLuint targetTexture = target->texture(); - GLuint fbo[2] {0, 0}; + GLuint fbo[2]{ 0, 0 }; // need mipmaps for blitting texture glGenerateTextureMipmap(sourceTexture); @@ -950,14 +921,13 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); - // maintain aspect ratio, filling the width first if possible. If that makes the height too // much, fill height instead. TODO: only do this when texture changes GLint newX = 0; GLint newY = 0; float aspectRatio = (float)texHeight / (float)texWidth; GLint newWidth = target->width(); - GLint newHeight = std::round(aspectRatio * (float) target->width()); + GLint newHeight = std::round(aspectRatio * (float)target->width()); if (newHeight > target->height()) { newHeight = target->height(); newWidth = std::round((float)target->height() / aspectRatio); @@ -966,7 +936,8 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne newY = (target->height() - newHeight) / 2; } - glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newX + newWidth, newY + newHeight, GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newX + newWidth, newY + newHeight, + GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, GL_NEAREST); // don't delete the textures! glDeleteFramebuffers(2, fbo); @@ -975,3 +946,14 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne #endif } +gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() { + return _drawTexturePipeline; +} + +gpu::PipelinePointer OpenGLDisplayPlugin::getCompositeScenePipeline() { + return _drawTexturePipeline; +} + +gpu::Element OpenGLDisplayPlugin::getCompositeFBColorSpace() { + return gpu::Element::COLOR_RGBA_32; +} diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index eae9f86710..d5d9bad8a6 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -23,11 +23,9 @@ #include -namespace gpu { - namespace gl { - class GLBackend; - } -} +namespace gpu { namespace gl { +class GLBackend; +}} // namespace gpu::gl class RefreshRateController; @@ -35,10 +33,12 @@ class OpenGLDisplayPlugin : public DisplayPlugin { Q_OBJECT Q_PROPERTY(float hudAlpha MEMBER _hudAlpha) using Parent = DisplayPlugin; + protected: using Mutex = std::mutex; using Lock = std::unique_lock; using Condition = std::condition_variable; + public: ~OpenGLDisplayPlugin(); // These must be final to ensure proper ordering of operations @@ -55,13 +55,9 @@ public: void captureFrame(const std::string& outputName) const override; void submitFrame(const gpu::FramePointer& newFrame) override; - glm::uvec2 getRecommendedRenderSize() const override { - return getSurfacePixels(); - } + glm::uvec2 getRecommendedRenderSize() const override { return getSurfacePixels(); } - glm::uvec2 getRecommendedUiSize() const override { - return getSurfaceSize(); - } + glm::uvec2 getRecommendedUiSize() const override { return getSurfaceSize(); } virtual bool setDisplayTexture(const QString& name) override; virtual bool onDisplayTextureReset() { return false; }; @@ -84,9 +80,9 @@ public: // Three threads, one for rendering, one for texture transfers, one reserved for the GL driver int getRequiredThreadCount() const override { return 3; } - void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override; - - virtual std::function getHUDOperator() override; + void copyTextureToQuickFramebuffer(NetworkTexturePointer source, + QOpenGLFramebufferObject* target, + GLsync* fenceSync) override; protected: friend class PresentThread; @@ -104,11 +100,9 @@ protected: virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; } virtual void compositeLayers(); virtual void compositeScene(); + virtual std::function getHUDOperator(); virtual void compositePointer(); - virtual void compositeExtra() {}; - - virtual gpu::PipelinePointer getCompositeScenePipeline(); - virtual gpu::Element getCompositeFBColorSpace(); + virtual void compositeExtra(){}; // These functions must only be called on the presentation thread virtual void customizeContext(); @@ -125,8 +119,15 @@ protected: // Plugin specific functionality to send the composed scene to the output window or device virtual void internalPresent(); - void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& fbo); - void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor); + void renderFromTexture(gpu::Batch& batch, + const gpu::TexturePointer& texture, + const glm::ivec4& viewport, + const glm::ivec4& scissor, + const gpu::FramebufferPointer& fbo); + void renderFromTexture(gpu::Batch& batch, + const gpu::TexturePointer& texture, + const glm::ivec4& viewport, + const glm::ivec4& scissor); virtual void updateFrameData(); virtual glm::mat4 getViewCorrection() { return glm::mat4(); } @@ -138,7 +139,7 @@ protected: void render(std::function f); - bool _vsyncEnabled { true }; + bool _vsyncEnabled{ true }; QThread* _presentThread{ nullptr }; std::queue _newFrameQueue; RateCounter<200> _droppedFrameRate; @@ -147,7 +148,7 @@ protected: RateCounter<200> _renderRate; gpu::FramePointer _currentFrame; - gpu::Frame* _lastFrame { nullptr }; + gpu::Frame* _lastFrame{ nullptr }; mat4 _prevRenderView; gpu::FramebufferPointer _compositeFramebuffer; gpu::PipelinePointer _hudPipeline; @@ -157,9 +158,12 @@ protected: gpu::PipelinePointer _linearToSRGBPipeline; gpu::PipelinePointer _SRGBToLinearPipeline; gpu::PipelinePointer _cursorPipeline; - gpu::TexturePointer _displayTexture{}; - float _compositeHUDAlpha { 1.0f }; + float _compositeHUDAlpha{ 1.0f }; + + virtual gpu::PipelinePointer getRenderTexturePipeline(); + virtual gpu::PipelinePointer getCompositeScenePipeline(); + virtual gpu::Element getCompositeFBColorSpace(); struct CursorData { QImage image; @@ -169,19 +173,19 @@ protected: }; std::map _cursorsData; - bool _lockCurrentTexture { false }; + bool _lockCurrentTexture{ false }; void assertNotPresentThread() const; void assertIsPresentThread() const; - template + template void withPresentThreadLock(F f) const { assertIsPresentThread(); Lock lock(_presentMutex); f(); } - template + template void withNonPresentThreadLock(F f) const { assertNotPresentThread(); Lock lock(_presentMutex); @@ -198,4 +202,3 @@ protected: QImage getScreenshot(float aspectRatio); QImage getSecondaryCameraScreenshot(); }; - diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index c493588992..43eabf3544 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -167,6 +167,7 @@ void OculusDisplayPlugin::hmdPresent() { batch.setStateScissorRect(ivec4(uvec2(), _outputFramebuffer->getSize())); batch.resetViewTransform(); batch.setProjectionTransform(mat4()); + //batch.setPipeline(_drawTexturePipeline); batch.setPipeline(_drawTexturePipeline); batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0)); batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 8eda599fa9..b220ee0214 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -24,6 +24,8 @@ public: virtual QJsonObject getHardwareStats() const; + virtual gpu::PipelinePointer getCompositeScenePipeline() override; + protected: QThread::Priority getPresentPriority() override { return QThread::TimeCriticalPriority; } @@ -34,8 +36,6 @@ protected: void uncustomizeContext() override; void cycleDebugOutput() override; - virtual gpu::PipelinePointer getCompositeScenePipeline() override; - private: static const char* NAME; ovrTextureSwapChain _textureSwapChain; From 3d36c5714fd9fb9a03e6422a9158860f08314095 Mon Sep 17 00:00:00 2001 From: Anna Date: Fri, 21 Jun 2019 11:34:10 -0700 Subject: [PATCH 12/63] added comments and cleaned up --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 8 ++++++-- plugins/oculus/src/OculusDisplayPlugin.cpp | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index c990be6e42..cdbbc15877 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -574,9 +574,10 @@ std::function OpenGL std::array hudEyeViewports; for_each_eye([&](Eye eye) { hudEyeViewports[eye] = eyeViewport(eye); }); return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { - if (hudPipeline && hudTexture) { + auto pipeline = mirror ? hudMirrorPipeline : hudPipeline; + if (pipeline && hudTexture) { batch.enableStereo(false); - batch.setPipeline(mirror ? hudMirrorPipeline : hudPipeline); + batch.setPipeline(pipeline); batch.setResourceTexture(0, hudTexture); if (hudStereo) { for_each_eye([&](Eye eye) { @@ -954,6 +955,9 @@ gpu::PipelinePointer OpenGLDisplayPlugin::getCompositeScenePipeline() { return _drawTexturePipeline; } +// Added this to allow desktop composite framebuffer to be RGBA while mobile is SRGBA, so that tone mapping looks right on both platforms +// Overridden by Basic2DWindowDisplayPlugin to achieve this +// FIXME: Eventually it would be ideal to have both framebuffers be of the same type gpu::Element OpenGLDisplayPlugin::getCompositeFBColorSpace() { return gpu::Element::COLOR_RGBA_32; } diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index 43eabf3544..c493588992 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -167,7 +167,6 @@ void OculusDisplayPlugin::hmdPresent() { batch.setStateScissorRect(ivec4(uvec2(), _outputFramebuffer->getSize())); batch.resetViewTransform(); batch.setProjectionTransform(mat4()); - //batch.setPipeline(_drawTexturePipeline); batch.setPipeline(_drawTexturePipeline); batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0)); batch.draw(gpu::TRIANGLE_STRIP, 4); From 70fbe840a5f95f12209283f04b6184124c4969ad Mon Sep 17 00:00:00 2001 From: Anna Date: Fri, 21 Jun 2019 12:00:20 -0700 Subject: [PATCH 13/63] added getCompositeFBColorSpace back into updateCompositeFramebuffer --- .../display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index cdbbc15877..b4fb936c5d 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -887,7 +887,7 @@ void OpenGLDisplayPlugin::updateCompositeFramebuffer() { auto renderSize = glm::uvec2(getRecommendedRenderSize()); if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { _compositeFramebuffer = - gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, + gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", getCompositeFBColorSpace(), renderSize.x, renderSize.y)); // _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_SRGBA_32, renderSize.x, renderSize.y)); } From 17163a1ce87a3a6577d1e560b7642a8c4e9137d2 Mon Sep 17 00:00:00 2001 From: Anna Date: Fri, 21 Jun 2019 13:41:41 -0700 Subject: [PATCH 14/63] undid some VS auto format changes --- .../display-plugins/OpenGLDisplayPlugin.cpp | 91 +++++++++++-------- 1 file changed, 52 insertions(+), 39 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index b4fb936c5d..7d12825b7e 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -59,14 +59,19 @@ class PresentThread : public QThread, public Dependency { using Lock = std::unique_lock; public: + PresentThread() { - connect(qApp, &QCoreApplication::aboutToQuit, [this] { shutdown(); }); + connect(qApp, &QCoreApplication::aboutToQuit, [this] { + shutdown(); + }); setObjectName("Present"); _refreshRateController = std::make_shared(); } - ~PresentThread() { shutdown(); } + ~PresentThread() { + shutdown(); + } auto getRefreshRateController() { return _refreshRateController; } @@ -86,7 +91,7 @@ public: Lock lock(_mutex); if (isRunning()) { _newPluginQueue.push(plugin); - _condition.wait(lock, [=]() -> bool { return _newPluginQueue.empty(); }); + _condition.wait(lock, [=]()->bool { return _newPluginQueue.empty(); }); } } @@ -113,7 +118,8 @@ public: CHECK_GL_ERROR(); while (!_shutdown) { if (_pendingOtherThreadOperation) { - PROFILE_RANGE(render, "MainThreadOp") { + PROFILE_RANGE(render, "MainThreadOp") + { Lock lock(_mutex); _context->doneCurrent(); // Move the context to the main thread @@ -230,17 +236,17 @@ private: void makeCurrent(); void doneCurrent(); - bool _shutdown{ false }; + bool _shutdown { false }; Mutex _mutex; // Used to allow the main thread to perform context operations Condition _condition; - QThread* _targetOperationThread{ nullptr }; - bool _pendingOtherThreadOperation{ false }; - bool _finishedOtherThreadOperation{ false }; + QThread* _targetOperationThread { nullptr }; + bool _pendingOtherThreadOperation { false }; + bool _finishedOtherThreadOperation { false }; std::queue _newPluginQueue; - gl::Context* _context{ nullptr }; - std::shared_ptr _refreshRateController{ nullptr }; + gl::Context* _context { nullptr }; + std::shared_ptr _refreshRateController { nullptr }; }; bool OpenGLDisplayPlugin::activate() { @@ -356,9 +362,11 @@ void OpenGLDisplayPlugin::customizeContext() { image = image.convertToFormat(QImage::Format_ARGB32); } if ((image.width() > 0) && (image.height() > 0)) { - cursorData.texture = gpu::Texture::createStrict(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.width(), - image.height(), gpu::Texture::MAX_NUM_MIPS, - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); + cursorData.texture = gpu::Texture::createStrict( + gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), + image.width(), image.height(), + gpu::Texture::MAX_NUM_MIPS, + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); cursorData.texture->setSource("cursor texture"); auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); cursorData.texture->setUsage(usage.build()); @@ -372,8 +380,11 @@ void OpenGLDisplayPlugin::customizeContext() { if (!_linearToSRGBPipeline) { gpu::StatePointer blendState = gpu::StatePointer(new gpu::State()); blendState->setDepthTest(gpu::State::DepthTest(false)); - blendState->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + blendState->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, + gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, + gpu::State::ONE); gpu::StatePointer scissorState = gpu::StatePointer(new gpu::State()); scissorState->setDepthTest(gpu::State::DepthTest(false)); @@ -391,10 +402,12 @@ void OpenGLDisplayPlugin::customizeContext() { _cursorPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTransformedTexture), blendState); } + updateCompositeFramebuffer(); } void OpenGLDisplayPlugin::uncustomizeContext() { + _drawTexturePipeline.reset(); _linearToSRGBPipeline.reset(); _SRGBToLinearPipeline.reset(); @@ -402,6 +415,7 @@ void OpenGLDisplayPlugin::uncustomizeContext() { _hudPipeline.reset(); _mirrorHUDPipeline.reset(); _compositeFramebuffer.reset(); + withPresentThreadLock([&] { _currentFrame.reset(); _lastFrame = nullptr; @@ -455,7 +469,9 @@ bool OpenGLDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { } void OpenGLDisplayPlugin::submitFrame(const gpu::FramePointer& newFrame) { - withNonPresentThreadLock([&] { _newFrameQueue.push(newFrame); }); + withNonPresentThreadLock([&] { + _newFrameQueue.push(newFrame); + }); } void OpenGLDisplayPlugin::captureFrame(const std::string& filename) const { @@ -469,10 +485,10 @@ void OpenGLDisplayPlugin::captureFrame(const std::string& filename) const { image = QImage{ 1, 1, QImage::Format_ARGB32 }; auto storedImage = texture->accessStoredMipFace(0, 0); memcpy(image.bits(), storedImage->data(), image.sizeInBytes()); - //if (texture == textureCache->getWhiteTexture()) { - //} else if (texture == textureCache->getBlackTexture()) { - //} else if (texture == textureCache->getBlueTexture()) { - //} else if (texture == textureCache->getGrayTexture()) { + //if (texture == textureCache->getWhiteTexture()) { + //} else if (texture == textureCache->getBlackTexture()) { + //} else if (texture == textureCache->getBlueTexture()) { + //} else if (texture == textureCache->getGrayTexture()) { } else { ivec4 rect = { 0, 0, texture->getWidth(), texture->getHeight() }; framebuffer->setRenderBuffer(0, texture, layer); @@ -522,7 +538,7 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, int xOffset = 0; int yOffset = 0; int newWidth = copyFbo->getWidth(); - int newHeight = std::round(aspectRatio * (float)copyFbo->getWidth()); + int newHeight = std::round(aspectRatio * (float) copyFbo->getWidth()); if (newHeight > copyFbo->getHeight()) { // ok, so now fill height instead newHeight = copyFbo->getHeight(); @@ -537,7 +553,7 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, batch.resetViewTransform(); batch.setViewportTransform(copyFboRect); batch.setStateScissorRect(copyFboRect); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0.0f, 0.0f, 0.0f, 1.0f }); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, {0.0f, 0.0f, 0.0f, 1.0f}); batch.blit(fbo, sourceRect, copyFbo, copyRect); } } @@ -572,7 +588,9 @@ std::function OpenGL auto hudStereo = isStereo(); auto hudCompositeFramebufferSize = _compositeFramebuffer->getSize(); std::array hudEyeViewports; - for_each_eye([&](Eye eye) { hudEyeViewports[eye] = eyeViewport(eye); }); + for_each_eye([&](Eye eye) { + hudEyeViewports[eye] = eyeViewport(eye); + }); return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { auto pipeline = mirror ? hudMirrorPipeline : hudPipeline; if (pipeline && hudTexture) { @@ -659,9 +677,8 @@ void OpenGLDisplayPlugin::internalPresent() { // Note: _displayTexture must currently be the same size as the display. uvec2 dims = _displayTexture ? uvec2(_displayTexture->getDimensions()) : getSurfacePixels(); auto viewport = ivec4(uvec2(0), dims); - renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, - viewport); - }); + renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, viewport); + }); swapBuffers(); _presentRate.increment(); } @@ -700,7 +717,7 @@ void OpenGLDisplayPlugin::present(const std::shared_ptr& compositeLayers(); } - { // If we have any snapshots this frame, handle them + { // If we have any snapshots this frame, handle them PROFILE_RANGE_EX(render, "snapshotOperators", 0xffff00ff, frameId) while (!_currentFrame->snapshotOperators.empty()) { auto& snapshotOperator = _currentFrame->snapshotOperators.front(); @@ -794,7 +811,7 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) { } auto bestSize = size; uvec2 corner(0); - if (aspectRatio != 0.0f) { // Pick out the largest piece of the center that produces the requested width/height aspectRatio + if (aspectRatio != 0.0f) { // Pick out the largest piece of the center that produces the requested width/height aspectRatio if (ceil(size.y * aspectRatio) < size.x) { bestSize.x = round(size.y * aspectRatio); } else { @@ -845,7 +862,9 @@ void OpenGLDisplayPlugin::assertIsPresentThread() const { } bool OpenGLDisplayPlugin::beginFrameRender(uint32_t frameIndex) { - withNonPresentThreadLock([&] { _compositeHUDAlpha = _hudAlpha; }); + withNonPresentThreadLock([&] { + _compositeHUDAlpha = _hudAlpha; + }); return Parent::beginFrameRender(frameIndex); } @@ -886,22 +905,17 @@ OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { void OpenGLDisplayPlugin::updateCompositeFramebuffer() { auto renderSize = glm::uvec2(getRecommendedRenderSize()); if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { - _compositeFramebuffer = - gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", getCompositeFBColorSpace(), - renderSize.x, renderSize.y)); - // _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_SRGBA_32, renderSize.x, renderSize.y)); + _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", getCompositeFBColorSpace(), renderSize.x, renderSize.y)); } } -void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, - QOpenGLFramebufferObject* target, - GLsync* fenceSync) { +void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, QOpenGLFramebufferObject* target, GLsync* fenceSync) { #if !defined(USE_GLES) auto glBackend = const_cast(*this).getGLBackend(); withOtherThreadContext([&] { GLuint sourceTexture = glBackend->getTextureID(networkTexture->getGPUTexture()); GLuint targetTexture = target->texture(); - GLuint fbo[2]{ 0, 0 }; + GLuint fbo[2] {0, 0}; // need mipmaps for blitting texture glGenerateTextureMipmap(sourceTexture); @@ -937,8 +951,7 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne newY = (target->height() - newHeight) / 2; } - glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newX + newWidth, newY + newHeight, - GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newX + newWidth, newY + newHeight, GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, GL_NEAREST); // don't delete the textures! glDeleteFramebuffers(2, fbo); From aa160c4d0f423975c50ac284d62b0fc8cade8018 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 21 Jun 2019 16:17:28 -0700 Subject: [PATCH 15/63] Improving presentation of stats & debug information --- interface/resources/qml/Stats.qml | 4 +- .../utilities/lib/prop/PropGroup.qml | 48 +++++++++++-------- .../utilities/lib/prop/PropScalar.qml | 21 ++++---- .../utilities/render/luci/Platform.qml | 25 ++-------- .../utilities/render/luci/RenderSettings.qml | 4 +- 5 files changed, 51 insertions(+), 51 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 2c991aa9dd..23aa256cdc 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -340,10 +340,10 @@ Item { text: "GPU: " + root.gpuFrameTime.toFixed(1) + " ms" } StatText { - text: "GPU (Per pixel): " + root.gpuFrameTimePerPixel.toFixed(5) + " ns/pp" + text: "GPU (Per pixel): " + root.gpuFrameTimePerPixel.toFixed(1) + " ns/pp" } StatText { - text: "GPU frame size: " + root.gpuFrameSize.x + " x " + root.gpuFrameSize.y + text: "GPU frame size: " + root.gpuFrameSize.x.toFixed(0) + " x " + root.gpuFrameSize.y.toFixed(0) } StatText { text: "LOD Target: " + root.lodTargetFramerate + " Hz Angle: " + root.lodAngle + " deg" diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 75437460ce..eab1b9c842 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -17,6 +17,8 @@ PropFolderPanel { Global { id: global } id: root + property var rootObject: {} + property alias propItemsPanel: root.panelFrameContent // Prop Group is designed to author an array of ProItems, they are defined with an array of the tuplets describing each individual item: @@ -79,20 +81,23 @@ PropFolderPanel { }) } break; case 'object': { - /* var component = Qt.createComponent("PropItem.qml"); - component.createObject(propItemsContainer, { - "label": proItem.property, - "object": proItem.object, - "property": proItem.property, - })*/ + console.log('Item is an object, create PropGroup: ' + JSON.stringify(proItem.object[proItem.property])); + var itemRootObject = proItem.object[proItem.property]; + var itemLabel = proItem.property; + var itemDepth = root.indentDepth + 1; + if (Array.isArray(itemRootObject)) { + if (objectItem.length > 1) { + itemLabel = itemLabel + " " + objectItem.length + } else { + itemLabel = itemLabel + " " + objectItem.length + itemRootObject = itemRootObject[0]; + } + } var component = Qt.createComponent("PropGroup.qml"); component.createObject(propItemsContainer, { - "label": proItem.property, - "object": proItem.object, - // "jobPath": root.jobPath + '.' + job.objectName, - // "showProps": root.showProps, - // "showSubs": root.showSubs, - // "indentDepth": root.indentDepth + 1, + "label": itemLabel, + "rootObject":itemRootObject, + "indentDepth": itemDepth, }) } break; case 'printLabel': { @@ -119,19 +124,20 @@ PropFolderPanel { function populateFromObjectProps(object) { var propsModel = [] - var props = Object.keys(object); + if (Array.isArray(object)) { + if (object.length <= 1) { + object = object[0]; + } + } + + var props = Object.keys(object); for (var p in props) { var o = {}; o["object"] = object o["property"] = props[p]; // o["readOnly"] = true; - /* - o["type"] = "string"; - - propsModel.push(o)*/ - var thePropThing = object[props[p]]; if ((thePropThing !== undefined) && (thePropThing !== null)) { var theType = typeof(thePropThing) @@ -139,7 +145,7 @@ PropFolderPanel { case 'object': { o["type"] = "object"; propsModel.push(o) - } + } break; default: { o["type"] = "string"; propsModel.push(o) @@ -151,9 +157,13 @@ PropFolderPanel { propsModel.push(o) } } + root.updatePropItems(root.propItemsPanel, propsModel); } Component.onCompleted: { + if (root.rootObject !== null) { + populateFromObjectProps(root.rootObject) + } } } diff --git a/scripts/developer/utilities/lib/prop/PropScalar.qml b/scripts/developer/utilities/lib/prop/PropScalar.qml index 33e1bfc958..ae86c6ef81 100644 --- a/scripts/developer/utilities/lib/prop/PropScalar.qml +++ b/scripts/developer/utilities/lib/prop/PropScalar.qml @@ -20,17 +20,22 @@ PropItem { property bool integral: false property var numDigits: 2 - property alias valueVar : sliderControl.value + property alias min: sliderControl.minimumValue property alias max: sliderControl.maximumValue property bool showValue: true - signal valueChanged(real value) - Component.onCompleted: { - valueVar = root.valueVarGetter(); - } + } + + property var sourceValueVar: root.valueVarGetter() + + function applyValueVarFromWidgets(value) { + if (!root.readOnly) { + root.valueVarSetter(value) + } + } PropLabel { id: valueLabel @@ -42,7 +47,7 @@ PropItem { horizontalAlignment: global.valueTextAlign height: global.slimHeight - text: root.valueVarGetter().toFixed(root.integral ? 0 : root.numDigits) + text: root.sourceValueVar.toFixed(root.integral ? 0 : root.numDigits) background: Rectangle { color: global.color @@ -59,8 +64,8 @@ PropItem { anchors.left: valueLabel.right anchors.right: root.right anchors.verticalCenter: root.verticalCenter - - onValueChanged: { if (!root.readOnly) { root.valueVarSetter(value)} } + value: root.sourceValueVar + onValueChanged: { applyValueVarFromWidgets(value) } } diff --git a/scripts/developer/utilities/render/luci/Platform.qml b/scripts/developer/utilities/render/luci/Platform.qml index 9c5ffda070..eaa4766b32 100644 --- a/scripts/developer/utilities/render/luci/Platform.qml +++ b/scripts/developer/utilities/render/luci/Platform.qml @@ -23,46 +23,31 @@ Column { id: computer label: "Computer" isUnfold: true - - Component.onCompleted: { - computer.populateFromObjectProps(JSON.parse(PlatformInfo.getComputer())) - } + rootObject:JSON.parse(PlatformInfo.getComputer()) } Prop.PropGroup { id: cpu label: "CPU" isUnfold: true - - Component.onCompleted: { - cpu.populateFromObjectProps(JSON.parse(PlatformInfo.getCPU(0))) - } + rootObject:JSON.parse(PlatformInfo.getPlatform()).cpus } Prop.PropGroup { id: memory label: "Memory" isUnfold: true - - Component.onCompleted: { - memory.populateFromObjectProps(JSON.parse(PlatformInfo.getMemory())) - } + rootObject:JSON.parse(PlatformInfo.getMemory()) } Prop.PropGroup { id: gpu label: "GPU" isUnfold: true - - Component.onCompleted: { - gpu.populateFromObjectProps(JSON.parse(PlatformInfo.getGPU(0))) - } + rootObject:JSON.parse(PlatformInfo.getPlatform()).gpus } Prop.PropGroup { id: display label: "Display" isUnfold: true - - Component.onCompleted: { - display.populateFromObjectProps(JSON.parse(PlatformInfo.getDisplay(0))) - } + rootObject:JSON.parse(PlatformInfo.getPlatform()).displays } } diff --git a/scripts/developer/utilities/render/luci/RenderSettings.qml b/scripts/developer/utilities/render/luci/RenderSettings.qml index 06f59dd72f..bd76964070 100644 --- a/scripts/developer/utilities/render/luci/RenderSettings.qml +++ b/scripts/developer/utilities/render/luci/RenderSettings.qml @@ -34,8 +34,8 @@ Column { label: "Viewport Resolution Scale" object: Render property: "viewportResolutionScale" - min: 0.5 - max: 1.0 + min: 0.25 + max: 1.5 } } From 7bf2c5fc8e01caafd53b4c81e7290ad722502dd5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 21 Jun 2019 16:22:01 -0700 Subject: [PATCH 16/63] Simplify the setting name --- interface/src/ui/PreferencesDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index bb66a8a646..ce70e91128 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -112,7 +112,7 @@ void setupPreferences() { RenderScriptingInterface::getInstance()->setViewportResolutionScale(value); }; - auto scaleSlider = new SliderPreference(GRAPHICS_QUALITY, "Viewport Resolution Scale", getter, setter); + auto scaleSlider = new SliderPreference(GRAPHICS_QUALITY, "Resolution Scale", getter, setter); scaleSlider->setMin(0.25f); scaleSlider->setMax(1.0f); scaleSlider->setStep(0.02f); From a278e6c52c9788e0c1c9f1c31135d9b14ea04042 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 21 Jun 2019 17:24:21 -0700 Subject: [PATCH 17/63] REmoving unecessary job introduced dureing development --- .../src/DeferredLightingEffect.cpp | 38 ------------------- .../render-utils/src/DeferredLightingEffect.h | 35 ----------------- .../render-utils/src/RenderCommonTask.cpp | 22 ----------- libraries/render-utils/src/RenderCommonTask.h | 12 ------ .../render-utils/src/RenderDeferredTask.cpp | 38 +++++++++++++++++++ .../render-utils/src/RenderDeferredTask.h | 36 ++++++++++++++++++ 6 files changed, 74 insertions(+), 107 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 257c01040f..3ab9340906 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -273,44 +273,6 @@ graphics::MeshPointer DeferredLightingEffect::getSpotLightMesh() { return _spotLightMesh; } -gpu::FramebufferPointer PreparePrimaryFramebuffer::createFramebuffer(const char* name, const glm::uvec2& frameSize) { - gpu::FramebufferPointer framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(name)); - auto colorFormat = gpu::Element::COLOR_SRGBA_32; - - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); - auto primaryColorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); - - framebuffer->setRenderBuffer(0, primaryColorTexture); - - auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format - auto primaryDepthTexture = gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); - - framebuffer->setDepthStencilBuffer(primaryDepthTexture, depthFormat); - - return framebuffer; -} - -void PreparePrimaryFramebuffer::configure(const Config& config) { - _resolutionScale = config.getResolutionScale(); -} - -void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, Output& primaryFramebuffer) { - glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); - glm::uvec2 scaledFrameSize(glm::vec2(frameSize) * _resolutionScale); - - // Resizing framebuffers instead of re-building them seems to cause issues with threaded - // rendering - if (!_primaryFramebuffer || _primaryFramebuffer->getSize() != scaledFrameSize) { - _primaryFramebuffer = createFramebuffer("deferredPrimary", scaledFrameSize); - } - - primaryFramebuffer = _primaryFramebuffer; - - // Set viewport for the rest of the scaled passes - renderContext->args->_viewport.z = scaledFrameSize.x; - renderContext->args->_viewport.w = scaledFrameSize.y; -} - void PrepareDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { auto args = renderContext->args; diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 4308cd822c..4779376410 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -74,41 +74,6 @@ private: friend class RenderDeferredCleanup; }; -class PreparePrimaryFramebufferConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale) -public: - float getResolutionScale() const { return resolutionScale; } - void setResolutionScale(float scale) { - resolutionScale = std::max(0.1f, std::min(2.0f, scale)); - } - -signals: - void dirty(); - -protected: - float resolutionScale{ 1.0f }; -}; - -class PreparePrimaryFramebuffer { -public: - - using Output = gpu::FramebufferPointer; - using Config = PreparePrimaryFramebufferConfig; - using JobModel = render::Job::ModelO; - - PreparePrimaryFramebuffer(float resolutionScale = 1.0f) : _resolutionScale{resolutionScale} {} - void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, Output& primaryFramebuffer); - - gpu::FramebufferPointer _primaryFramebuffer; - float _resolutionScale{ 1.0f }; - -private: - - static gpu::FramebufferPointer createFramebuffer(const char* name, const glm::uvec2& size); -}; - class PrepareDeferred { public: // Inputs: primaryFramebuffer and lightingModel diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 39024eaeab..e5de6ccd27 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -177,28 +177,6 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer }); } -void NewFramebuffer::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { - RenderArgs* args = renderContext->args; - // auto frameSize = input; - output.reset(); - - glm::uvec2 frameSize(args->_viewport.z, args->_viewport.w); - - if (_outputFramebuffer && _outputFramebuffer->getSize() != frameSize) { - _outputFramebuffer.reset(); - } - - if (!_outputFramebuffer) { - _outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("newFramebuffer.out")); - auto colorFormat = gpu::Element::COLOR_SRGBA_32; - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); - auto colorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); - _outputFramebuffer->setRenderBuffer(0, colorTexture); - } - - output = _outputFramebuffer; -} - void NewOrDefaultFramebuffer::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { RenderArgs* args = renderContext->args; // auto frameSize = input; diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index 0094fc1efd..756445a30f 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -84,18 +84,6 @@ public: void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer); }; - -class NewFramebuffer { -public: - using Input = glm::uvec2; - using Output = gpu::FramebufferPointer; - using JobModel = render::Job::ModelIO; - - void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); -private: - gpu::FramebufferPointer _outputFramebuffer; -}; - class NewOrDefaultFramebuffer { public: using Input = glm::uvec2; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index eb69bad32e..a9ceba8f5a 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -428,6 +428,44 @@ void RenderDeferredTaskDebug::build(JobModel& task, const render::Varying& input } +gpu::FramebufferPointer PreparePrimaryFramebuffer::createFramebuffer(const char* name, const glm::uvec2& frameSize) { + gpu::FramebufferPointer framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(name)); + auto colorFormat = gpu::Element::COLOR_SRGBA_32; + + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); + auto primaryColorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); + + framebuffer->setRenderBuffer(0, primaryColorTexture); + + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format + auto primaryDepthTexture = gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); + + framebuffer->setDepthStencilBuffer(primaryDepthTexture, depthFormat); + + return framebuffer; +} + +void PreparePrimaryFramebuffer::configure(const Config& config) { + _resolutionScale = config.getResolutionScale(); +} + +void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, Output& primaryFramebuffer) { + glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); + glm::uvec2 scaledFrameSize(glm::vec2(frameSize) * _resolutionScale); + + // Resizing framebuffers instead of re-building them seems to cause issues with threaded + // rendering + if (!_primaryFramebuffer || _primaryFramebuffer->getSize() != scaledFrameSize) { + _primaryFramebuffer = createFramebuffer("deferredPrimary", scaledFrameSize); + } + + primaryFramebuffer = _primaryFramebuffer; + + // Set viewport for the rest of the scaled passes + renderContext->args->_viewport.z = scaledFrameSize.x; + renderContext->args->_viewport.w = scaledFrameSize.y; +} + void RenderTransparentDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) { assert(renderContext->args); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 3eb1153928..ee397d94c7 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -149,4 +149,40 @@ public: private: }; + +class PreparePrimaryFramebufferConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale) +public: + float getResolutionScale() const { return resolutionScale; } + void setResolutionScale(float scale) { + resolutionScale = std::max(0.1f, std::min(2.0f, scale)); + } + +signals: + void dirty(); + +protected: + float resolutionScale{ 1.0f }; +}; + +class PreparePrimaryFramebuffer { +public: + + using Output = gpu::FramebufferPointer; + using Config = PreparePrimaryFramebufferConfig; + using JobModel = render::Job::ModelO; + + PreparePrimaryFramebuffer(float resolutionScale = 1.0f) : _resolutionScale{ resolutionScale } {} + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, Output& primaryFramebuffer); + + gpu::FramebufferPointer _primaryFramebuffer; + float _resolutionScale{ 1.0f }; + +private: + + static gpu::FramebufferPointer createFramebuffer(const char* name, const glm::uvec2& size); +}; + #endif // hifi_RenderDeferredTask_h From 8c3ddc049ce33c596a1fd1f8f519e9a50ae327b6 Mon Sep 17 00:00:00 2001 From: Anna Date: Fri, 21 Jun 2019 20:08:09 -0700 Subject: [PATCH 18/63] works on desktop, android mobile, rift and quest --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 17 ----------------- .../Basic2DWindowOpenGLDisplayPlugin.h | 2 -- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 8 +------- .../src/display-plugins/OpenGLDisplayPlugin.h | 1 - plugins/oculus/src/OculusDisplayPlugin.cpp | 5 +++++ plugins/oculus/src/OculusDisplayPlugin.h | 1 + 6 files changed, 7 insertions(+), 27 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 38f7600315..b8912d95b6 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -123,23 +123,6 @@ gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getRenderTexturePipeline( #endif } -gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getCompositeScenePipeline() { -#if defined(Q_OS_ANDROID) - return _linearToSRGBPipeline; -#else - return _drawTexturePipeline; -#endif -} - -gpu::Element Basic2DWindowOpenGLDisplayPlugin::getCompositeFBColorSpace() { -#if defined(Q_OS_ANDROID) - return gpu::Element::COLOR_SRGBA_32; -#else - return gpu::Element::COLOR_RGBA_32; -#endif -} - - void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { #if defined(Q_OS_ANDROID) auto& virtualPadManager = VirtualPad::Manager::instance(); diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index ae830b2e28..68301ff8b4 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -38,8 +38,6 @@ public: virtual void pluginUpdate() override {}; virtual gpu::PipelinePointer getRenderTexturePipeline() override; - virtual gpu::PipelinePointer getCompositeScenePipeline() override; - virtual gpu::Element getCompositeFBColorSpace() override; protected: mutable bool _isThrottled = false; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 7d12825b7e..75cdf5ebef 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -905,7 +905,7 @@ OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { void OpenGLDisplayPlugin::updateCompositeFramebuffer() { auto renderSize = glm::uvec2(getRecommendedRenderSize()); if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { - _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", getCompositeFBColorSpace(), renderSize.x, renderSize.y)); + _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y)); } } @@ -968,9 +968,3 @@ gpu::PipelinePointer OpenGLDisplayPlugin::getCompositeScenePipeline() { return _drawTexturePipeline; } -// Added this to allow desktop composite framebuffer to be RGBA while mobile is SRGBA, so that tone mapping looks right on both platforms -// Overridden by Basic2DWindowDisplayPlugin to achieve this -// FIXME: Eventually it would be ideal to have both framebuffers be of the same type -gpu::Element OpenGLDisplayPlugin::getCompositeFBColorSpace() { - return gpu::Element::COLOR_RGBA_32; -} diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index d5d9bad8a6..a6ab40d2bc 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -163,7 +163,6 @@ protected: virtual gpu::PipelinePointer getRenderTexturePipeline(); virtual gpu::PipelinePointer getCompositeScenePipeline(); - virtual gpu::Element getCompositeFBColorSpace(); struct CursorData { QImage image; diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index c493588992..f928ccb8a4 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -124,6 +124,11 @@ void OculusDisplayPlugin::uncustomizeContext() { Parent::uncustomizeContext(); } +gpu::PipelinePointer OculusDisplayPlugin::getRenderTexturePipeline() { + //return _SRGBToLinearPipeline; + return _drawTexturePipeline; +} + gpu::PipelinePointer OculusDisplayPlugin::getCompositeScenePipeline() { return _SRGBToLinearPipeline; } diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index b220ee0214..a892d27534 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -24,6 +24,7 @@ public: virtual QJsonObject getHardwareStats() const; + virtual gpu::PipelinePointer getRenderTexturePipeline() override; virtual gpu::PipelinePointer getCompositeScenePipeline() override; protected: From 73616b81f39bd49362f0e55b893203f544c1369f Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Thu, 20 Jun 2019 15:36:28 -0700 Subject: [PATCH 19/63] Fail on empty LAUNCHER_HMAC_SECRET Priot to this change there was code that attempted to verify that LAUNCHER_HMAC_SECRET was set to something. This code was broke though and didn't catch the case correctly. This change fixes the check. --- launchers/darwin/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index 4da675fcc9..9592ef69f3 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -67,7 +67,7 @@ add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${src_files}) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME} MACOSX_BUNDLE_BUNDLE_NAME ${APP_NAME}) set_from_env(LAUNCHER_HMAC_SECRET LAUNCHER_HMAC_SECRET "") -if (LAUNCHER_HMAC_SECRET STREQUAL "") +if ("${LAUNCHER_HMAC_SECRET}" STREQUAL "") message(FATAL_ERROR "LAUNCHER_HMAC_SECRET is not set") endif() From 3a5aa4194e7fe5a745a1ff17a1f6cb3ebed497db Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Sat, 22 Jun 2019 11:23:17 -0700 Subject: [PATCH 20/63] Pin the macOS HQ Launcher target version to 10.9 This change pins HQ Launcher's target SDK to 10.9, which is the same as the target SDK for Interface. Without this pinned value the target version defaults to whatever the OS version is on the machine that happened to build HQ Launcher. --- launchers/darwin/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index 9592ef69f3..76d209d89d 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 3.0) +set(ENV{MACOSX_DEPLOYMENT_TARGET} 10.9) project(HQLauncher) set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/") set(src_files From 4d28c5fe412ae1f3df98ccf1edf1f6660211b0a5 Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Sat, 22 Jun 2019 11:32:36 -0700 Subject: [PATCH 21/63] Use version from Interface in macOS HQ Launcher Prior to this change the macOS HQ Launcher used the version from the settings files. Pull this information in the settings file could result in a situation where the setting file was updated, but interface wasn't. When the launcher ran a second time it would check the settings file and think Interface was updated even though it wasn't. This change resolves the issue by asking interface for its version directly. In the event that Interface doesn't response with a version number HQ Launcher knows how to interoperate HQ Launcher will fall back to using the settings file. Known Issues --- 1) Interface reports different version number formats depending on how its built. A stable interface for getting the build version from interface should be added. --- launchers/darwin/CMakeLists.txt | 2 + launchers/darwin/src/Interface.h | 8 ++ launchers/darwin/src/Interface.m | 100 ++++++++++++++++++++++ launchers/darwin/src/LatestBuildRequest.m | 25 ++++-- 4 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 launchers/darwin/src/Interface.h create mode 100644 launchers/darwin/src/Interface.m diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index 76d209d89d..a3fc0dc7c1 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -27,6 +27,8 @@ set(src_files src/LatestBuildRequest.m src/OrganizationRequest.m src/OrganizationRequest.h + src/Interface.h + src/Interface.m src/ErrorViewController.h src/ErrorViewController.m src/Settings.h diff --git a/launchers/darwin/src/Interface.h b/launchers/darwin/src/Interface.h new file mode 100644 index 0000000000..c142aeecf5 --- /dev/null +++ b/launchers/darwin/src/Interface.h @@ -0,0 +1,8 @@ +#import + +@interface Interface : NSObject + +-(id _Nonnull) initWith:(NSString * _Nonnull) aPathToInterface; +-(NSInteger) getVersion:(out NSError * _Nullable * _Nonnull) anError; + +@end diff --git a/launchers/darwin/src/Interface.m b/launchers/darwin/src/Interface.m new file mode 100644 index 0000000000..b007e7faa5 --- /dev/null +++ b/launchers/darwin/src/Interface.m @@ -0,0 +1,100 @@ +#import "Interface.h" + +@implementation Interface +{ + NSString *pathTo; +} + +-(id) initWith:(NSString*)aPathToInterface +{ + [self init]; + self->pathTo = [NSString stringWithFormat:@"%@/Contents/MacOS/interface", aPathToInterface]; + return self; +} + +-(NSInteger) getVersion:(out NSError * _Nullable *) outError +{ + NSTask * interface = [[NSTask alloc] init]; + NSPipe * standardOut = [NSPipe pipe]; + + interface.launchPath = self->pathTo; + interface.arguments = @[ @"--version" ]; + interface.standardOutput = standardOut; + + NSLog(@"calling interface at %@", self->pathTo); + + if (@available(macOS 10.13, *)) { + NSError *error = nil; + if (![interface launchAndReturnError:&error]) { + *outError = [NSError errorWithDomain:@"interface" + code:-1 + userInfo:@{NSUnderlyingErrorKey: error}]; + return 0; + } + } else { + NSError *error = nil; + [interface launch]; + [interface waitUntilExit]; + if (0 != [interface terminationStatus]) { + *outError = [NSError errorWithDomain:@"interface" + code:-1 + userInfo:@{NSUnderlyingErrorKey: error}]; + return 0; + } + } + + NSFileHandle * fh = [standardOut fileHandleForReading]; + NSData * data = [fh readDataToEndOfFile]; + NSString * output = [NSString stringWithUTF8String:[data bytes]]; + if (output == nil) { + NSDictionary * userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't start interface", nil) + }; + *outError = [NSError errorWithDomain:@"interface" + code:-1 + userInfo:userInfo]; + return 0; + } + + // Interface returns the build version as a string like this: + // "Interface 33333-DEADBEEF". This code grabs the substring + // between "Interface " and the hyphon ("-") + NSRange start = [output rangeOfString:@"Interface "]; + if (start.length == 0) { + NSDictionary * userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil) + }; + *outError = [NSError errorWithDomain:@"interface" + code:-2 + userInfo:userInfo]; + return 0; + } + NSRange end = [output rangeOfString:@"-"]; + if (end.length == 0) { + NSDictionary * userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil) + }; + *outError = [NSError errorWithDomain:@"interface" + code:-2 + userInfo:userInfo]; + return 0; + } + NSRange subRange = {start.length, end.location - start.length}; + NSString * versionStr; + @try { + versionStr = [output substringWithRange:subRange]; + } + @catch (NSException *) { + NSDictionary * userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil) + }; + *outError = [NSError errorWithDomain:@"interface" + code:-2 + userInfo:userInfo]; + return 0; + } + + return versionStr.integerValue; +} + +@end diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index 5119efa8f6..21f63425ab 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -1,9 +1,22 @@ #import "LatestBuildRequest.h" #import "Launcher.h" #import "Settings.h" +#import "Interface.h" @implementation LatestBuildRequest +- (NSInteger) getCurrentVersion { + NSString* interfaceAppPath = [[Launcher.sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]; + NSError * error = nil; + Interface * interface = [[Interface alloc] initWith:interfaceAppPath]; + NSInteger currentVersion = [interface getVersion:&error]; + if (currentVersion == 0 && error != nil) { + NSLog(@"can't get version from interface, falling back to settings: %@", error); + currentVersion = [Settings.sharedSettings latestBuildVersion]; + } + return currentVersion; +} + - (void) requestLatestBuildInfo { NSMutableURLRequest *request = [NSMutableURLRequest new]; [request setURL:[NSURL URLWithString:@"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"]]; @@ -45,8 +58,7 @@ BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]]; dispatch_async(dispatch_get_main_queue(), ^{ - Settings* settings = [Settings sharedSettings]; - NSInteger currentVersion = [settings latestBuildVersion]; + NSInteger currentVersion = [self getCurrentVersion]; NSLog(@"Latest Build Request -> does build directory exist: %@", appDirectoryExist ? @"TRUE" : @"FALSE"); NSLog(@"Latest Build Request -> current version: %ld", currentVersion); NSLog(@"Latest Build Request -> latest version: %ld", buildNumber.integerValue); @@ -105,11 +117,10 @@ NSDictionary* macInstallerObject = [installers objectForKey:@"mac"]; NSString* macInstallerUrl = [macInstallerObject valueForKey:@"zip_url"]; - BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]]; - - Settings* settings = [Settings sharedSettings]; - NSInteger currentVersion = [settings latestBuildVersion]; - BOOL latestVersionAvailable = (currentVersion != buildNumber.integerValue); + NSString* interfaceAppPath = [[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]; + BOOL appDirectoryExist = [fileManager fileExistsAtPath:interfaceAppPath]; + + BOOL latestVersionAvailable = ([self getCurrentVersion] != buildNumber.integerValue); [[Settings sharedSettings] buildVersion:buildNumber.integerValue]; BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist); From 4f6e2c85f9c14ae89b303b1b0ee0800f4845e77c Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Sat, 22 Jun 2019 12:28:57 -0700 Subject: [PATCH 22/63] Never cache the tags API in macOS's HQ Launcher Prior to this change we used the default session while downloading the latest tags API response from Thunder. This left open the possibility that NSURLSession could cache the response, even though the server asked it not to; NSURLSession can be pretty aggressive about its caching. This change ensure no caching of the API is occurring my using an ephemeral session when calling the tags API. --- launchers/darwin/src/LatestBuildRequest.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index 21f63425ab..7e836548af 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -23,8 +23,8 @@ [request setHTTPMethod:@"GET"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; - - NSURLSession* session = [NSURLSession sharedSession]; + // We're using an ephermeral session here to ensure the tags api response is never cached. + NSURLSession * session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration]; NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { From 9e309b095da40440ac5b5c6a052b1bdc9a5b8e68 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sun, 23 Jun 2019 08:00:13 -0700 Subject: [PATCH 23/63] Fix bug that was packing zero offsets that were never used --- libraries/render-utils/src/Model.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 64a46f3c1e..eccc7287b2 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1738,6 +1738,9 @@ void Blender::run() { int numMeshes = 0; // number of meshes in this model. for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) { numMeshes++; + if (meshIter->blendshapes.isEmpty()) { + continue; + } int numVertsInMesh = meshIter->vertices.size(); numBlendshapeOffsets += numVertsInMesh; } From 87c680382f5c11bb8556e901fcff383fdd2b1285 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sun, 23 Jun 2019 08:42:38 -0700 Subject: [PATCH 24/63] Strip-mining optimization to improve cache utilization. For each mesh: init, accumulate, and pack using a recycled offset buffer. --- libraries/render-utils/src/Model.cpp | 32 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index eccc7287b2..6e969fe51f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1735,6 +1735,7 @@ Blender::Blender(ModelPointer model, HFMModel::ConstPointer hfmModel, int blendN void Blender::run() { DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } }); int numBlendshapeOffsets = 0; // number of offsets required for all meshes. + int maxBlendshapeOffsets = 0; // number of offsets in the largest mesh. int numMeshes = 0; // number of meshes in this model. for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) { numMeshes++; @@ -1743,16 +1744,19 @@ void Blender::run() { } int numVertsInMesh = meshIter->vertices.size(); numBlendshapeOffsets += numVertsInMesh; + maxBlendshapeOffsets = std::max(maxBlendshapeOffsets, numVertsInMesh); } - // all elements are default constructed to zero offsets. - QVector packedBlendshapeOffsets(numBlendshapeOffsets); - QVector unpackedBlendshapeOffsets(numBlendshapeOffsets); - - // allocate the required size + // allocate the required sizes QVector blendedMeshSizes; blendedMeshSizes.reserve(numMeshes); + QVector packedBlendshapeOffsets; + packedBlendshapeOffsets.reserve(numBlendshapeOffsets); + + QVector unpackedBlendshapeOffsets; + unpackedBlendshapeOffsets.reserve(maxBlendshapeOffsets); // reuse for all meshes + int offset = 0; for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) { if (meshIter->blendshapes.isEmpty()) { @@ -1762,6 +1766,9 @@ void Blender::run() { int numVertsInMesh = meshIter->vertices.size(); blendedMeshSizes.push_back(numVertsInMesh); + // initialize offsets to zero + memset(unpackedBlendshapeOffsets.data(), 0, numVertsInMesh * sizeof(BlendshapeOffsetUnpacked)); + // for each blendshape in this mesh, accumulate the offsets into unpackedBlendshapeOffsets. const float NORMAL_COEFFICIENT_SCALE = 0.01f; for (int i = 0, n = qMin(_blendshapeCoefficients.size(), meshIter->blendshapes.size()); i < n; i++) { @@ -1776,7 +1783,7 @@ void Blender::run() { for (int j = 0; j < blendshape.indices.size(); ++j) { int index = blendshape.indices.at(j); - auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[offset + index]; + auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[index]; currentBlendshapeOffset.positionOffset += blendshape.vertices.at(j) * vertexCoefficient; currentBlendshapeOffset.normalOffset += blendshape.normals.at(j) * normalCoefficient; if (j < blendshape.tangents.size()) { @@ -1784,20 +1791,19 @@ void Blender::run() { } } } - offset += numVertsInMesh; - } - // convert unpackedBlendshapeOffsets into packedBlendshapeOffsets for the gpu. - // FIXME it feels like we could be more effectively using SIMD here - { + // convert unpackedBlendshapeOffsets into packedBlendshapeOffsets for the gpu. auto unpacked = unpackedBlendshapeOffsets.data(); - auto packed = packedBlendshapeOffsets.data(); - for (int i = 0; i < unpackedBlendshapeOffsets.size(); ++i) { + auto packed = packedBlendshapeOffsets.data() + offset; + for (int i = 0; i < numVertsInMesh; ++i) { packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked)); ++unpacked; ++packed; } + + offset += numVertsInMesh; } + Q_ASSERT(offset == numBlendshapeOffsets); // post the result to the ModelBlender, which will dispatch to the model if still alive QMetaObject::invokeMethod(DependencyManager::get().data(), "setBlendedVertices", From cceff21cd0ea1d583e39c6dea5f333df909bed10 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sun, 23 Jun 2019 08:57:56 -0700 Subject: [PATCH 25/63] Pull packBlendshapeOffsets() into separate function --- libraries/render-utils/src/Model.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6e969fe51f..6a06047bef 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1691,10 +1691,7 @@ public: } }; - -using packBlendshapeOffsetTo = void(glm::uvec4& packed, const BlendshapeOffsetUnpacked& unpacked); - -void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uvec4& packed, const BlendshapeOffsetUnpacked& unpacked) { +static void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uvec4& packed, const BlendshapeOffsetUnpacked& unpacked) { float len = glm::compMax(glm::abs(unpacked.positionOffset)); glm::vec3 normalizedPos(unpacked.positionOffset); if (len > 0.0f) { @@ -1711,6 +1708,14 @@ void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uvec4& pac ); } +static void packBlendshapeOffsets(BlendshapeOffsetUnpacked* unpacked, BlendshapeOffsetPacked* packed, int size) { + for (int i = 0; i < size; ++i) { + packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked)); + ++unpacked; + ++packed; + } +} + class Blender : public QRunnable { public: @@ -1795,11 +1800,7 @@ void Blender::run() { // convert unpackedBlendshapeOffsets into packedBlendshapeOffsets for the gpu. auto unpacked = unpackedBlendshapeOffsets.data(); auto packed = packedBlendshapeOffsets.data() + offset; - for (int i = 0; i < numVertsInMesh; ++i) { - packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked)); - ++unpacked; - ++packed; - } + packBlendshapeOffsets(unpacked, packed, numVertsInMesh); offset += numVertsInMesh; } From 8653118b6cb09810b7d1688ddb62975d52b96f05 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sun, 23 Jun 2019 10:32:57 -0700 Subject: [PATCH 26/63] Full SIMD implementation of packBlendshapeOffsets() using AVX2. 6x speedup over the existing (partial SIMD) version. 60x speedup over the original (pure GLM) version. --- libraries/render-utils/src/Model.cpp | 10 +- .../src/avx2/BlendshapePacking_avx2.cpp | 285 ++++++++++++++++++ 2 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 libraries/render-utils/src/avx2/BlendshapePacking_avx2.cpp diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6a06047bef..67f64395b2 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1708,7 +1708,7 @@ static void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uve ); } -static void packBlendshapeOffsets(BlendshapeOffsetUnpacked* unpacked, BlendshapeOffsetPacked* packed, int size) { +static void packBlendshapeOffsets_ref(BlendshapeOffsetUnpacked* unpacked, BlendshapeOffsetPacked* packed, int size) { for (int i = 0; i < size; ++i) { packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked)); ++unpacked; @@ -1716,6 +1716,14 @@ static void packBlendshapeOffsets(BlendshapeOffsetUnpacked* unpacked, Blendshape } } +void packBlendshapeOffsets_AVX2(float (*unpacked)[9], uint32_t (*packed)[4], int size); + +static void packBlendshapeOffsets(BlendshapeOffsetUnpacked* unpacked, BlendshapeOffsetPacked* packed, int size) { + static_assert(sizeof(BlendshapeOffsetUnpacked) == 9 * sizeof(float), "struct BlendshapeOffsetUnpacked size doesn't match."); + static_assert(sizeof(BlendshapeOffsetPacked) == 4 * sizeof(uint32_t), "struct BlendshapeOffsetPacked size doesn't match."); + packBlendshapeOffsets_AVX2((float(*)[9])unpacked, (uint32_t(*)[4])packed, size); +} + class Blender : public QRunnable { public: diff --git a/libraries/render-utils/src/avx2/BlendshapePacking_avx2.cpp b/libraries/render-utils/src/avx2/BlendshapePacking_avx2.cpp new file mode 100644 index 0000000000..5524c355dc --- /dev/null +++ b/libraries/render-utils/src/avx2/BlendshapePacking_avx2.cpp @@ -0,0 +1,285 @@ +// +// BlendshapePacking_avx2.cpp +// +// Created by Ken Cooke on 6/22/19. +// Copyright 2019 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 +// + +#ifdef __AVX2__ + +#include +#include + +void packBlendshapeOffsets_AVX2(float (*unpacked)[9], uint32_t (*packed)[4], int size) { + + int i = 0; + for (; i < size - 7; i += 8) { // blocks of 8 + + // + // deinterleave (8x9 to 9x8 matrix transpose) + // + __m256 s0 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+0][0])), _mm_load_ps(&unpacked[i+4][0]), 1); + __m256 s1 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+1][0])), _mm_load_ps(&unpacked[i+5][0]), 1); + __m256 s2 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+2][0])), _mm_load_ps(&unpacked[i+6][0]), 1); + __m256 s3 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+3][0])), _mm_load_ps(&unpacked[i+7][0]), 1); + __m256 s4 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+0][4])), _mm_load_ps(&unpacked[i+4][4]), 1); + __m256 s5 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+1][4])), _mm_load_ps(&unpacked[i+5][4]), 1); + __m256 s6 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+2][4])), _mm_load_ps(&unpacked[i+6][4]), 1); + __m256 s7 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+3][4])), _mm_load_ps(&unpacked[i+7][4]), 1); + + __m256 t0 = _mm256_unpacklo_ps(s0, s1); + __m256 t1 = _mm256_unpackhi_ps(s0, s1); + __m256 t2 = _mm256_unpacklo_ps(s2, s3); + __m256 t3 = _mm256_unpackhi_ps(s2, s3); + __m256 t4 = _mm256_unpacklo_ps(s4, s5); + __m256 t5 = _mm256_unpackhi_ps(s4, s5); + __m256 t6 = _mm256_unpacklo_ps(s6, s7); + __m256 t7 = _mm256_unpackhi_ps(s6, s7); + + __m256 px = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(1,0,1,0)); + __m256 py = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(3,2,3,2)); + __m256 pz = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(1,0,1,0)); + __m256 nx = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(3,2,3,2)); + __m256 ny = _mm256_shuffle_ps(t4, t6, _MM_SHUFFLE(1,0,1,0)); + __m256 nz = _mm256_shuffle_ps(t4, t6, _MM_SHUFFLE(3,2,3,2)); + __m256 tx = _mm256_shuffle_ps(t5, t7, _MM_SHUFFLE(1,0,1,0)); + __m256 ty = _mm256_shuffle_ps(t5, t7, _MM_SHUFFLE(3,2,3,2)); + + __m256 tz = _mm256_i32gather_ps(unpacked[i+0], _mm256_setr_epi32(8,17,26,35,44,53,62,71), sizeof(float)); + + // abs(pos) + __m256 apx = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), px); + __m256 apy = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), py); + __m256 apz = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), pz); + + // len = compMax(abs(pos)) + __m256 len = _mm256_max_ps(_mm256_max_ps(apx, apy), apz); + + // detect zeros + __m256 mask = _mm256_cmp_ps(len, _mm256_setzero_ps(), _CMP_EQ_OQ); + + // rcp = 1.0f / len + __m256 rcp = _mm256_div_ps(_mm256_set1_ps(1.0f), len); + + // replace +inf with 1.0f + rcp = _mm256_blendv_ps(rcp, _mm256_set1_ps(1.0f), mask); + len = _mm256_blendv_ps(len, _mm256_set1_ps(1.0f), mask); + + // pos *= 1.0f / len + px = _mm256_mul_ps(px, rcp); + py = _mm256_mul_ps(py, rcp); + pz = _mm256_mul_ps(pz, rcp); + + // clamp(vec, -1.0f, 1.0f) + px = _mm256_min_ps(_mm256_max_ps(px, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + py = _mm256_min_ps(_mm256_max_ps(py, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + pz = _mm256_min_ps(_mm256_max_ps(pz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + nx = _mm256_min_ps(_mm256_max_ps(nx, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + ny = _mm256_min_ps(_mm256_max_ps(ny, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + nz = _mm256_min_ps(_mm256_max_ps(nz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + tx = _mm256_min_ps(_mm256_max_ps(tx, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + ty = _mm256_min_ps(_mm256_max_ps(ty, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + tz = _mm256_min_ps(_mm256_max_ps(tz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + + // vec *= 511.0f + px = _mm256_mul_ps(px, _mm256_set1_ps(511.0f)); + py = _mm256_mul_ps(py, _mm256_set1_ps(511.0f)); + pz = _mm256_mul_ps(pz, _mm256_set1_ps(511.0f)); + nx = _mm256_mul_ps(nx, _mm256_set1_ps(511.0f)); + ny = _mm256_mul_ps(ny, _mm256_set1_ps(511.0f)); + nz = _mm256_mul_ps(nz, _mm256_set1_ps(511.0f)); + tx = _mm256_mul_ps(tx, _mm256_set1_ps(511.0f)); + ty = _mm256_mul_ps(ty, _mm256_set1_ps(511.0f)); + tz = _mm256_mul_ps(tz, _mm256_set1_ps(511.0f)); + + // veci = lrint(vec) & 03ff + __m256i pxi = _mm256_and_si256(_mm256_cvtps_epi32(px), _mm256_set1_epi32(0x3ff)); + __m256i pyi = _mm256_and_si256(_mm256_cvtps_epi32(py), _mm256_set1_epi32(0x3ff)); + __m256i pzi = _mm256_and_si256(_mm256_cvtps_epi32(pz), _mm256_set1_epi32(0x3ff)); + __m256i nxi = _mm256_and_si256(_mm256_cvtps_epi32(nx), _mm256_set1_epi32(0x3ff)); + __m256i nyi = _mm256_and_si256(_mm256_cvtps_epi32(ny), _mm256_set1_epi32(0x3ff)); + __m256i nzi = _mm256_and_si256(_mm256_cvtps_epi32(nz), _mm256_set1_epi32(0x3ff)); + __m256i txi = _mm256_and_si256(_mm256_cvtps_epi32(tx), _mm256_set1_epi32(0x3ff)); + __m256i tyi = _mm256_and_si256(_mm256_cvtps_epi32(ty), _mm256_set1_epi32(0x3ff)); + __m256i tzi = _mm256_and_si256(_mm256_cvtps_epi32(tz), _mm256_set1_epi32(0x3ff)); + + // pack = (xi << 0) | (yi << 10) | (zi << 20); + __m256i li = _mm256_castps_si256(len); // length + __m256i pi = _mm256_or_si256(_mm256_or_si256(pxi, _mm256_slli_epi32(pyi, 10)), _mm256_slli_epi32(pzi, 20)); // position + __m256i ni = _mm256_or_si256(_mm256_or_si256(nxi, _mm256_slli_epi32(nyi, 10)), _mm256_slli_epi32(nzi, 20)); // normal + __m256i ti = _mm256_or_si256(_mm256_or_si256(txi, _mm256_slli_epi32(tyi, 10)), _mm256_slli_epi32(tzi, 20)); // tangent + + // + // interleave (4x4 matrix transpose) + // + __m256i u0 = _mm256_unpacklo_epi32(li, pi); + __m256i u1 = _mm256_unpackhi_epi32(li, pi); + __m256i u2 = _mm256_unpacklo_epi32(ni, ti); + __m256i u3 = _mm256_unpackhi_epi32(ni, ti); + + __m256i v0 = _mm256_unpacklo_epi64(u0, u2); + __m256i v1 = _mm256_unpackhi_epi64(u0, u2); + __m256i v2 = _mm256_unpacklo_epi64(u1, u3); + __m256i v3 = _mm256_unpackhi_epi64(u1, u3); + + __m256i w0 = _mm256_permute2f128_si256(v0, v1, 0x20); + __m256i w1 = _mm256_permute2f128_si256(v2, v3, 0x20); + __m256i w2 = _mm256_permute2f128_si256(v0, v1, 0x31); + __m256i w3 = _mm256_permute2f128_si256(v2, v3, 0x31); + + // store pack x 8 + _mm256_storeu_si256((__m256i*)packed[i+0], w0); + _mm256_storeu_si256((__m256i*)packed[i+2], w1); + _mm256_storeu_si256((__m256i*)packed[i+4], w2); + _mm256_storeu_si256((__m256i*)packed[i+6], w3); + } + + if (i < size) { // remainder + int rem = size - i; + + // + // deinterleave (8x9 to 9x8 matrix transpose) + // + __m256 s0 = _mm256_setzero_ps(); + __m256 s1 = _mm256_setzero_ps(); + __m256 s2 = _mm256_setzero_ps(); + __m256 s3 = _mm256_setzero_ps(); + __m256 s4 = _mm256_setzero_ps(); + __m256 s5 = _mm256_setzero_ps(); + __m256 s6 = _mm256_setzero_ps(); + __m256 s7 = _mm256_setzero_ps(); + + switch (rem) { + case 7: s6 = _mm256_loadu_ps(unpacked[i+6]); + case 6: s5 = _mm256_loadu_ps(unpacked[i+5]); + case 5: s4 = _mm256_loadu_ps(unpacked[i+4]); + case 4: s3 = _mm256_loadu_ps(unpacked[i+3]); + case 3: s2 = _mm256_loadu_ps(unpacked[i+2]); + case 2: s1 = _mm256_loadu_ps(unpacked[i+1]); + case 1: s0 = _mm256_loadu_ps(unpacked[i+0]); + } + + __m256 t0 = _mm256_unpacklo_ps(s0, s1); + __m256 t1 = _mm256_unpackhi_ps(s0, s1); + __m256 t2 = _mm256_unpacklo_ps(s2, s3); + __m256 t3 = _mm256_unpackhi_ps(s2, s3); + __m256 t4 = _mm256_unpacklo_ps(s4, s5); + __m256 t5 = _mm256_unpackhi_ps(s4, s5); + __m256 t6 = _mm256_unpacklo_ps(s6, s7); + __m256 t7 = _mm256_unpackhi_ps(s6, s7); + + s0 = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(1,0,1,0)); + s1 = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(3,2,3,2)); + s2 = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(1,0,1,0)); + s3 = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(3,2,3,2)); + s4 = _mm256_shuffle_ps(t4, t6, _MM_SHUFFLE(1,0,1,0)); + s5 = _mm256_shuffle_ps(t4, t6, _MM_SHUFFLE(3,2,3,2)); + s6 = _mm256_shuffle_ps(t5, t7, _MM_SHUFFLE(1,0,1,0)); + s7 = _mm256_shuffle_ps(t5, t7, _MM_SHUFFLE(3,2,3,2)); + + __m256 px = _mm256_permute2f128_ps(s0, s4, 0x20); + __m256 py = _mm256_permute2f128_ps(s1, s5, 0x20); + __m256 pz = _mm256_permute2f128_ps(s2, s6, 0x20); + __m256 nx = _mm256_permute2f128_ps(s3, s7, 0x20); + __m256 ny = _mm256_permute2f128_ps(s0, s4, 0x31); + __m256 nz = _mm256_permute2f128_ps(s1, s5, 0x31); + __m256 tx = _mm256_permute2f128_ps(s2, s6, 0x31); + __m256 ty = _mm256_permute2f128_ps(s3, s7, 0x31); + + __m256i loadmask = _mm256_cvtepi8_epi32(_mm_cvtsi64_si128(0xffffffffffffffffULL >> (64 - 8 * rem))); + __m256 tz = _mm256_mask_i32gather_ps(_mm256_setzero_ps(), unpacked[i+0], _mm256_setr_epi32(8,17,26,35,44,53,62,71), + _mm256_castsi256_ps(loadmask), sizeof(float)); + // abs(pos) + __m256 apx = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), px); + __m256 apy = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), py); + __m256 apz = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), pz); + + // len = compMax(abs(pos)) + __m256 len = _mm256_max_ps(_mm256_max_ps(apx, apy), apz); + + // detect zeros + __m256 mask = _mm256_cmp_ps(len, _mm256_setzero_ps(), _CMP_EQ_OQ); + + // rcp = 1.0f / len + __m256 rcp = _mm256_div_ps(_mm256_set1_ps(1.0f), len); + + // replace +inf with 1.0f + rcp = _mm256_blendv_ps(rcp, _mm256_set1_ps(1.0f), mask); + len = _mm256_blendv_ps(len, _mm256_set1_ps(1.0f), mask); + + // pos *= 1.0f / len + px = _mm256_mul_ps(px, rcp); + py = _mm256_mul_ps(py, rcp); + pz = _mm256_mul_ps(pz, rcp); + + // clamp(vec, -1.0f, 1.0f) + px = _mm256_min_ps(_mm256_max_ps(px, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + py = _mm256_min_ps(_mm256_max_ps(py, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + pz = _mm256_min_ps(_mm256_max_ps(pz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + nx = _mm256_min_ps(_mm256_max_ps(nx, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + ny = _mm256_min_ps(_mm256_max_ps(ny, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + nz = _mm256_min_ps(_mm256_max_ps(nz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + tx = _mm256_min_ps(_mm256_max_ps(tx, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + ty = _mm256_min_ps(_mm256_max_ps(ty, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + tz = _mm256_min_ps(_mm256_max_ps(tz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f)); + + // vec *= 511.0f + px = _mm256_mul_ps(px, _mm256_set1_ps(511.0f)); + py = _mm256_mul_ps(py, _mm256_set1_ps(511.0f)); + pz = _mm256_mul_ps(pz, _mm256_set1_ps(511.0f)); + nx = _mm256_mul_ps(nx, _mm256_set1_ps(511.0f)); + ny = _mm256_mul_ps(ny, _mm256_set1_ps(511.0f)); + nz = _mm256_mul_ps(nz, _mm256_set1_ps(511.0f)); + tx = _mm256_mul_ps(tx, _mm256_set1_ps(511.0f)); + ty = _mm256_mul_ps(ty, _mm256_set1_ps(511.0f)); + tz = _mm256_mul_ps(tz, _mm256_set1_ps(511.0f)); + + // veci = lrint(vec) & 03ff + __m256i pxi = _mm256_and_si256(_mm256_cvtps_epi32(px), _mm256_set1_epi32(0x3ff)); + __m256i pyi = _mm256_and_si256(_mm256_cvtps_epi32(py), _mm256_set1_epi32(0x3ff)); + __m256i pzi = _mm256_and_si256(_mm256_cvtps_epi32(pz), _mm256_set1_epi32(0x3ff)); + __m256i nxi = _mm256_and_si256(_mm256_cvtps_epi32(nx), _mm256_set1_epi32(0x3ff)); + __m256i nyi = _mm256_and_si256(_mm256_cvtps_epi32(ny), _mm256_set1_epi32(0x3ff)); + __m256i nzi = _mm256_and_si256(_mm256_cvtps_epi32(nz), _mm256_set1_epi32(0x3ff)); + __m256i txi = _mm256_and_si256(_mm256_cvtps_epi32(tx), _mm256_set1_epi32(0x3ff)); + __m256i tyi = _mm256_and_si256(_mm256_cvtps_epi32(ty), _mm256_set1_epi32(0x3ff)); + __m256i tzi = _mm256_and_si256(_mm256_cvtps_epi32(tz), _mm256_set1_epi32(0x3ff)); + + // pack = (xi << 0) | (yi << 10) | (zi << 20); + __m256i li = _mm256_castps_si256(len); // length + __m256i pi = _mm256_or_si256(_mm256_or_si256(pxi, _mm256_slli_epi32(pyi, 10)), _mm256_slli_epi32(pzi, 20)); // position + __m256i ni = _mm256_or_si256(_mm256_or_si256(nxi, _mm256_slli_epi32(nyi, 10)), _mm256_slli_epi32(nzi, 20)); // normal + __m256i ti = _mm256_or_si256(_mm256_or_si256(txi, _mm256_slli_epi32(tyi, 10)), _mm256_slli_epi32(tzi, 20)); // tangent + + // + // interleave (4x4 matrix transpose) + // + __m256i u0 = _mm256_unpacklo_epi32(li, pi); + __m256i u1 = _mm256_unpackhi_epi32(li, pi); + __m256i u2 = _mm256_unpacklo_epi32(ni, ti); + __m256i u3 = _mm256_unpackhi_epi32(ni, ti); + + __m256i v0 = _mm256_unpacklo_epi64(u0, u2); + __m256i v1 = _mm256_unpackhi_epi64(u0, u2); + __m256i v2 = _mm256_unpacklo_epi64(u1, u3); + __m256i v3 = _mm256_unpackhi_epi64(u1, u3); + + // store pack x 8 + switch (rem) { + case 7: _mm_storeu_si128((__m128i*)packed[i+6], _mm256_extractf128_si256(v2, 1)); + case 6: _mm_storeu_si128((__m128i*)packed[i+5], _mm256_extractf128_si256(v1, 1)); + case 5: _mm_storeu_si128((__m128i*)packed[i+4], _mm256_extractf128_si256(v0, 1)); + case 4: _mm_storeu_si128((__m128i*)packed[i+3], _mm256_castsi256_si128(v3)); + case 3: _mm_storeu_si128((__m128i*)packed[i+2], _mm256_castsi256_si128(v2)); + case 2: _mm_storeu_si128((__m128i*)packed[i+1], _mm256_castsi256_si128(v1)); + case 1: _mm_storeu_si128((__m128i*)packed[i+0], _mm256_castsi256_si128(v0)); + } + } + + _mm256_zeroupper(); +} + +#endif From 87e0f5b2bba804f892741217a893e345f6283b53 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sun, 23 Jun 2019 10:40:15 -0700 Subject: [PATCH 27/63] Runtime dispatch for AVX2 --- libraries/render-utils/src/Model.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 67f64395b2..164090709a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1716,14 +1716,29 @@ static void packBlendshapeOffsets_ref(BlendshapeOffsetUnpacked* unpacked, Blends } } +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__) +// +// Runtime CPU dispatch +// +#include "CPUDetect.h" + void packBlendshapeOffsets_AVX2(float (*unpacked)[9], uint32_t (*packed)[4], int size); static void packBlendshapeOffsets(BlendshapeOffsetUnpacked* unpacked, BlendshapeOffsetPacked* packed, int size) { - static_assert(sizeof(BlendshapeOffsetUnpacked) == 9 * sizeof(float), "struct BlendshapeOffsetUnpacked size doesn't match."); - static_assert(sizeof(BlendshapeOffsetPacked) == 4 * sizeof(uint32_t), "struct BlendshapeOffsetPacked size doesn't match."); - packBlendshapeOffsets_AVX2((float(*)[9])unpacked, (uint32_t(*)[4])packed, size); + static bool _cpuSupportsAVX2 = cpuSupportsAVX2(); + if (_cpuSupportsAVX2) { + static_assert(sizeof(BlendshapeOffsetUnpacked) == 9 * sizeof(float), "struct BlendshapeOffsetUnpacked size doesn't match."); + static_assert(sizeof(BlendshapeOffsetPacked) == 4 * sizeof(uint32_t), "struct BlendshapeOffsetPacked size doesn't match."); + packBlendshapeOffsets_AVX2((float(*)[9])unpacked, (uint32_t(*)[4])packed, size); + } else { + packBlendshapeOffsets_ref(unpacked, packed, size); + } } +#else // portable reference code +static auto& packBlendshapeOffsets = packBlendshapeOffsets_ref; +#endif + class Blender : public QRunnable { public: From 75aea88f200b0b3cf716aba5aa1871739701097d Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 24 Jun 2019 11:51:03 -0700 Subject: [PATCH 28/63] CR feedback --- libraries/render-utils/src/Model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 164090709a..11c1e42fd4 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1720,7 +1720,7 @@ static void packBlendshapeOffsets_ref(BlendshapeOffsetUnpacked* unpacked, Blends // // Runtime CPU dispatch // -#include "CPUDetect.h" +#include void packBlendshapeOffsets_AVX2(float (*unpacked)[9], uint32_t (*packed)[4], int size); From e39ccff873465dd98e0e05e2323ab71f8db77234 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Mon, 24 Jun 2019 11:57:37 -0700 Subject: [PATCH 29/63] BUGZ-812 - Log system info on domain connect or connect refusal --- domain-server/src/DomainGatekeeper.cpp | 3 +- domain-server/src/NodeConnectionData.cpp | 6 +++- libraries/networking/CMakeLists.txt | 2 +- libraries/networking/src/NodeList.cpp | 30 +++++++++++-------- .../networking/src/ThreadedAssignment.cpp | 11 +++++++ libraries/networking/src/ThreadedAssignment.h | 2 +- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- 8 files changed, 40 insertions(+), 19 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 6d339852d5..6aaa348f6c 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -136,7 +136,8 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointergetSenderSockAddr() << "with hardware address" << nodeConnection.hardwareAddress - << "and machine fingerprint" << nodeConnection.machineFingerprint; + << "and machine fingerprint" << nodeConnection.machineFingerprint + << "sysinfo" << nodeConnection.SystemInfo; } } diff --git a/domain-server/src/NodeConnectionData.cpp b/domain-server/src/NodeConnectionData.cpp index 9703db39c8..e3406aa797 100644 --- a/domain-server/src/NodeConnectionData.cpp +++ b/domain-server/src/NodeConnectionData.cpp @@ -37,7 +37,11 @@ NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, c dataStream >> newHeader.machineFingerprint; // and the operating system type - dataStream >> newHeader.SystemInfo; + QByteArray compressedSystemInfo; + dataStream >> compressedSystemInfo; + if(!compressedSystemInfo.isEmpty()) { + newHeader.SystemInfo = qUncompress(compressedSystemInfo); + } dataStream >> newHeader.connectReason; diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index c3592c5da2..9f63f2cb00 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME networking) setup_hifi_library(Network) -link_hifi_libraries(shared) +link_hifi_libraries(shared platform) target_openssl() target_tbb() diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 96b713c583..0dad7705f8 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "AccountManager.h" #include "AddressManager.h" @@ -42,6 +44,7 @@ using namespace std::chrono; const int KEEPALIVE_PING_INTERVAL_MS = 1000; +const int MAX_SYSTEM_INFO_SIZE = 1000; NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) : LimitedNodeList(socketListenPort, dtlsListenPort), @@ -418,19 +421,20 @@ void NodeList::sendDomainServerCheckIn() { auto accountManager = DependencyManager::get(); packetStream << FingerprintUtils::getMachineFingerprint(); - QString systemInfo; -#if defined Q_OS_WIN - systemInfo = "OS:Windows"; -#elif defined Q_OS_OSX - systemInfo = "OS:OSX"; -#elif defined Q_OS_LINUX - systemInfo = "OS:Linux"; -#elif defined Q_OS_ANDROID - systemInfo = "OS:Android"; -#else - systemInfo = "OS:Unknown"; -#endif - packetStream << systemInfo; + auto desc = platform::getAll(); + + QByteArray systemInfo(desc.dump().c_str()); + QByteArray compressedSystemInfo = qCompress(systemInfo); + + if(compressedSystemInfo.size() > MAX_SYSTEM_INFO_SIZE) { + // Highly unlikely, as not even unreasonable machines will + // overflow the max size, but prevent MTU overflow anyway. + // We could do something sophisticated like clearing specific + // values if they're too big, but we'll save that for later. + compressedSystemInfo.clear(); + } + + packetStream << compressedSystemInfo; packetStream << _connectReason; diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index 2b415073f2..b8a8f65080 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "NetworkLogging.h" ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) : @@ -38,6 +39,16 @@ ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) : // if the NL tells us we got a DS response, clear our member variable of queued check-ins auto nodeList = DependencyManager::get(); connect(nodeList.data(), &NodeList::receivedDomainServerList, this, &ThreadedAssignment::clearQueuedCheckIns); + + platform::create(); + if (!platform::enumeratePlatform()) { + qCDebug(networking) << "Failed to enumerate platform."; + } +} + +ThreadedAssignment::~ThreadedAssignment() { + stop(); + platform::destroy(); } void ThreadedAssignment::setFinished(bool isFinished) { diff --git a/libraries/networking/src/ThreadedAssignment.h b/libraries/networking/src/ThreadedAssignment.h index e76533b2a1..12096cf23f 100644 --- a/libraries/networking/src/ThreadedAssignment.h +++ b/libraries/networking/src/ThreadedAssignment.h @@ -22,7 +22,7 @@ class ThreadedAssignment : public Assignment { Q_OBJECT public: ThreadedAssignment(ReceivedMessage& message); - ~ThreadedAssignment() { stop(); } + ~ThreadedAssignment(); virtual void aboutToFinish() { }; void addPacketStatsAndSendStatsPacket(QJsonObject statsObject); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index e434867c9a..ed68fe89dc 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType packetType) { return static_cast(DomainConnectionDeniedVersion::IncludesExtraInfo); case PacketType::DomainConnectRequest: - return static_cast(DomainConnectRequestVersion::HasSystemInfo); + return static_cast(DomainConnectRequestVersion::HasCompressedSystemInfo); case PacketType::DomainServerAddedNode: return static_cast(DomainServerAddedNodeVersion::PermissionsGrid); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index a244399c5a..6230b8b11e 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -347,7 +347,8 @@ enum class DomainConnectRequestVersion : PacketVersion { AlwaysHasMachineFingerprint, HasTimestamp, HasReason, - HasSystemInfo + HasSystemInfo, + HasCompressedSystemInfo }; enum class DomainConnectionDeniedVersion : PacketVersion { From 3e2e020731b8be785ea6d0ddbc1917b5b940cb8d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 24 Jun 2019 12:48:13 -0700 Subject: [PATCH 30/63] BUGZ-746: About tab: Better CPU/GPU info reporting; New copied info (including OS version) --- .../simplifiedUI/settingsApp/about/About.qml | 49 +++++++++++++++++-- .../simplifiedControls/Button.qml | 30 ++++++++++++ 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml index 76ab762a6b..3e3758e7a8 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml @@ -122,12 +122,22 @@ Flickable { } HifiStylesUit.GraphikRegular { - text: "CPU: " + PlatformInfo.getCPUBrand() + text: "CPU:" Layout.maximumWidth: parent.width height: paintedHeight size: 16 color: simplifiedUI.colors.text.white wrapMode: Text.Wrap + + Component.onCompleted: { + var cpu = JSON.parse(PlatformInfo.getCPU(0)); + var cpuModel = cpu.model; + if (cpuModel.length === 0) { + cpuModel = "Unknown"; + } + + text = "CPU: " + cpuModel; + } } HifiStylesUit.GraphikRegular { @@ -158,12 +168,22 @@ Flickable { } HifiStylesUit.GraphikRegular { - text: "GPU: " + PlatformInfo.getGraphicsCardType() + text: "GPU: " Layout.maximumWidth: parent.width height: paintedHeight size: 16 color: simplifiedUI.colors.text.white wrapMode: Text.Wrap + + Component.onCompleted: { + var gpu = JSON.parse(PlatformInfo.getGPU(0)); + var gpuModel = gpu.model; + if (gpuModel.length === 0) { + gpuModel = "Unknown"; + } + + text = "GPU: " + gpuModel; + } } HifiStylesUit.GraphikRegular { @@ -180,9 +200,11 @@ Flickable { width: 200 height: 32 text: "Copy to Clipboard" + temporaryText: "Copied!" onClicked: { Window.copyToClipboard(root.buildPlatformInfoTextToCopy()); + showTemporaryText(); } } } @@ -206,12 +228,29 @@ Flickable { textToCopy += "Computer Vendor/Model: " + computerVendor + "/" + computerModel + "\n"; textToCopy += "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + "\n"; textToCopy += "OS Type: " + PlatformInfo.getOperatingSystemType() + "\n"; - textToCopy += "CPU: " + PlatformInfo.getCPUBrand() + "\n"; + + var cpu = JSON.parse(PlatformInfo.getCPU(0)); + var cpuModel = cpu.model; + if (cpuModel.length === 0) { + cpuModel = "Unknown"; + } + + textToCopy += "CPU: " + cpuModel + "\n"; textToCopy += "# CPUs: " + PlatformInfo.getNumCPUs() + "\n"; textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n"; textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n"; - textToCopy += "GPU: " + PlatformInfo.getGraphicsCardType() + "\n"; - textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")); + + var gpu = JSON.parse(PlatformInfo.getGPU(0)); + var gpuModel = gpu.model; + if (gpuModel.length === 0) { + gpuModel = "Unknown"; + } + + textToCopy += "GPU: " + gpuModel + "\n"; + textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")) + "\n"; + + textToCopy += "\n**All Platform Info**\n"; + textToCopy += JSON.stringify(JSON.parse(PlatformInfo.getPlatform()), null, 4); return textToCopy; } diff --git a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Button.qml b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Button.qml index 313daab704..1d594a0d6d 100644 --- a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Button.qml +++ b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Button.qml @@ -16,6 +16,9 @@ import TabletScriptingInterface 1.0 Original.Button { id: root + // The two properties below are used when calling showTemporaryText() + property string originalText: "" + property string temporaryText: "" SimplifiedConstants.SimplifiedConstants { id: simplifiedUI @@ -103,4 +106,31 @@ Original.Button { horizontalAlignment: Text.AlignHCenter text: root.text } + + Timer { + id: showTemporaryTextTimer + interval: 1500 + repeat: false + running: false + + onTriggered: { + buttonText.text = root.originalText; + root.originalText = ""; + } + } + + function showTemporaryText() { + if (root.temporaryText === "") { + return; + } + + if (showTemporaryTextTimer.running) { + showTemporaryTextTimer.restart(); + return; + } + + root.originalText = buttonText.text; + buttonText.text = root.temporaryText; + showTemporaryTextTimer.start(); + } } From 541d45012a0677f65757e1e84add0654ba3b2872 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 24 Jun 2019 12:54:58 -0700 Subject: [PATCH 31/63] Move BlendshapePacking_avx2.cpp to shared --- .../{render-utils => shared}/src/avx2/BlendshapePacking_avx2.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libraries/{render-utils => shared}/src/avx2/BlendshapePacking_avx2.cpp (100%) diff --git a/libraries/render-utils/src/avx2/BlendshapePacking_avx2.cpp b/libraries/shared/src/avx2/BlendshapePacking_avx2.cpp similarity index 100% rename from libraries/render-utils/src/avx2/BlendshapePacking_avx2.cpp rename to libraries/shared/src/avx2/BlendshapePacking_avx2.cpp From 2322df5a5930f436fcf43389a906f97f638f71b0 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 24 Jun 2019 12:57:42 -0700 Subject: [PATCH 32/63] Add unit-test to validate AVX2 --- tests/shared/src/BlendshapePackingTests.cpp | 148 ++++++++++++++++++++ tests/shared/src/BlendshapePackingTests.h | 23 +++ 2 files changed, 171 insertions(+) create mode 100644 tests/shared/src/BlendshapePackingTests.cpp create mode 100644 tests/shared/src/BlendshapePackingTests.h diff --git a/tests/shared/src/BlendshapePackingTests.cpp b/tests/shared/src/BlendshapePackingTests.cpp new file mode 100644 index 0000000000..a751a5ca02 --- /dev/null +++ b/tests/shared/src/BlendshapePackingTests.cpp @@ -0,0 +1,148 @@ +// +// BlendshapePackingTests.cpp +// tests/shared/src +// +// Created by Ken Cooke on 6/24/19. +// Copyright 2019 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 "BlendshapePackingTests.h" + +#include + +#include + +#include +#include + +struct BlendshapeOffsetUnpacked { + glm::vec3 positionOffset; + glm::vec3 normalOffset; + glm::vec3 tangentOffset; +}; + +struct BlendshapeOffsetPacked { + glm::uvec4 packedPosNorTan; +}; + +QTEST_MAIN(BlendshapePackingTests) + +static void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uvec4& packed, const BlendshapeOffsetUnpacked& unpacked) { + float len = glm::compMax(glm::abs(unpacked.positionOffset)); + glm::vec3 normalizedPos(unpacked.positionOffset); + if (len > 0.0f) { + normalizedPos /= len; + } else { + len = 1.0f; + } + + packed = glm::uvec4( + glm::floatBitsToUint(len), + glm_packSnorm3x10_1x2(glm::vec4(normalizedPos, 0.0f)), + glm_packSnorm3x10_1x2(glm::vec4(unpacked.normalOffset, 0.0f)), + glm_packSnorm3x10_1x2(glm::vec4(unpacked.tangentOffset, 0.0f)) + ); +} + +static void packBlendshapeOffsets_ref(BlendshapeOffsetUnpacked* unpacked, BlendshapeOffsetPacked* packed, int size) { + for (int i = 0; i < size; ++i) { + packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked)); + ++unpacked; + ++packed; + } +} + +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__) +// +// Runtime CPU dispatch +// +#include + +void packBlendshapeOffsets_AVX2(float (*unpacked)[9], uint32_t (*packed)[4], int size); + +static void packBlendshapeOffsets(BlendshapeOffsetUnpacked* unpacked, BlendshapeOffsetPacked* packed, int size) { + static bool _cpuSupportsAVX2 = cpuSupportsAVX2(); + if (_cpuSupportsAVX2) { + static_assert(sizeof(BlendshapeOffsetUnpacked) == 9 * sizeof(float), "struct BlendshapeOffsetUnpacked size doesn't match."); + static_assert(sizeof(BlendshapeOffsetPacked) == 4 * sizeof(uint32_t), "struct BlendshapeOffsetPacked size doesn't match."); + packBlendshapeOffsets_AVX2((float(*)[9])unpacked, (uint32_t(*)[4])packed, size); + } else { + packBlendshapeOffsets_ref(unpacked, packed, size); + } +} + +#else // portable reference code +static auto& packBlendshapeOffsets = packBlendshapeOffsets_ref; +#endif + +void comparePacked(BlendshapeOffsetPacked& ref, BlendshapeOffsetPacked& tst) { + union i10i10i10i2 { + struct { + int x : 10; + int y : 10; + int z : 10; + int w : 2; + } data; + uint32_t pack; + } Ref[4], Tst[4]; + + for (int i = 0; i < 4; i++) { + Ref[i].pack = ref.packedPosNorTan[i]; + Tst[i].pack = tst.packedPosNorTan[i]; + } + + // allow 1 ULP due to rounding differences + QCOMPARE_WITH_ABS_ERROR(Tst[0].pack, Ref[0].pack, 1); + + QCOMPARE_WITH_ABS_ERROR(Tst[1].data.x, Ref[1].data.x, 1); + QCOMPARE_WITH_ABS_ERROR(Tst[1].data.y, Ref[1].data.y, 1); + QCOMPARE_WITH_ABS_ERROR(Tst[1].data.z, Ref[1].data.z, 1); + + QCOMPARE_WITH_ABS_ERROR(Tst[2].data.x, Ref[2].data.x, 1); + QCOMPARE_WITH_ABS_ERROR(Tst[2].data.y, Ref[2].data.y, 1); + QCOMPARE_WITH_ABS_ERROR(Tst[2].data.z, Ref[2].data.z, 1); + + QCOMPARE_WITH_ABS_ERROR(Tst[3].data.x, Ref[3].data.x, 1); + QCOMPARE_WITH_ABS_ERROR(Tst[3].data.y, Ref[3].data.y, 1); + QCOMPARE_WITH_ABS_ERROR(Tst[3].data.z, Ref[3].data.z, 1); +} + +void BlendshapePackingTests::testAVX2() { + + for (int numBlendshapeOffsets = 0; numBlendshapeOffsets < 4096; ++numBlendshapeOffsets) { + + std::vector unpackedBlendshapeOffsets(numBlendshapeOffsets); + std::vector packedBlendshapeOffsets1(numBlendshapeOffsets); + std::vector packedBlendshapeOffsets2(numBlendshapeOffsets); + + // init test data + if (numBlendshapeOffsets > 0) { + unpackedBlendshapeOffsets[0] = { + glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), + }; + } + for (int i = 1; i < numBlendshapeOffsets; ++i) { + unpackedBlendshapeOffsets[i] = { + glm::linearRand(glm::vec3(-2.0f, -2.0f, -2.0f), glm::vec3(2.0f, 2.0f, 2.0f)), + glm::linearRand(glm::vec3(-2.0f, -2.0f, -2.0f), glm::vec3(2.0f, 2.0f, 2.0f)), + glm::linearRand(glm::vec3(-2.0f, -2.0f, -2.0f), glm::vec3(2.0f, 2.0f, 2.0f)), + }; + } + + // ref version + packBlendshapeOffsets_ref(unpackedBlendshapeOffsets.data(), packedBlendshapeOffsets1.data(), numBlendshapeOffsets); + + // AVX2 version, if supported by CPU + packBlendshapeOffsets(unpackedBlendshapeOffsets.data(), packedBlendshapeOffsets2.data(), numBlendshapeOffsets); + + // verify + for (int i = 0; i < numBlendshapeOffsets; ++i) { + auto ref = packedBlendshapeOffsets1.at(i); + auto tst = packedBlendshapeOffsets2.at(i); + comparePacked(ref, tst); + } + } +} diff --git a/tests/shared/src/BlendshapePackingTests.h b/tests/shared/src/BlendshapePackingTests.h new file mode 100644 index 0000000000..d6d0ef8b10 --- /dev/null +++ b/tests/shared/src/BlendshapePackingTests.h @@ -0,0 +1,23 @@ +// +// BlendshapePackingTests.h +// tests/shared/src +// +// Created by Ken Cooke on 6/24/19. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_BlendshapePackingTests_h +#define hifi_BlendshapePackingTests_h + +#include + +class BlendshapePackingTests : public QObject { + Q_OBJECT +private slots: + void testAVX2(); +}; + +#endif // hifi_BlendshapePackingTests_h From aefa43bd116599a458b6cac467af42b9e7924cd7 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 24 Jun 2019 13:02:28 -0700 Subject: [PATCH 33/63] Prevent duplicates from accumulating in EntityTree::_needsParentFixup --- libraries/entities/src/EntityTree.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index dbc347631d..dca3ac595a 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2121,9 +2121,10 @@ void EntityTree::fixupNeedsParentFixups() { _needsParentFixup.clear(); } + std::unordered_set seenEntityIds; QMutableVectorIterator iter(entitiesToFixup); while (iter.hasNext()) { - EntityItemWeakPointer entityWP = iter.next(); + const auto& entityWP = iter.next(); EntityItemPointer entity = entityWP.lock(); if (!entity) { // entity was deleted before we found its parent @@ -2131,6 +2132,17 @@ void EntityTree::fixupNeedsParentFixups() { continue; } + const auto id = entity->getID(); + // BUGZ-771 some entities seem to never be removed by the below logic and further seem to accumulate dupes within the _needsParentFixup list + // This block ensures that duplicates are removed from entitiesToFixup before it's re-appended to _needsParentFixup + if (0 != seenEntityIds.count(id)) { + // Entity was duplicated inside entitiesToFixup + iter.remove(); + continue; + } + + seenEntityIds.insert(id); + entity->requiresRecalcBoxes(); bool queryAACubeSuccess { false }; bool maxAACubeSuccess { false }; From 6aca2fcf076303758244b41c33c401bd5e50bb5f Mon Sep 17 00:00:00 2001 From: RebeccaStankus Date: Mon, 24 Jun 2019 14:01:51 -0700 Subject: [PATCH 34/63] Working on new file structure --- script-archive/light_modifier/README.md | 2 +- .../light_modifier/lightModifier.js | 4 +-- scripts/defaultScripts.js | 4 +-- .../assets/data/createAppTooltips.json | 0 scripts/system/{ => create}/edit.js | 26 +++++++++---------- .../entityList}/entityList.js | 2 +- .../entityList}/html/entityList.html | 12 ++++----- .../entityList}/html/js/entityList.js | 0 .../html/js/entityListContextMenu.js | 0 .../entityList}/html/js/listView.js | 0 .../{ => entityList/qml}/EditEntityList.qml | 2 +- .../{ => entityList/qml}/EntityList.qml | 2 +- .../html/entityProperties.html | 12 ++++----- .../html/js/createAppTooltip.js | 0 .../html/js/draggableNumber.js | 0 .../html/js/entityProperties.js | 0 .../html/js/underscore-min.js | 0 .../entitySelectionTool.js | 6 ++--- .../{ => create}/modules/createWindow.js | 0 .../modules/entityShapeVisualizer.js | 0 scripts/system/create/{ => qml}/Edit.qml | 0 .../system/create/{ => qml}/EditTabButton.qml | 0 .../system/create/{ => qml}/EditTabView.qml | 24 ++++++++--------- scripts/system/create/{ => qml}/EditTools.qml | 0 .../create/{ => qml}/EditToolsTabView.qml | 22 ++++++++-------- .../create/{ => qml}/NewEntityButton.qml | 0 .../create/{ => qml}/NewMaterialDialog.qml | 0 .../create/{ => qml}/NewMaterialWindow.qml | 0 .../create/{ => qml}/NewModelDialog.qml | 0 .../create/{ => qml}/NewModelWindow.qml | 0 .../icons}/126-material-01.svg | 0 .../icons}/20-text-01.svg | 0 .../icons}/21-cube-01.svg | 0 .../icons}/22-sphere-01.svg | 0 .../icons}/23-zone-01.svg | 0 .../icons}/24-light-01.svg | 0 .../icons}/25-web-1-01.svg | 0 .../icons}/90-particles-01.svg | 0 .../icons}/94-model-01.svg | 0 .../{create-icons => qml/icons}/image.svg | 0 scripts/system/libraries/EditEntityList.qml | 12 --------- .../libraries/{ => gridTool}/gridTool.js | 0 .../gridTool}/html/gridControls.html | 12 ++++----- .../gridTool}/html/js/colpick.js | 0 .../gridTool}/html/js/gridControls.js | 0 scripts/system/marketplaces/marketplaces.js | 2 +- 46 files changed, 66 insertions(+), 78 deletions(-) rename scripts/system/{ => create}/assets/data/createAppTooltips.json (100%) rename scripts/system/{ => create}/edit.js (99%) rename scripts/system/{libraries => create/entityList}/entityList.js (99%) rename scripts/system/{ => create/entityList}/html/entityList.html (89%) rename scripts/system/{ => create/entityList}/html/js/entityList.js (100%) rename scripts/system/{ => create/entityList}/html/js/entityListContextMenu.js (100%) rename scripts/system/{ => create/entityList}/html/js/listView.js (100%) rename scripts/system/create/{ => entityList/qml}/EditEntityList.qml (82%) rename scripts/system/create/{ => entityList/qml}/EntityList.qml (58%) rename scripts/system/{ => create/entityProperties}/html/entityProperties.html (78%) rename scripts/system/{ => create/entityProperties}/html/js/createAppTooltip.js (100%) rename scripts/system/{ => create/entityProperties}/html/js/draggableNumber.js (100%) rename scripts/system/{ => create/entityProperties}/html/js/entityProperties.js (100%) rename scripts/system/{ => create/entityProperties}/html/js/underscore-min.js (100%) rename scripts/system/{libraries => create/entitySelectionTool}/entitySelectionTool.js (99%) rename scripts/system/{ => create}/modules/createWindow.js (100%) rename scripts/system/{ => create}/modules/entityShapeVisualizer.js (100%) rename scripts/system/create/{ => qml}/Edit.qml (100%) rename scripts/system/create/{ => qml}/EditTabButton.qml (100%) rename scripts/system/create/{ => qml}/EditTabView.qml (93%) rename scripts/system/create/{ => qml}/EditTools.qml (100%) rename scripts/system/create/{ => qml}/EditToolsTabView.qml (93%) rename scripts/system/create/{ => qml}/NewEntityButton.qml (100%) rename scripts/system/create/{ => qml}/NewMaterialDialog.qml (100%) rename scripts/system/create/{ => qml}/NewMaterialWindow.qml (100%) rename scripts/system/create/{ => qml}/NewModelDialog.qml (100%) rename scripts/system/create/{ => qml}/NewModelWindow.qml (100%) rename scripts/system/create/{create-icons => qml/icons}/126-material-01.svg (100%) rename scripts/system/create/{create-icons => qml/icons}/20-text-01.svg (100%) rename scripts/system/create/{create-icons => qml/icons}/21-cube-01.svg (100%) rename scripts/system/create/{create-icons => qml/icons}/22-sphere-01.svg (100%) rename scripts/system/create/{create-icons => qml/icons}/23-zone-01.svg (100%) rename scripts/system/create/{create-icons => qml/icons}/24-light-01.svg (100%) rename scripts/system/create/{create-icons => qml/icons}/25-web-1-01.svg (100%) rename scripts/system/create/{create-icons => qml/icons}/90-particles-01.svg (100%) rename scripts/system/create/{create-icons => qml/icons}/94-model-01.svg (100%) rename scripts/system/create/{create-icons => qml/icons}/image.svg (100%) delete mode 100644 scripts/system/libraries/EditEntityList.qml rename scripts/system/libraries/{ => gridTool}/gridTool.js (100%) rename scripts/system/{ => libraries/gridTool}/html/gridControls.html (85%) rename scripts/system/{ => libraries/gridTool}/html/js/colpick.js (100%) rename scripts/system/{ => libraries/gridTool}/html/js/gridControls.js (100%) diff --git a/script-archive/light_modifier/README.md b/script-archive/light_modifier/README.md index f23bd25dda..d78fe3ef41 100644 --- a/script-archive/light_modifier/README.md +++ b/script-archive/light_modifier/README.md @@ -18,7 +18,7 @@ When you run the lightLoader.js script, several scripts will be loaded: - visiblePanel.js (the transparent panel) - closeButton.js (for closing the ui) - ../libraries/lightOverlayManager.js (shows 2d overlays for lights in the world) -- ../libraries/entitySelectionTool.js (visualizes volume of the lights) +- ../../scripts/system/create/entitySelectionTool/entitySelectionTool.js (visualizes volume of the lights) Current sliders are (top to bottom): red diff --git a/script-archive/light_modifier/lightModifier.js b/script-archive/light_modifier/lightModifier.js index 0c691e2b2e..1080777721 100644 --- a/script-archive/light_modifier/lightModifier.js +++ b/script-archive/light_modifier/lightModifier.js @@ -33,8 +33,8 @@ var PARENT_SCRIPT_URL = Script.resolvePath('lightParent.js?' + Math.random(0 - 1 if (SHOW_OVERLAYS === true) { - Script.include('../libraries/gridTool.js'); - Script.include('../libraries/entitySelectionTool.js?' + Math.random(0 - 100)); + Script.include('../../libraries/gridTool/gridTool.js'); + Script.include('../../scripts/system/create/entitySelectionTool/entitySelectionTool.js?' + Math.random(0 - 100)); Script.include('../libraries/lightOverlayManager.js'); var grid = Grid(); diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index e392680df9..607ee3165b 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -27,7 +27,7 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/marketplaces/marketplaces.js", "system/notifications.js", "system/commerce/wallet.js", - "system/edit.js", + "system/create/edit.js", "system/dialTone.js", "system/firstPersonHMD.js", "system/tablet-ui/tabletUI.js", @@ -36,7 +36,7 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/audioMuteOverlay.js" ]; var DEFAULT_SCRIPTS_SEPARATE = [ - "system/controllers/controllerScripts.js", + "system/controllers/controllerScripts.js" //"system/chat.js" ]; diff --git a/scripts/system/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json similarity index 100% rename from scripts/system/assets/data/createAppTooltips.json rename to scripts/system/create/assets/data/createAppTooltips.json diff --git a/scripts/system/edit.js b/scripts/system/create/edit.js similarity index 99% rename from scripts/system/edit.js rename to scripts/system/create/edit.js index cf99f3a618..4c13a70a5d 100644 --- a/scripts/system/edit.js +++ b/scripts/system/create/edit.js @@ -24,16 +24,16 @@ var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton"; var CONTROLLER_MAPPING_NAME = "com.highfidelity.editMode"; Script.include([ - "libraries/stringHelpers.js", - "libraries/dataViewHelpers.js", - "libraries/progressDialog.js", - "libraries/entitySelectionTool.js", - "libraries/ToolTip.js", - "libraries/entityCameraTool.js", - "libraries/gridTool.js", - "libraries/entityList.js", - "libraries/utils.js", - "libraries/entityIconOverlayManager.js" + "../libraries/stringHelpers.js", + "../libraries/dataViewHelpers.js", + "../libraries/progressDialog.js", + "../libraries/ToolTip.js", + "../libraries/entityCameraTool.js", + "../libraries/utils.js", + "../libraries/entityIconOverlayManager.js", + "../libraries/gridTool/gridTool.js", + "entityList/entityList.js", + "entitySelectionTool/entitySelectionTool.js" ]); var CreateWindow = Script.require('./modules/createWindow.js'); @@ -45,7 +45,7 @@ var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942; var DEFAULT_IMAGE = "https://hifi-content.s3.amazonaws.com/DomainContent/production/no-image.jpg"; var createToolsWindow = new CreateWindow( - Script.resolvePath("create/EditTools.qml"), + Script.resolvePath("./qml/EditTools.qml"), 'Create Tools', 'com.highfidelity.create.createToolsWindow', function () { @@ -174,7 +174,7 @@ var IMPORTING_SVO_OVERLAY_HEIGHT = 30; var IMPORTING_SVO_OVERLAY_MARGIN = 5; var IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34; var importingSVOImageOverlay = Overlays.addOverlay("image", { - imageURL: Script.resolvePath("assets") + "/images/hourglass.svg", + imageURL: Script.resolvePath("../assets/images/hourglass.svg"), width: 20, height: 20, alpha: 1.0, @@ -812,7 +812,7 @@ var toolBar = (function () { tablet.screenChanged.connect(function (type, url) { var isGoingToHomescreenOnDesktop = (!shouldUseEditTabletApp() && (url === 'hifi/tablet/TabletHome.qml' || url === '')); - if (isActive && (type !== "QML" || url !== Script.resolvePath("create/Edit.qml")) && !isGoingToHomescreenOnDesktop) { + if (isActive && (type !== "QML" || url !== Script.resolvePath("./qml/Edit.qml")) && !isGoingToHomescreenOnDesktop) { that.setActive(false); } }); diff --git a/scripts/system/libraries/entityList.js b/scripts/system/create/entityList/entityList.js similarity index 99% rename from scripts/system/libraries/entityList.js rename to scripts/system/create/entityList/entityList.js index 585e4e06a5..06e100f457 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/create/entityList/entityList.js @@ -37,7 +37,7 @@ EntityListTool = function(shouldUseEditTabletApp) { var ENTITY_LIST_WIDTH = 495; var MAX_DEFAULT_CREATE_TOOLS_HEIGHT = 778; var entityListWindow = new CreateWindow( - Script.resolvePath("../create/EditEntityList.qml"), + Script.resolvePath("./qml/EditEntityList.qml"), 'Entity List', 'com.highfidelity.create.entityListWindow', function () { diff --git a/scripts/system/html/entityList.html b/scripts/system/create/entityList/html/entityList.html similarity index 89% rename from scripts/system/html/entityList.html rename to scripts/system/create/entityList/html/entityList.html index 986e5c09b0..3e17a66df5 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/create/entityList/html/entityList.html @@ -11,15 +11,15 @@ Entity List - + - - - + + + + + - - diff --git a/scripts/system/html/js/entityList.js b/scripts/system/create/entityList/html/js/entityList.js similarity index 100% rename from scripts/system/html/js/entityList.js rename to scripts/system/create/entityList/html/js/entityList.js diff --git a/scripts/system/html/js/entityListContextMenu.js b/scripts/system/create/entityList/html/js/entityListContextMenu.js similarity index 100% rename from scripts/system/html/js/entityListContextMenu.js rename to scripts/system/create/entityList/html/js/entityListContextMenu.js diff --git a/scripts/system/html/js/listView.js b/scripts/system/create/entityList/html/js/listView.js similarity index 100% rename from scripts/system/html/js/listView.js rename to scripts/system/create/entityList/html/js/listView.js diff --git a/scripts/system/create/EditEntityList.qml b/scripts/system/create/entityList/qml/EditEntityList.qml similarity index 82% rename from scripts/system/create/EditEntityList.qml rename to scripts/system/create/entityList/qml/EditEntityList.qml index 94935c7bb5..1d5beb9914 100644 --- a/scripts/system/create/EditEntityList.qml +++ b/scripts/system/create/entityList/qml/EditEntityList.qml @@ -10,7 +10,7 @@ import stylesUit 1.0 WebView { id: entityListToolWebView - url: Paths.defaultScripts + "/system/html/entityList.html" + url: Qt.resolvedUrl("../html/entityList.html") enabled: true blurOnCtrlShift: false } diff --git a/scripts/system/create/EntityList.qml b/scripts/system/create/entityList/qml/EntityList.qml similarity index 58% rename from scripts/system/create/EntityList.qml rename to scripts/system/create/entityList/qml/EntityList.qml index 2f8a8863be..a70fc6d15d 100644 --- a/scripts/system/create/EntityList.qml +++ b/scripts/system/create/entityList/qml/EntityList.qml @@ -1,6 +1,6 @@ WebView { id: entityListToolWebView - url: Paths.defaultScripts + "/system/html/entityList.html" + url: QT.resolvedURL("../html/entityList.html") enabled: true blurOnCtrlShift: false } diff --git a/scripts/system/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html similarity index 78% rename from scripts/system/html/entityProperties.html rename to scripts/system/create/entityProperties/html/entityProperties.html index 67f03a33a2..7d18b9898c 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -12,19 +12,19 @@ Properties - - + + - - + + + + - - diff --git a/scripts/system/html/js/createAppTooltip.js b/scripts/system/create/entityProperties/html/js/createAppTooltip.js similarity index 100% rename from scripts/system/html/js/createAppTooltip.js rename to scripts/system/create/entityProperties/html/js/createAppTooltip.js diff --git a/scripts/system/html/js/draggableNumber.js b/scripts/system/create/entityProperties/html/js/draggableNumber.js similarity index 100% rename from scripts/system/html/js/draggableNumber.js rename to scripts/system/create/entityProperties/html/js/draggableNumber.js diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js similarity index 100% rename from scripts/system/html/js/entityProperties.js rename to scripts/system/create/entityProperties/html/js/entityProperties.js diff --git a/scripts/system/html/js/underscore-min.js b/scripts/system/create/entityProperties/html/js/underscore-min.js similarity index 100% rename from scripts/system/html/js/underscore-min.js rename to scripts/system/create/entityProperties/html/js/underscore-min.js diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/create/entitySelectionTool/entitySelectionTool.js similarity index 99% rename from scripts/system/libraries/entitySelectionTool.js rename to scripts/system/create/entitySelectionTool/entitySelectionTool.js index 3fdc1d6652..9c993d6d73 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/create/entitySelectionTool/entitySelectionTool.js @@ -21,9 +21,9 @@ const SPACE_WORLD = "world"; const HIGHLIGHT_LIST_NAME = "editHandleHighlightList"; Script.include([ - "./controllers.js", - "./controllerDispatcherUtils.js", - "./utils.js" + "../../libraries/controllers.js", + "../../libraries/controllerDispatcherUtils.js", + "../../libraries/utils.js" ]); diff --git a/scripts/system/modules/createWindow.js b/scripts/system/create/modules/createWindow.js similarity index 100% rename from scripts/system/modules/createWindow.js rename to scripts/system/create/modules/createWindow.js diff --git a/scripts/system/modules/entityShapeVisualizer.js b/scripts/system/create/modules/entityShapeVisualizer.js similarity index 100% rename from scripts/system/modules/entityShapeVisualizer.js rename to scripts/system/create/modules/entityShapeVisualizer.js diff --git a/scripts/system/create/Edit.qml b/scripts/system/create/qml/Edit.qml similarity index 100% rename from scripts/system/create/Edit.qml rename to scripts/system/create/qml/Edit.qml diff --git a/scripts/system/create/EditTabButton.qml b/scripts/system/create/qml/EditTabButton.qml similarity index 100% rename from scripts/system/create/EditTabButton.qml rename to scripts/system/create/qml/EditTabButton.qml diff --git a/scripts/system/create/EditTabView.qml b/scripts/system/create/qml/EditTabView.qml similarity index 93% rename from scripts/system/create/EditTabView.qml rename to scripts/system/create/qml/EditTabView.qml index 7e8789487c..ad6c11c348 100644 --- a/scripts/system/create/EditTabView.qml +++ b/scripts/system/create/qml/EditTabView.qml @@ -72,7 +72,7 @@ TabBar { NewEntityButton { - icon: "create-icons/94-model-01.svg" + icon: "icons/94-model-01.svg" text: "MODEL" onClicked: { editRoot.sendToScript({ @@ -84,7 +84,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/21-cube-01.svg" + icon: "icons/21-cube-01.svg" text: "SHAPE" onClicked: { editRoot.sendToScript({ @@ -96,7 +96,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/24-light-01.svg" + icon: "icons/24-light-01.svg" text: "LIGHT" onClicked: { editRoot.sendToScript({ @@ -108,7 +108,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/20-text-01.svg" + icon: "icons/20-text-01.svg" text: "TEXT" onClicked: { editRoot.sendToScript({ @@ -120,7 +120,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/image.svg" + icon: "icons/image.svg" text: "IMAGE" onClicked: { editRoot.sendToScript({ @@ -132,7 +132,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/25-web-1-01.svg" + icon: "icons/25-web-1-01.svg" text: "WEB" onClicked: { editRoot.sendToScript({ @@ -144,7 +144,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/23-zone-01.svg" + icon: "icons/23-zone-01.svg" text: "ZONE" onClicked: { editRoot.sendToScript({ @@ -156,7 +156,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/90-particles-01.svg" + icon: "icons/90-particles-01.svg" text: "PARTICLE" onClicked: { editRoot.sendToScript({ @@ -168,7 +168,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/126-material-01.svg" + icon: "icons/126-material-01.svg" text: "MATERIAL" onClicked: { editRoot.sendToScript({ @@ -231,7 +231,7 @@ TabBar { property Component visualItem: Component { WebView { id: entityListToolWebView - url: Paths.defaultScripts + "/system/html/entityList.html" + url: Qt.resolvedUrl("../entityList/html/entityList.html") enabled: true blurOnCtrlShift: false } @@ -247,7 +247,7 @@ TabBar { property Component visualItem: Component { WebView { id: entityPropertiesWebView - url: Paths.defaultScripts + "/system/html/entityProperties.html" + url: Paths.defaultScripts + "/entityProperties/html/entityProperties.html" enabled: true blurOnCtrlShift: false } @@ -263,7 +263,7 @@ TabBar { property Component visualItem: Component { WebView { id: gridControlsWebView - url: Paths.defaultScripts + "/system/html/gridControls.html" + url: Paths.defaultScripts + "../../libraries/gridTool/html/gridControls.html" enabled: true blurOnCtrlShift: false } diff --git a/scripts/system/create/EditTools.qml b/scripts/system/create/qml/EditTools.qml similarity index 100% rename from scripts/system/create/EditTools.qml rename to scripts/system/create/qml/EditTools.qml diff --git a/scripts/system/create/EditToolsTabView.qml b/scripts/system/create/qml/EditToolsTabView.qml similarity index 93% rename from scripts/system/create/EditToolsTabView.qml rename to scripts/system/create/qml/EditToolsTabView.qml index a333acc586..53ee9e6e1e 100644 --- a/scripts/system/create/EditToolsTabView.qml +++ b/scripts/system/create/qml/EditToolsTabView.qml @@ -78,7 +78,7 @@ TabBar { NewEntityButton { - icon: "create-icons/94-model-01.svg" + icon: "icons/94-model-01.svg" text: "MODEL" onClicked: { editRoot.sendToScript({ @@ -90,7 +90,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/21-cube-01.svg" + icon: "icons/21-cube-01.svg" text: "SHAPE" onClicked: { editRoot.sendToScript({ @@ -102,7 +102,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/24-light-01.svg" + icon: "icons/24-light-01.svg" text: "LIGHT" onClicked: { editRoot.sendToScript({ @@ -114,7 +114,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/20-text-01.svg" + icon: "icons/20-text-01.svg" text: "TEXT" onClicked: { editRoot.sendToScript({ @@ -126,7 +126,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/image.svg" + icon: "icons/image.svg" text: "IMAGE" onClicked: { editRoot.sendToScript({ @@ -138,7 +138,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/25-web-1-01.svg" + icon: "icons/25-web-1-01.svg" text: "WEB" onClicked: { editRoot.sendToScript({ @@ -150,7 +150,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/23-zone-01.svg" + icon: "icons/23-zone-01.svg" text: "ZONE" onClicked: { editRoot.sendToScript({ @@ -162,7 +162,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/90-particles-01.svg" + icon: "icons/90-particles-01.svg" text: "PARTICLE" onClicked: { editRoot.sendToScript({ @@ -174,7 +174,7 @@ TabBar { } NewEntityButton { - icon: "create-icons/126-material-01.svg" + icon: "icons/126-material-01.svg" text: "MATERIAL" onClicked: { editRoot.sendToScript({ @@ -237,7 +237,7 @@ TabBar { property Component visualItem: Component { WebView { id: entityPropertiesWebView - url: Paths.defaultScripts + "/system/html/entityProperties.html" + url: Qt.resolvedUrl("../entityProperties/html/entityProperties.html") enabled: true blurOnCtrlShift: false } @@ -253,7 +253,7 @@ TabBar { property Component visualItem: Component { WebView { id: gridControlsWebView - url: Paths.defaultScripts + "/system/html/gridControls.html" + url: Qt.resolvedURL("../gridTool/html/gridControls.html") enabled: true blurOnCtrlShift: false } diff --git a/scripts/system/create/NewEntityButton.qml b/scripts/system/create/qml/NewEntityButton.qml similarity index 100% rename from scripts/system/create/NewEntityButton.qml rename to scripts/system/create/qml/NewEntityButton.qml diff --git a/scripts/system/create/NewMaterialDialog.qml b/scripts/system/create/qml/NewMaterialDialog.qml similarity index 100% rename from scripts/system/create/NewMaterialDialog.qml rename to scripts/system/create/qml/NewMaterialDialog.qml diff --git a/scripts/system/create/NewMaterialWindow.qml b/scripts/system/create/qml/NewMaterialWindow.qml similarity index 100% rename from scripts/system/create/NewMaterialWindow.qml rename to scripts/system/create/qml/NewMaterialWindow.qml diff --git a/scripts/system/create/NewModelDialog.qml b/scripts/system/create/qml/NewModelDialog.qml similarity index 100% rename from scripts/system/create/NewModelDialog.qml rename to scripts/system/create/qml/NewModelDialog.qml diff --git a/scripts/system/create/NewModelWindow.qml b/scripts/system/create/qml/NewModelWindow.qml similarity index 100% rename from scripts/system/create/NewModelWindow.qml rename to scripts/system/create/qml/NewModelWindow.qml diff --git a/scripts/system/create/create-icons/126-material-01.svg b/scripts/system/create/qml/icons/126-material-01.svg similarity index 100% rename from scripts/system/create/create-icons/126-material-01.svg rename to scripts/system/create/qml/icons/126-material-01.svg diff --git a/scripts/system/create/create-icons/20-text-01.svg b/scripts/system/create/qml/icons/20-text-01.svg similarity index 100% rename from scripts/system/create/create-icons/20-text-01.svg rename to scripts/system/create/qml/icons/20-text-01.svg diff --git a/scripts/system/create/create-icons/21-cube-01.svg b/scripts/system/create/qml/icons/21-cube-01.svg similarity index 100% rename from scripts/system/create/create-icons/21-cube-01.svg rename to scripts/system/create/qml/icons/21-cube-01.svg diff --git a/scripts/system/create/create-icons/22-sphere-01.svg b/scripts/system/create/qml/icons/22-sphere-01.svg similarity index 100% rename from scripts/system/create/create-icons/22-sphere-01.svg rename to scripts/system/create/qml/icons/22-sphere-01.svg diff --git a/scripts/system/create/create-icons/23-zone-01.svg b/scripts/system/create/qml/icons/23-zone-01.svg similarity index 100% rename from scripts/system/create/create-icons/23-zone-01.svg rename to scripts/system/create/qml/icons/23-zone-01.svg diff --git a/scripts/system/create/create-icons/24-light-01.svg b/scripts/system/create/qml/icons/24-light-01.svg similarity index 100% rename from scripts/system/create/create-icons/24-light-01.svg rename to scripts/system/create/qml/icons/24-light-01.svg diff --git a/scripts/system/create/create-icons/25-web-1-01.svg b/scripts/system/create/qml/icons/25-web-1-01.svg similarity index 100% rename from scripts/system/create/create-icons/25-web-1-01.svg rename to scripts/system/create/qml/icons/25-web-1-01.svg diff --git a/scripts/system/create/create-icons/90-particles-01.svg b/scripts/system/create/qml/icons/90-particles-01.svg similarity index 100% rename from scripts/system/create/create-icons/90-particles-01.svg rename to scripts/system/create/qml/icons/90-particles-01.svg diff --git a/scripts/system/create/create-icons/94-model-01.svg b/scripts/system/create/qml/icons/94-model-01.svg similarity index 100% rename from scripts/system/create/create-icons/94-model-01.svg rename to scripts/system/create/qml/icons/94-model-01.svg diff --git a/scripts/system/create/create-icons/image.svg b/scripts/system/create/qml/icons/image.svg similarity index 100% rename from scripts/system/create/create-icons/image.svg rename to scripts/system/create/qml/icons/image.svg diff --git a/scripts/system/libraries/EditEntityList.qml b/scripts/system/libraries/EditEntityList.qml deleted file mode 100644 index 4fc5ff19ef..0000000000 --- a/scripts/system/libraries/EditEntityList.qml +++ /dev/null @@ -1,12 +0,0 @@ -import QtQuick 2.7 -import QtQuick.Controls 2.2 -import QtWebChannel 1.0 -import QtGraphicalEffects 1.0 -import "qrc:///qml/controls" as HifiControls - -HifiControls.WebView { - id: entityListToolWebView - url: Qt.resolvedUrl("../html/entityList.html") - enabled: true - blurOnCtrlShift: false -} diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool/gridTool.js similarity index 100% rename from scripts/system/libraries/gridTool.js rename to scripts/system/libraries/gridTool/gridTool.js diff --git a/scripts/system/html/gridControls.html b/scripts/system/libraries/gridTool/html/gridControls.html similarity index 85% rename from scripts/system/html/gridControls.html rename to scripts/system/libraries/gridTool/html/gridControls.html index 8d6ee34bc0..d6c56033dd 100644 --- a/scripts/system/html/gridControls.html +++ b/scripts/system/libraries/gridTool/html/gridControls.html @@ -9,14 +9,14 @@ --> - - - + + + - - - + + + diff --git a/scripts/system/html/js/colpick.js b/scripts/system/libraries/gridTool/html/js/colpick.js similarity index 100% rename from scripts/system/html/js/colpick.js rename to scripts/system/libraries/gridTool/html/js/colpick.js diff --git a/scripts/system/html/js/gridControls.js b/scripts/system/libraries/gridTool/html/js/gridControls.js similarity index 100% rename from scripts/system/html/js/gridControls.js rename to scripts/system/libraries/gridTool/html/js/gridControls.js diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 38287e3af3..5c7623066b 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -17,7 +17,7 @@ var selectionDisplay = null; // for gridTool.js to ignore (function () { // BEGIN LOCAL_SCOPE var AppUi = Script.require('appUi'); -Script.include("/~/system/libraries/gridTool.js"); +Script.include("/~/system/libraries/gridTool/gridTool.js"); Script.include("/~/system/libraries/connectionUtils.js"); Script.include("/~/system/libraries/accountUtils.js"); From 3c0c1413db22c19dc6bb77b733d69df46ca76f74 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Mon, 24 Jun 2019 14:12:25 -0700 Subject: [PATCH 35/63] fix apple build --- libraries/platform/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/platform/CMakeLists.txt b/libraries/platform/CMakeLists.txt index 70f3157e1e..55203d45a4 100644 --- a/libraries/platform/CMakeLists.txt +++ b/libraries/platform/CMakeLists.txt @@ -5,3 +5,11 @@ link_hifi_libraries(shared) GroupSources("src") target_json() + +if (APPLE) + # link in required OS X frameworks and include the right GL headers + find_library(OpenGL OpenGL) + find_library(AppKit AppKit) + + target_link_libraries(${TARGET_NAME} ${OpenGL} ${AppKit}) +endif () From 9ae67c15b233f873b50ff3e1235054283803bbc3 Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Mon, 24 Jun 2019 14:27:07 -0700 Subject: [PATCH 36/63] Use old API to launch tasks on all versions of macOS --- launchers/darwin/src/Interface.m | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/launchers/darwin/src/Interface.m b/launchers/darwin/src/Interface.m index b007e7faa5..d02b66b581 100644 --- a/launchers/darwin/src/Interface.m +++ b/launchers/darwin/src/Interface.m @@ -23,24 +23,14 @@ NSLog(@"calling interface at %@", self->pathTo); - if (@available(macOS 10.13, *)) { - NSError *error = nil; - if (![interface launchAndReturnError:&error]) { - *outError = [NSError errorWithDomain:@"interface" - code:-1 - userInfo:@{NSUnderlyingErrorKey: error}]; - return 0; - } - } else { - NSError *error = nil; - [interface launch]; - [interface waitUntilExit]; - if (0 != [interface terminationStatus]) { - *outError = [NSError errorWithDomain:@"interface" - code:-1 - userInfo:@{NSUnderlyingErrorKey: error}]; - return 0; - } + NSError *error = nil; + [interface launch]; + [interface waitUntilExit]; + if (0 != [interface terminationStatus]) { + *outError = [NSError errorWithDomain:@"interface" + code:-1 + userInfo:@{NSUnderlyingErrorKey: error}]; + return 0; } NSFileHandle * fh = [standardOut fileHandleForReading]; From c605c2917f1c7a60ec447980bd82094269b6d301 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 24 Jun 2019 11:04:01 -0700 Subject: [PATCH 37/63] trying to fix entity tree renderer performance --- .../src/EntityTreeRenderer.cpp | 52 ++++++++----------- .../src/EntityTreeRenderer.h | 2 +- libraries/shared/src/PrioritySortUtil.h | 2 +- 3 files changed, 24 insertions(+), 32 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 5ac6e4f642..5cb7b89de5 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -207,7 +207,7 @@ void EntityTreeRenderer::stopDomainAndNonOwnedEntities() { if (entityItem && !entityItem->getScript().isEmpty()) { if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) { - if (entityItem->contains(_avatarPosition)) { + if (_currentEntitiesInside.contains(entityID)) { _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); } _entitiesScriptEngine->unloadEntityScript(entityID, true); @@ -222,6 +222,7 @@ void EntityTreeRenderer::clearDomainAndNonOwnedEntities() { auto sessionUUID = getTree()->getMyAvatarSessionUUID(); std::unordered_map savedEntities; + std::unordered_set savedRenderables; // remove all entities from the scene auto scene = _viewState->getMain3DScene(); if (scene) { @@ -232,11 +233,12 @@ void EntityTreeRenderer::clearDomainAndNonOwnedEntities() { fadeOutRenderable(renderer); } else { savedEntities[entry.first] = entry.second; + savedRenderables.insert(entry.second); } } } - _renderablesToUpdate = savedEntities; + _renderablesToUpdate = savedRenderables; _entitiesInScene = savedEntities; if (_layeredZones.clearDomainAndNonOwnedZones(sessionUUID)) { @@ -389,13 +391,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene PerformanceTimer pt("change"); std::unordered_set changedEntities; _changedEntitiesGuard.withWriteLock([&] { -#if 0 - // FIXME Weird build failure in latest VC update that fails to compile when using std::swap changedEntities.swap(_changedEntities); -#else - changedEntities.insert(_changedEntities.begin(), _changedEntities.end()); - _changedEntities.clear(); -#endif }); { @@ -404,7 +400,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene auto renderable = renderableForEntityId(entityId); if (renderable) { // only add valid renderables _renderablesToUpdate - _renderablesToUpdate.insert({ entityId, renderable }); + _renderablesToUpdate.insert(renderable); } } } @@ -414,8 +410,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene // we expect to update all renderables within available time budget PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size()); uint64_t updateStart = usecTimestampNow(); - for (const auto& entry : _renderablesToUpdate) { - const auto& renderable = entry.second; + for (const auto& renderable : _renderablesToUpdate) { assert(renderable); // only valid renderables are added to _renderablesToUpdate renderable->updateInScene(scene, transaction); } @@ -424,8 +419,8 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene // compute average per-renderable update cost float cost = (float)(usecTimestampNow() - updateStart) / (float)(numRenderables); - const float blend = 0.1f; - _avgRenderableUpdateCost = (1.0f - blend) * _avgRenderableUpdateCost + blend * cost; + const float BLEND = 0.1f; + _avgRenderableUpdateCost = (1.0f - BLEND) * _avgRenderableUpdateCost + BLEND * cost; } else { // we expect the cost to updating all renderables to exceed available time budget // so we first sort by priority and update in order until out of time @@ -450,43 +445,40 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene PrioritySortUtil::PriorityQueue sortedRenderables(views); sortedRenderables.reserve(_renderablesToUpdate.size()); { - PROFILE_RANGE_EX(simulation_physics, "SortRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size()); - std::unordered_map::iterator itr = _renderablesToUpdate.begin(); - while (itr != _renderablesToUpdate.end()) { - assert(itr->second); // only valid renderables are added to _renderablesToUpdate - sortedRenderables.push(SortableRenderer(itr->second)); - ++itr; + PROFILE_RANGE_EX(simulation_physics, "BuildSortedRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size()); + for (const auto& renderable : _renderablesToUpdate) { + assert(renderable); // only valid renderables are added to _renderablesToUpdate + sortedRenderables.push(SortableRenderer(renderable)); } } { - PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, sortedRenderables.size()); + PROFILE_RANGE_EX(simulation_physics, "SortAndUpdateRenderables", 0xffff00ff, sortedRenderables.size()); // compute remaining time budget + const auto& sortedRenderablesVector = sortedRenderables.getSortedVector(); uint64_t updateStart = usecTimestampNow(); - uint64_t timeBudget = MIN_SORTED_UPDATE_RENDERABLES_TIME_BUDGET; uint64_t sortCost = updateStart - sortStart; + uint64_t timeBudget = MIN_SORTED_UPDATE_RENDERABLES_TIME_BUDGET; if (sortCost < MAX_UPDATE_RENDERABLES_TIME_BUDGET - MIN_SORTED_UPDATE_RENDERABLES_TIME_BUDGET) { timeBudget = MAX_UPDATE_RENDERABLES_TIME_BUDGET - sortCost; } uint64_t expiry = updateStart + timeBudget; // process the sorted renderables - size_t numSorted = sortedRenderables.size(); - const auto& sortedRenderablesVector = sortedRenderables.getSortedVector(); for (const auto& sortedRenderable : sortedRenderablesVector) { if (usecTimestampNow() > expiry) { break; } const auto& renderable = sortedRenderable.getRenderer(); renderable->updateInScene(scene, transaction); - _renderablesToUpdate.erase(renderable->getEntity()->getID()); + _renderablesToUpdate.erase(renderable); } // compute average per-renderable update cost - size_t numUpdated = numSorted - sortedRenderables.size() + 1; // add one to avoid divide by zero + size_t numUpdated = sortedRenderables.size() - _renderablesToUpdate.size() + 1; // add one to avoid divide by zero float cost = (float)(usecTimestampNow() - updateStart) / (float)(numUpdated); - const float blend = 0.1f; - _avgRenderableUpdateCost = (1.0f - blend) * _avgRenderableUpdateCost + blend * cost; + const float BLEND = 0.1f; + _avgRenderableUpdateCost = (1.0f - BLEND) * _avgRenderableUpdateCost + BLEND * cost; } } } @@ -990,7 +982,6 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { // If it's in a pending queue, remove it - _renderablesToUpdate.erase(entityID); _entitiesToAdd.erase(entityID); auto itr = _entitiesInScene.find(entityID); @@ -1000,7 +991,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { } if (_tree && !_shuttingDown && _entitiesScriptEngine && !itr->second->getEntity()->getScript().isEmpty()) { - if (itr->second->getEntity()->contains(_avatarPosition)) { + if (_currentEntitiesInside.contains(entityID)) { _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); } _entitiesScriptEngine->unloadEntityScript(entityID, true); @@ -1013,6 +1004,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { } auto renderable = itr->second; + _renderablesToUpdate.erase(renderable); _entitiesInScene.erase(itr); if (!renderable) { @@ -1047,7 +1039,7 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool QString scriptUrl = entity->getScript(); if ((shouldLoad && unloadFirst) || scriptUrl.isEmpty()) { if (_entitiesScriptEngine) { - if (entity->contains(_avatarPosition)) { + if (_currentEntitiesInside.contains(entityID)) { _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); } _entitiesScriptEngine->unloadEntityScript(entityID); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index f794d947ed..bea04f106b 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -246,7 +246,7 @@ private: ReadWriteLockable _changedEntitiesGuard; std::unordered_set _changedEntities; - std::unordered_map _renderablesToUpdate; + std::unordered_set _renderablesToUpdate; std::unordered_map _entitiesInScene; std::unordered_map _entitiesToAdd; diff --git a/libraries/shared/src/PrioritySortUtil.h b/libraries/shared/src/PrioritySortUtil.h index d6a740231c..e4a258a065 100644 --- a/libraries/shared/src/PrioritySortUtil.h +++ b/libraries/shared/src/PrioritySortUtil.h @@ -45,7 +45,7 @@ namespace PrioritySortUtil { class PriorityQueue { public: PriorityQueue() = delete; - PriorityQueue(const ConicalViewFrustums& views) : _views(views) { } + PriorityQueue(const ConicalViewFrustums& views) : _views(views), _usecCurrentTime(usecTimestampNow()) { } PriorityQueue(const ConicalViewFrustums& views, float angularWeight, float centerWeight, float ageWeight) : _views(views), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight) , _usecCurrentTime(usecTimestampNow()) { From e119afdeada368d895e7fd547c0aff0823adfda3 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Mon, 24 Jun 2019 14:35:59 -0700 Subject: [PATCH 38/63] terms of service --- .../cmake/modules/MacOSXBundleInfo.plist.in | 2 +- launchers/darwin/nib/DisplayNameScreen.xib | 32 ++++++++++++++++++- launchers/darwin/src/DisplayNameScreen.m | 5 +++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/launchers/darwin/cmake/modules/MacOSXBundleInfo.plist.in b/launchers/darwin/cmake/modules/MacOSXBundleInfo.plist.in index 4c87bff3cf..3fe8e80f7a 100644 --- a/launchers/darwin/cmake/modules/MacOSXBundleInfo.plist.in +++ b/launchers/darwin/cmake/modules/MacOSXBundleInfo.plist.in @@ -32,6 +32,6 @@ CFBundleName ${MACOSX_BUNDLE_BUNDLE_NAME} CFBundleDisplayName - CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} diff --git a/launchers/darwin/nib/DisplayNameScreen.xib b/launchers/darwin/nib/DisplayNameScreen.xib index e56f2bf66b..f75491fc13 100644 --- a/launchers/darwin/nib/DisplayNameScreen.xib +++ b/launchers/darwin/nib/DisplayNameScreen.xib @@ -69,8 +69,17 @@ + + + + + + + + + + + + + + + + + + + + + @@ -91,5 +112,14 @@ + + + + + + + + + diff --git a/launchers/darwin/src/DisplayNameScreen.m b/launchers/darwin/src/DisplayNameScreen.m index 7a402d792b..581eabc4ee 100644 --- a/launchers/darwin/src/DisplayNameScreen.m +++ b/launchers/darwin/src/DisplayNameScreen.m @@ -31,4 +31,9 @@ { [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.highfidelity.com/hq-support"]]; } + +- (IBAction)termsOfService:(id)sender +{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.highfidelity.com/termsofservice"]]; +} @end From c5883a8d67dc361c5a87b48fe95a0e66ccd57a67 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Mon, 24 Jun 2019 14:58:06 -0700 Subject: [PATCH 39/63] CR fixes --- domain-server/src/NodeConnectionData.cpp | 2 +- libraries/networking/src/NodeList.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/src/NodeConnectionData.cpp b/domain-server/src/NodeConnectionData.cpp index e3406aa797..5419014622 100644 --- a/domain-server/src/NodeConnectionData.cpp +++ b/domain-server/src/NodeConnectionData.cpp @@ -39,7 +39,7 @@ NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, c // and the operating system type QByteArray compressedSystemInfo; dataStream >> compressedSystemInfo; - if(!compressedSystemInfo.isEmpty()) { + if (!compressedSystemInfo.isEmpty()) { newHeader.SystemInfo = qUncompress(compressedSystemInfo); } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 0dad7705f8..9dd7716823 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -426,7 +426,7 @@ void NodeList::sendDomainServerCheckIn() { QByteArray systemInfo(desc.dump().c_str()); QByteArray compressedSystemInfo = qCompress(systemInfo); - if(compressedSystemInfo.size() > MAX_SYSTEM_INFO_SIZE) { + if (compressedSystemInfo.size() > MAX_SYSTEM_INFO_SIZE) { // Highly unlikely, as not even unreasonable machines will // overflow the max size, but prevent MTU overflow anyway. // We could do something sophisticated like clearing specific From 5d3ed3f80e2bf8bcc0f9551433eae14de5afee5f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Jun 2019 15:01:31 -0700 Subject: [PATCH 40/63] Update win32 launcher with working ToS link --- launchers/win32/Launcher.rc | 2 +- launchers/win32/LauncherDlg.cpp | 24 +++++++++++++++++++----- launchers/win32/LauncherDlg.h | 3 ++- launchers/win32/resource.h | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/launchers/win32/Launcher.rc b/launchers/win32/Launcher.rc index 49f3ca53c5..4d9e0ffcd6 100644 --- a/launchers/win32/Launcher.rc +++ b/launchers/win32/Launcher.rc @@ -103,7 +103,7 @@ BEGIN CTEXT "",IDC_MESSAGE2_LABEL,35,172,239,15,NOT WS_VISIBLE CTEXT "",IDC_ACTION2_LABEL,15,147,278,25,NOT WS_VISIBLE RTEXT "",IDC_TERMS,15,172,180,15,NOT WS_VISIBLE - LTEXT "",IDC_TERMS2,197,172,80,15,NOT WS_VISIBLE + CONTROL "",IDC_TERMS_LINK,"Button", BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,197,172,80,15 CTEXT "",IDC_TROUBLE,65,203,174,15,NOT WS_VISIBLE CONTROL "NEXT",IDC_BUTTON_NEXT,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,107,158,94,16 CONTROL "Having Trouble?",IDC_TROUBLE_LINK,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,126,203,56,11 diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index 98c61794a0..bd33d96cb7 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -37,6 +37,7 @@ static CString GRAPHIK_REGULAR = _T("Graphik-Regular"); static CString GRAPHIK_SEMIBOLD = _T("Graphik-Semibold"); static CString TROUBLE_URL = _T("https://www.highfidelity.com/hq-support"); +static CString TERMS_URL = _T("https://www.highfidelity.com/termsofservice"); CLauncherDlg::CLauncherDlg(CWnd* pParent) @@ -54,6 +55,7 @@ void CLauncherDlg::DoDataExchange(CDataExchange* pDX) { DDX_Control(pDX, IDC_BUTTON_NEXT, m_btnNext); DDX_Control(pDX, IDC_TROUBLE_LINK, m_trouble_link); + DDX_Control(pDX, IDC_TERMS_LINK, m_terms_link); DDX_Control(pDX, IDC_ORGNAME, m_orgname); DDX_Control(pDX, IDC_USERNAME, m_username); DDX_Control(pDX, IDC_PASSWORD, m_password); @@ -69,6 +71,7 @@ BEGIN_MESSAGE_MAP(CLauncherDlg, CDialog) ON_EN_SETFOCUS(IDC_PASSWORD, &CLauncherDlg::OnPassEditChangeFocus) ON_BN_CLICKED(IDC_BUTTON_NEXT, &CLauncherDlg::OnNextClicked) ON_BN_CLICKED(IDC_TROUBLE_LINK, &CLauncherDlg::OnTroubleClicked) + ON_BN_CLICKED(IDC_TERMS_LINK, &CLauncherDlg::OnTermsClicked) ON_WM_CTLCOLOR() ON_WM_DRAWITEM() ON_WM_SETCURSOR() @@ -103,7 +106,6 @@ BOOL CLauncherDlg::OnInitDialog() { m_password_banner = (CStatic *)GetDlgItem(IDC_PASSWORD_BANNER); m_terms = (CStatic *)GetDlgItem(IDC_TERMS); - m_terms2 = (CStatic *)GetDlgItem(IDC_TERMS2); m_trouble = (CStatic *)GetDlgItem(IDC_TROUBLE); m_voxel = (CStatic *)GetDlgItem(IDC_VOXEL); @@ -223,6 +225,10 @@ afx_msg void CLauncherDlg::OnTroubleClicked() { LauncherUtils::executeOnForeground(TROUBLE_URL, _T("")); } +afx_msg void CLauncherDlg::OnTermsClicked() { + LauncherUtils::executeOnForeground(TERMS_URL, _T("")); +} + afx_msg void CLauncherDlg::OnNextClicked() { if (_drawStep != DrawStep::DrawChoose) { CString token; @@ -362,9 +368,9 @@ void CLauncherDlg::prepareChoose() { m_action_label->SetWindowTextW(_T("Choose a display name")); m_message_label->SetWindowTextW(_T("This is the name that your teammates will see.")); m_terms->ShowWindow(SW_SHOW); - m_terms2->ShowWindow(SW_SHOW); + m_terms_link.ShowWindow(SW_SHOW); m_terms->SetWindowTextW(_T("By signing in, you agree to the High Fidelity")); - m_terms2->SetWindowTextW(_T("Terms of Service")); + m_terms_link.SetWindowTextW(_T("Terms of Service")); CRect rec; m_btnNext.GetWindowRect(&rec); ScreenToClient(&rec); @@ -380,7 +386,7 @@ void CLauncherDlg::prepareProcess(DrawStep step) { m_trouble->ShowWindow(SW_HIDE); m_trouble_link.ShowWindow(SW_HIDE); m_terms->ShowWindow(SW_HIDE); - m_terms2->ShowWindow(SW_HIDE); + m_terms_link.ShowWindow(SW_HIDE); m_orgname_banner->ShowWindow(SW_HIDE); m_username_banner->ShowWindow(SW_HIDE); m_password_banner->ShowWindow(SW_HIDE); @@ -465,7 +471,7 @@ BOOL CLauncherDlg::getTextFormat(int resID, TextFormat& formatOut) { case IDC_TERMS: formatOut.size = TERMS_FONT_SIZE; break; - case IDC_TERMS2: + case IDC_TERMS_LINK: formatOut.size = TERMS_FONT_SIZE; formatOut.isBold = true; break; @@ -542,6 +548,14 @@ void CLauncherDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) dc.SelectObject(buttonFont); } dc.DrawText(_T("Having Trouble"), CRect(rect.left, rect.top, rect.right, rect.bottom), DT_CENTER | DT_VCENTER | DT_SINGLELINE); + } else if (nIDCtl == IDC_TERMS_LINK) { + dc.FillSolidRect(rect, COLOR_BLACK); + dc.SetTextColor(COLOR_LIGHT_GREY); + CFont buttonFont; + if (LauncherUtils::getFont(GRAPHIK_SEMIBOLD, TERMS_FONT_SIZE, true, buttonFont)) { + dc.SelectObject(buttonFont); + } + dc.DrawText(_T("Terms of Service"), CRect(rect.left, rect.top, rect.right, rect.bottom), DT_LEFT | DT_TOP | DT_SINGLELINE); } } diff --git a/launchers/win32/LauncherDlg.h b/launchers/win32/LauncherDlg.h index beaaedcdb6..6357c2a5b0 100644 --- a/launchers/win32/LauncherDlg.h +++ b/launchers/win32/LauncherDlg.h @@ -72,13 +72,13 @@ protected: HICON m_hIcon; CButton m_btnNext; CButton m_trouble_link; + CButton m_terms_link; CStatic* m_message_label; CStatic* m_action_label; CStatic* m_message2_label; CStatic* m_action2_label; CStatic* m_terms; - CStatic* m_terms2; CStatic* m_trouble; CStatic* m_voxel; @@ -111,6 +111,7 @@ protected: afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnNextClicked(); afx_msg void OnTroubleClicked(); + afx_msg void OnTermsClicked(); afx_msg void OnOrgEditChangeFocus(); afx_msg void OnUserEditChangeFocus(); afx_msg void OnPassEditChangeFocus(); diff --git a/launchers/win32/resource.h b/launchers/win32/resource.h index 51e6e7bd71..f5a1e3ef07 100644 --- a/launchers/win32/resource.h +++ b/launchers/win32/resource.h @@ -23,7 +23,7 @@ #define IDC_USERNAME_BANNER 1019 #define IDC_PASSWORD_BANNER 1020 #define IDC_TERMS 1021 -#define IDC_TERMS2 1022 +#define IDC_TERMS_LINK 1022 #define IDC_TROUBLE 1023 #define IDC_VOXEL 1024 #define IDC_TROUBLE_LINK 1027 From 2824d6fc5f68c07e555c2aaf87c4178b04a295f2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Jun 2019 15:12:35 -0700 Subject: [PATCH 41/63] Fix aspect ratio of splash logo in win32 launcher --- launchers/win32/LauncherDlg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index 98c61794a0..a031120541 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -275,7 +275,7 @@ void CLauncherDlg::drawLogo(CHwndRenderTarget* pRenderTarget) { CD2DBitmap m_pBitmamLogo(pRenderTarget, IDB_PNG2, _T("PNG")); auto size = pRenderTarget->GetSize(); int logoWidth = 231; - int logoHeight = 181; + int logoHeight = 173; float logoPosX = 0.5f * (size.width - logoWidth); float logoPosY = 0.95f * (size.height - logoHeight); CD2DRectF logoRec(logoPosX, logoPosY, logoPosX + logoWidth, logoPosY + logoHeight); From dd639c4191b3ba47acbcf8fa0d0355f70dd83d42 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Mon, 24 Jun 2019 15:33:47 -0700 Subject: [PATCH 42/63] fix typo --- launchers/darwin/nib/DisplayNameScreen.xib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launchers/darwin/nib/DisplayNameScreen.xib b/launchers/darwin/nib/DisplayNameScreen.xib index f75491fc13..3ba3deba53 100644 --- a/launchers/darwin/nib/DisplayNameScreen.xib +++ b/launchers/darwin/nib/DisplayNameScreen.xib @@ -72,7 +72,7 @@ - + From 792cef1a91fb5e9a59b9bd88424b2cc287f8c262 Mon Sep 17 00:00:00 2001 From: Anna Date: Mon, 24 Jun 2019 15:57:09 -0700 Subject: [PATCH 43/63] fixed bad merge --- .../display-plugins/src/display-plugins/OpenGLDisplayPlugin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index a6ab40d2bc..777c74822a 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -80,6 +80,7 @@ public: // Three threads, one for rendering, one for texture transfers, one reserved for the GL driver int getRequiredThreadCount() const override { return 3; } + virtual std::function getHUDOperator() override; void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override; @@ -100,7 +101,6 @@ protected: virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; } virtual void compositeLayers(); virtual void compositeScene(); - virtual std::function getHUDOperator(); virtual void compositePointer(); virtual void compositeExtra(){}; From cb1bf57bd1a817fef2ee3017209b61684a20c0a4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Jun 2019 16:54:06 -0700 Subject: [PATCH 44/63] Address pr review comments --- libraries/render-utils/src/RenderDeferredTask.cpp | 7 ------- libraries/render-utils/src/RenderDeferredTask.h | 4 +++- libraries/render-utils/src/RenderForwardTask.cpp | 7 ------- libraries/render-utils/src/RenderForwardTask.h | 4 +++- libraries/render/src/render/ResampleTask.cpp | 7 ------- libraries/render/src/render/ResampleTask.h | 9 ++------- 6 files changed, 8 insertions(+), 30 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index a9ceba8f5a..e513fb7282 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -97,11 +97,8 @@ RenderDeferredTask::RenderDeferredTask() void RenderDeferredTask::configure(const Config& config) { // Propagate resolution scale to sub jobs who need it auto preparePrimaryBufferConfig = config.getConfig("PreparePrimaryBuffer"); - auto upsamplePrimaryBufferConfig = config.getConfig("PrimaryBufferUpscale"); assert(preparePrimaryBufferConfig); - assert(upsamplePrimaryBufferConfig); preparePrimaryBufferConfig->setResolutionScale(config.resolutionScale); - upsamplePrimaryBufferConfig->setProperty("factor", 1.0f / config.resolutionScale); } void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { @@ -254,15 +251,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren } // Upscale to finale resolution - //const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", toneMappedBuffer); const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", toneMappedBuffer); // HUD Layer const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); task.addJob("RenderHUDLayer", renderHUDLayerInputs); - - // Blit! - // task.addJob("Blit", primaryFramebuffer); } RenderDeferredTaskDebug::RenderDeferredTaskDebug() { diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index ee397d94c7..969094488e 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -156,7 +156,9 @@ class PreparePrimaryFramebufferConfig : public render::Job::Config { public: float getResolutionScale() const { return resolutionScale; } void setResolutionScale(float scale) { - resolutionScale = std::max(0.1f, std::min(2.0f, scale)); + const float SCALE_RANGE_MIN = 0.1f; + const float SCALE_RANGE_MAX = 2.0f; + resolutionScale = std::max(SCALE_RANGE_MIN, std::min(SCALE_RANGE_MAX, scale)); } signals: diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index d361aa4a41..d65ad18aa1 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -52,11 +52,8 @@ extern void initForwardPipelines(ShapePlumber& plumber); void RenderForwardTask::configure(const Config& config) { // Propagate resolution scale to sub jobs who need it auto preparePrimaryBufferConfig = config.getConfig("PreparePrimaryBuffer"); - auto upsamplePrimaryBufferConfig = config.getConfig("PrimaryBufferUpscale"); assert(preparePrimaryBufferConfig); - assert(upsamplePrimaryBufferConfig); preparePrimaryBufferConfig->setResolutionScale(config.resolutionScale); - upsamplePrimaryBufferConfig->setProperty("factor", 1.0f / config.resolutionScale); } void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { @@ -172,10 +169,6 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // HUD Layer const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); task.addJob("RenderHUDLayer", renderHUDLayerInputs); - - // Disable blit because we do tonemapping and compositing directly to the blit FBO - // Blit! - // task.addJob("Blit", primaryFramebuffer); } gpu::FramebufferPointer PreparePrimaryFramebufferMSAA::createFramebuffer(const char* name, const glm::uvec2& frameSize, int numSamples) { diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index 8cca5ec912..baf7f66c6c 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -47,7 +47,9 @@ class PreparePrimaryFramebufferMSAAConfig : public render::Job::Config { public: float getResolutionScale() const { return resolutionScale; } void setResolutionScale(float scale) { - resolutionScale = std::max(0.1f, std::min(2.0f, scale)); + const float SCALE_RANGE_MIN = 0.1f; + const float SCALE_RANGE_MAX = 2.0f; + resolutionScale = std::max(SCALE_RANGE_MIN, std::min(SCALE_RANGE_MAX, scale)); } int getNumSamples() const { return numSamples; } diff --git a/libraries/render/src/render/ResampleTask.cpp b/libraries/render/src/render/ResampleTask.cpp index 93b2e0e97d..3e9bfec8da 100644 --- a/libraries/render/src/render/ResampleTask.cpp +++ b/libraries/render/src/render/ResampleTask.cpp @@ -138,19 +138,12 @@ void Upsample::run(const RenderContextPointer& renderContext, const gpu::Framebu gpu::PipelinePointer UpsampleToBlitFramebuffer::_pipeline; -void UpsampleToBlitFramebuffer::configure(const Config& config) { - _factor = config.factor; -} - void UpsampleToBlitFramebuffer::run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; auto sourceFramebuffer = input; - // auto srcFramebuffer = input.get0(); - // auto dstFramebuffer = input.get1(); -// resampledFrameBuffer = getResampledFrameBuffer(sourceFramebuffer); resampledFrameBuffer = args->_blitFramebuffer; if (resampledFrameBuffer != sourceFramebuffer) { diff --git a/libraries/render/src/render/ResampleTask.h b/libraries/render/src/render/ResampleTask.h index 8b5bbd5c4e..e62b76e6d0 100644 --- a/libraries/render/src/render/ResampleTask.h +++ b/libraries/render/src/render/ResampleTask.h @@ -70,21 +70,16 @@ namespace render { class UpsampleToBlitFramebuffer { public: - // using Input = render::VaryingSet2; using Input = gpu::FramebufferPointer; - using Config = UpsampleConfig; - using JobModel = Job::ModelIO; + using JobModel = Job::ModelIO; - UpsampleToBlitFramebuffer(float factor = 2.0f) : _factor{ factor } {} + UpsampleToBlitFramebuffer() {} - void configure(const Config& config); void run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer); protected: static gpu::PipelinePointer _pipeline; - - float _factor{ 2.0f }; }; } From 8d0b7a81f55cc1c5a508ed8d022c70e8c381897b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Jun 2019 17:01:11 -0700 Subject: [PATCH 45/63] one more --- scripts/developer/utilities/lib/prop/PropGroup.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index eab1b9c842..848ff8b288 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -127,7 +127,7 @@ PropFolderPanel { if (Array.isArray(object)) { if (object.length <= 1) { - object = object[0]; + object = object[0]; } } From 5686f5117120bcc86c36571005df579651282fb1 Mon Sep 17 00:00:00 2001 From: Preston Bezos Date: Tue, 25 Jun 2019 09:19:30 -0700 Subject: [PATCH 46/63] fixed hmd settings buttons spacing --- .../qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index c093b26437..44b639f70b 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -405,8 +405,8 @@ Rectangle { id: settingsButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right - anchors.rightMargin: 2 - width: 48 + anchors.rightMargin: 3 + width: 36 height: width Image { From 1481c7424f8f06185161a4390575f47f55c81b7f Mon Sep 17 00:00:00 2001 From: Preston Bezos Date: Tue, 25 Jun 2019 11:02:44 -0700 Subject: [PATCH 47/63] changed ptt muted icon --- .../hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml index a7b2088fc9..c46367d064 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml @@ -115,7 +115,7 @@ Rectangle { Image { id: image visible: false - source: (pushToTalk) ? (pushingToTalk ? pushToTalkIcon : pushToTalkMutedIcon) : muted ? mutedIcon : + source: (pushToTalk) ? pushToTalkIcon : muted ? mutedIcon : clipping ? clippingIcon : gated ? gatedIcon : unmutedIcon anchors.fill: parent } @@ -170,7 +170,7 @@ Rectangle { Image { id: maskImage visible: false - source: (pushToTalk) ? (pushingToTalk ? pushToTalkIcon : pushToTalkMutedIcon) : muted ? mutedIcon : + source: (pushToTalk) ? pushToTalkIcon : muted ? mutedIcon : clipping ? clippingIcon : gated ? gatedIcon : unmutedIcon anchors.top: parent.top anchors.left: parent.left From 9470467c31ab0d19bbf58bfde00f850daf267c26 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 25 Jun 2019 11:28:01 -0700 Subject: [PATCH 48/63] Ad the check for nsight to avoid the COmpositeHUD pass --- libraries/render-utils/src/RenderHUDLayerTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/RenderHUDLayerTask.cpp b/libraries/render-utils/src/RenderHUDLayerTask.cpp index a34f3b3e49..ac7a867366 100644 --- a/libraries/render-utils/src/RenderHUDLayerTask.cpp +++ b/libraries/render-utils/src/RenderHUDLayerTask.cpp @@ -17,7 +17,7 @@ void CompositeHUD::run(const RenderContextPointer& renderContext, const gpu::Fra assert(renderContext->args->_context); // We do not want to render HUD elements in secondary camera - if (renderContext->args->_renderMode == RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) { + if (nsightActive() || renderContext->args->_renderMode == RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) { return; } From b7a3d82f0f0977344b303ee81cbd0fe5274a603f Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 25 Jun 2019 11:30:25 -0700 Subject: [PATCH 49/63] DEV-170: Increase the speed of the animation when clicking between tabs in Settings --- .../hifi/simplifiedUI/settingsApp/SettingsApp.qml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/SettingsApp.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/SettingsApp.qml index 1f48d1d753..a9199ff5f1 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/SettingsApp.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/SettingsApp.qml @@ -91,7 +91,20 @@ Rectangle { Component { id: highlightBar Rectangle { + width: tabListView.currentItem.width + height: tabListView.currentItem.height color: simplifiedUI.colors.darkBackground + x: tabListView.currentItem.x + Behavior on x { + SmoothedAnimation { + duration: 250 + } + } + Behavior on width { + SmoothedAnimation { + duration: 250 + } + } } } @@ -104,6 +117,7 @@ Rectangle { orientation: ListView.Horizontal model: tabListModel highlight: highlightBar + highlightFollowsCurrentItem: false interactive: contentItem.width > width delegate: Item { visible: model.tabTitle !== "Dev" || (model.tabTitle === "Dev" && root.developerModeEnabled) From b079e3283ede4ce91ff1dda5aebdf1d5aadedf8c Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Tue, 25 Jun 2019 11:48:41 -0700 Subject: [PATCH 50/63] BUGFIX: use unaligned loads --- .../shared/src/avx2/BlendshapePacking_avx2.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/shared/src/avx2/BlendshapePacking_avx2.cpp b/libraries/shared/src/avx2/BlendshapePacking_avx2.cpp index 5524c355dc..1fea60a315 100644 --- a/libraries/shared/src/avx2/BlendshapePacking_avx2.cpp +++ b/libraries/shared/src/avx2/BlendshapePacking_avx2.cpp @@ -21,14 +21,14 @@ void packBlendshapeOffsets_AVX2(float (*unpacked)[9], uint32_t (*packed)[4], int // // deinterleave (8x9 to 9x8 matrix transpose) // - __m256 s0 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+0][0])), _mm_load_ps(&unpacked[i+4][0]), 1); - __m256 s1 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+1][0])), _mm_load_ps(&unpacked[i+5][0]), 1); - __m256 s2 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+2][0])), _mm_load_ps(&unpacked[i+6][0]), 1); - __m256 s3 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+3][0])), _mm_load_ps(&unpacked[i+7][0]), 1); - __m256 s4 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+0][4])), _mm_load_ps(&unpacked[i+4][4]), 1); - __m256 s5 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+1][4])), _mm_load_ps(&unpacked[i+5][4]), 1); - __m256 s6 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+2][4])), _mm_load_ps(&unpacked[i+6][4]), 1); - __m256 s7 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_load_ps(&unpacked[i+3][4])), _mm_load_ps(&unpacked[i+7][4]), 1); + __m256 s0 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+0][0])), _mm_loadu_ps(&unpacked[i+4][0]), 1); + __m256 s1 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+1][0])), _mm_loadu_ps(&unpacked[i+5][0]), 1); + __m256 s2 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+2][0])), _mm_loadu_ps(&unpacked[i+6][0]), 1); + __m256 s3 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+3][0])), _mm_loadu_ps(&unpacked[i+7][0]), 1); + __m256 s4 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+0][4])), _mm_loadu_ps(&unpacked[i+4][4]), 1); + __m256 s5 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+1][4])), _mm_loadu_ps(&unpacked[i+5][4]), 1); + __m256 s6 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+2][4])), _mm_loadu_ps(&unpacked[i+6][4]), 1); + __m256 s7 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+3][4])), _mm_loadu_ps(&unpacked[i+7][4]), 1); __m256 t0 = _mm256_unpacklo_ps(s0, s1); __m256 t1 = _mm256_unpackhi_ps(s0, s1); From 768dd051aa7d976fb3400381ce68fecefcf9bd3d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 25 Jun 2019 11:54:50 -0700 Subject: [PATCH 51/63] Add sanity check for viewport resolution scale to avoid negative value --- interface/src/scripting/RenderScriptingInterface.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/scripting/RenderScriptingInterface.cpp b/interface/src/scripting/RenderScriptingInterface.cpp index 1a0be3b9b2..338a5ab883 100644 --- a/interface/src/scripting/RenderScriptingInterface.cpp +++ b/interface/src/scripting/RenderScriptingInterface.cpp @@ -159,6 +159,10 @@ void RenderScriptingInterface::setViewportResolutionScale(float scale) { } void RenderScriptingInterface::forceViewportResolutionScale(float scale) { + // just not negative values or zero + if (scale <= 0.f) { + return; + } _renderSettingLock.withWriteLock([&] { _viewportResolutionScale = (scale); _viewportResolutionScaleSetting.set(scale); From 0a34745ff9c002a3b28a723b1e3ab984565ea49b Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Tue, 25 Jun 2019 12:53:07 -0700 Subject: [PATCH 52/63] Use QVector resize() instead of reserve() to silence Debug builds about size not being set. Causes unneeded default initialization, but no obvious way to avoid. --- libraries/render-utils/src/Model.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 11c1e42fd4..ce3ff51502 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1777,13 +1777,13 @@ void Blender::run() { // allocate the required sizes QVector blendedMeshSizes; - blendedMeshSizes.reserve(numMeshes); + blendedMeshSizes.resize(numMeshes); QVector packedBlendshapeOffsets; - packedBlendshapeOffsets.reserve(numBlendshapeOffsets); + packedBlendshapeOffsets.resize(numBlendshapeOffsets); QVector unpackedBlendshapeOffsets; - unpackedBlendshapeOffsets.reserve(maxBlendshapeOffsets); // reuse for all meshes + unpackedBlendshapeOffsets.resize(maxBlendshapeOffsets); // reuse for all meshes int offset = 0; for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) { From 4c5c61231d856f4f3dcf2f4102dc8cb1e050093a Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Tue, 25 Jun 2019 12:57:55 -0700 Subject: [PATCH 53/63] Only use QVector resize when actually needed --- libraries/render-utils/src/Model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ce3ff51502..74cf1ffa39 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1777,7 +1777,7 @@ void Blender::run() { // allocate the required sizes QVector blendedMeshSizes; - blendedMeshSizes.resize(numMeshes); + blendedMeshSizes.reserve(numMeshes); QVector packedBlendshapeOffsets; packedBlendshapeOffsets.resize(numBlendshapeOffsets); From 31c10d1aa1b4191df1234685a75f33a8b16b49b8 Mon Sep 17 00:00:00 2001 From: MiladNazeri Date: Tue, 25 Jun 2019 13:24:57 -0700 Subject: [PATCH 54/63] Update BUILD_WIN.md When I updated the download link, I forgot to change the text above. It might be a little confusing. --- BUILD_WIN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 48530b9351..2d6074cd77 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -31,7 +31,7 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo ### Step 2. Installing CMake -Download and install the latest version of CMake 3.9. +Download and install the latest version of CMake 3.14. Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.14 Version page](https://cmake.org/files/v3.14/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted. From 68d620fca339c1ed67af18cbd7c81b6054e0fbbc Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Tue, 25 Jun 2019 13:37:45 -0700 Subject: [PATCH 55/63] fix crash --- launchers/darwin/src/LatestBuildRequest.m | 19 +++++++++++++------ launchers/darwin/src/main.mm | 10 +++++----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index 7e836548af..fd233afd0e 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -6,12 +6,18 @@ @implementation LatestBuildRequest - (NSInteger) getCurrentVersion { - NSString* interfaceAppPath = [[Launcher.sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]; - NSError * error = nil; - Interface * interface = [[Interface alloc] initWith:interfaceAppPath]; - NSInteger currentVersion = [interface getVersion:&error]; - if (currentVersion == 0 && error != nil) { - NSLog(@"can't get version from interface, falling back to settings: %@", error); + NSInteger currentVersion; + @try { + NSString* interfaceAppPath = [[Launcher.sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]; + NSError * error = nil; + Interface * interface = [[Interface alloc] initWith:interfaceAppPath]; + currentVersion = [interface getVersion:&error]; + if (currentVersion == 0 && error != nil) { + NSLog(@"can't get version from interface, falling back to settings: %@", error); + currentVersion = [Settings.sharedSettings latestBuildVersion]; + } + } @catch (NSException *exception) { + NSLog(@"an exception was thrown"); currentVersion = [Settings.sharedSettings latestBuildVersion]; } return currentVersion; @@ -58,6 +64,7 @@ BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]]; dispatch_async(dispatch_get_main_queue(), ^{ + NSInteger currentVersion = [self getCurrentVersion]; NSLog(@"Latest Build Request -> does build directory exist: %@", appDirectoryExist ? @"TRUE" : @"FALSE"); NSLog(@"Latest Build Request -> current version: %ld", currentVersion); diff --git a/launchers/darwin/src/main.mm b/launchers/darwin/src/main.mm index 7feab64d86..b6555aad87 100644 --- a/launchers/darwin/src/main.mm +++ b/launchers/darwin/src/main.mm @@ -5,13 +5,13 @@ void redirectLogToDocuments() { NSString* filePath = [[NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"/Launcher/"]; - + if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) { NSError * error = nil; [[NSFileManager defaultManager] createDirectoryAtPath:filePath withIntermediateDirectories:TRUE attributes:nil error:&error]; } NSString *pathForLog = [filePath stringByAppendingPathComponent:@"log.txt"]; - + freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr); } @@ -23,12 +23,12 @@ int main(int argc, const char* argv[]) { NSLog(@"launcher is already running"); return 0; } - + [NSApplication sharedApplication]; Launcher* sharedLauncher = [Launcher sharedLauncher]; [Settings sharedSettings]; [NSApp setDelegate: sharedLauncher]; - + // Referenced from https://stackoverflow.com/questions/9155015/handle-cmd-q-in-cocoa-application-and-menu-item-quit-application-programmatic id menubar = [[NSMenu new] autorelease]; id appMenuItem = [[NSMenuItem new] autorelease]; @@ -40,7 +40,7 @@ int main(int argc, const char* argv[]) { id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:quitTitle action:@selector(terminate:) keyEquivalent:@"q"] autorelease]; [appMenu addItem:quitMenuItem]; [appMenuItem setSubmenu:appMenu]; - + [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; return NSApplicationMain(argc, argv); } From 1e38e7b7eb000714e616b7455e2f0e99e3890309 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Tue, 25 Jun 2019 14:11:41 -0700 Subject: [PATCH 56/63] print out exception error --- launchers/darwin/src/LatestBuildRequest.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index fd233afd0e..0c136dce3c 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -17,7 +17,7 @@ currentVersion = [Settings.sharedSettings latestBuildVersion]; } } @catch (NSException *exception) { - NSLog(@"an exception was thrown"); + NSLog(@"an exception was thrown: %@", exception); currentVersion = [Settings.sharedSettings latestBuildVersion]; } return currentVersion; From b4e1c2264c186cb6ab7f27274fabb54b804d1a60 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 25 Jun 2019 14:47:58 -0700 Subject: [PATCH 57/63] Use a queued signal to quit from AccountManager::saveLoginStatus() --- libraries/networking/src/AccountManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 3a7d3e0a67..e2e9d33eb6 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -956,7 +956,7 @@ void AccountManager::saveLoginStatus(bool isLoggedIn) { QProcess launcher; launcher.setProgram(launcherPath); launcher.startDetached(); - qApp->quit(); + QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection); } } } \ No newline at end of file From 72867437be52761ba04c8d2670a7b773da27d3df Mon Sep 17 00:00:00 2001 From: milad Date: Tue, 25 Jun 2019 15:38:02 -0700 Subject: [PATCH 58/63] updated lifetime --- .../resources/modules/nameTagListManager.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js b/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js index 2ba9904845..de783f8661 100644 --- a/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js +++ b/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js @@ -19,7 +19,8 @@ var HALF = 0.5; var CLEAR_ENTITY_EDIT_PROPS = true; var MILISECONDS_IN_SECOND = 1000; var SECONDS_IN_MINUTE = 60; -var ALWAYS_ON_MAX_LIFETIME_IN_SECONDS = 20 * SECONDS_IN_MINUTE; // Delete after 20 minutes in case a nametag is hanging around in on mode +// Delete after 5 minutes in case a nametag is hanging around in on mode +var ALWAYS_ON_MAX_LIFETIME_IN_SECONDS = 5 * SECONDS_IN_MINUTE; // ************************************* // START UTILTY @@ -377,6 +378,11 @@ function maybeAddOrRemoveIntervalCheck() { add(avatar); return; } + if (avatar in _this.avatars) { + var entity = _this.avatars[avatar].nametag; + var age = entity.get("age"); + entity.edit('lifetime', age + ALWAYS_ON_MAX_LIFETIME_IN_SECONDS); + } if (avatarDistance > MAX_RADIUS_IGNORE_METERS) { maybeRemove(avatar); } From d8daee49a8e2bf7397d911099a5dfb693cffc448 Mon Sep 17 00:00:00 2001 From: RebeccaStankus Date: Tue, 25 Jun 2019 13:40:07 -0700 Subject: [PATCH 59/63] Fixed bad path to gridControls --- .../system/assets/images/icon-particles.svg | 29 - .../system/assets/images/icon-point-light.svg | 57 - .../system/assets/images/icon-spot-light.svg | 37 - .../system/assets/images/icon-zone.svg | 73 - scripts/simplifiedUI/system/edit.js | 2858 ---------------- .../simplifiedUI/system/html/entityList.html | 93 - .../system/html/entityProperties.html | 51 - .../system/html/js/createAppTooltip.js | 116 - .../system/libraries/EditEntityList.qml | 12 - .../system/libraries/entityList.js | 330 -- .../system/libraries/entitySelectionTool.js | 2925 ----------------- .../create}/assets/images/hourglass.svg | 0 scripts/system/create/edit.js | 2 +- .../create/modules/entityShapeVisualizer.js | 4 +- scripts/system/create/qml/EditTabView.qml | 2 +- .../system/create/qml/EditToolsTabView.qml | 2 +- scripts/system/marketplaces/marketplaces.js | 2 +- 17 files changed, 6 insertions(+), 6587 deletions(-) delete mode 100644 scripts/simplifiedUI/system/assets/images/icon-particles.svg delete mode 100644 scripts/simplifiedUI/system/assets/images/icon-point-light.svg delete mode 100644 scripts/simplifiedUI/system/assets/images/icon-spot-light.svg delete mode 100644 scripts/simplifiedUI/system/assets/images/icon-zone.svg delete mode 100644 scripts/simplifiedUI/system/edit.js delete mode 100644 scripts/simplifiedUI/system/html/entityList.html delete mode 100644 scripts/simplifiedUI/system/html/entityProperties.html delete mode 100644 scripts/simplifiedUI/system/html/js/createAppTooltip.js delete mode 100644 scripts/simplifiedUI/system/libraries/EditEntityList.qml delete mode 100644 scripts/simplifiedUI/system/libraries/entityList.js delete mode 100644 scripts/simplifiedUI/system/libraries/entitySelectionTool.js rename scripts/{simplifiedUI/system => system/create}/assets/images/hourglass.svg (100%) diff --git a/scripts/simplifiedUI/system/assets/images/icon-particles.svg b/scripts/simplifiedUI/system/assets/images/icon-particles.svg deleted file mode 100644 index 5e0105d7cd..0000000000 --- a/scripts/simplifiedUI/system/assets/images/icon-particles.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/icon-point-light.svg b/scripts/simplifiedUI/system/assets/images/icon-point-light.svg deleted file mode 100644 index 896c35b63b..0000000000 --- a/scripts/simplifiedUI/system/assets/images/icon-point-light.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/icon-spot-light.svg b/scripts/simplifiedUI/system/assets/images/icon-spot-light.svg deleted file mode 100644 index ac2f87bb27..0000000000 --- a/scripts/simplifiedUI/system/assets/images/icon-spot-light.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/icon-zone.svg b/scripts/simplifiedUI/system/assets/images/icon-zone.svg deleted file mode 100644 index 41aeac4951..0000000000 --- a/scripts/simplifiedUI/system/assets/images/icon-zone.svg +++ /dev/null @@ -1,73 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/scripts/simplifiedUI/system/edit.js b/scripts/simplifiedUI/system/edit.js deleted file mode 100644 index cf99f3a618..0000000000 --- a/scripts/simplifiedUI/system/edit.js +++ /dev/null @@ -1,2858 +0,0 @@ -// edit.js -// -// Created by Brad Hefta-Gaub on 10/2/14. -// Persist toolbar by HRS 6/11/15. -// Copyright 2014 High Fidelity, Inc. -// -// This script allows you to edit entities with a new UI/UX for mouse and trackpad based editing -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager, - Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, - progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, OverlaySystemWindow, - keyUpEventFromUIWindow:true */ - -(function() { // BEGIN LOCAL_SCOPE - -"use strict"; - -var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton"; - -var CONTROLLER_MAPPING_NAME = "com.highfidelity.editMode"; - -Script.include([ - "libraries/stringHelpers.js", - "libraries/dataViewHelpers.js", - "libraries/progressDialog.js", - "libraries/entitySelectionTool.js", - "libraries/ToolTip.js", - "libraries/entityCameraTool.js", - "libraries/gridTool.js", - "libraries/entityList.js", - "libraries/utils.js", - "libraries/entityIconOverlayManager.js" -]); - -var CreateWindow = Script.require('./modules/createWindow.js'); - -var TITLE_OFFSET = 60; -var CREATE_TOOLS_WIDTH = 490; -var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942; - -var DEFAULT_IMAGE = "https://hifi-content.s3.amazonaws.com/DomainContent/production/no-image.jpg"; - -var createToolsWindow = new CreateWindow( - Script.resolvePath("create/EditTools.qml"), - 'Create Tools', - 'com.highfidelity.create.createToolsWindow', - function () { - var windowHeight = Window.innerHeight - TITLE_OFFSET; - if (windowHeight > MAX_DEFAULT_ENTITY_LIST_HEIGHT) { - windowHeight = MAX_DEFAULT_ENTITY_LIST_HEIGHT; - } - return { - size: { - x: CREATE_TOOLS_WIDTH, - y: windowHeight - }, - position: { - x: Window.x + Window.innerWidth - CREATE_TOOLS_WIDTH, - y: Window.y + TITLE_OFFSET - } - } - }, - false -); - -/** - * @description Returns true in case we should use the tablet version of the CreateApp - * @returns boolean - */ -var shouldUseEditTabletApp = function() { - return HMD.active || (!HMD.active && !Settings.getValue("desktopTabletBecomesToolbar", true)); -}; - - -var selectionDisplay = SelectionDisplay; -var selectionManager = SelectionManager; - -var PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg"); -var POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg"); -var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg"); -var ZONE_URL = Script.resolvePath("assets/images/icon-zone.svg"); - -var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect', 'Zone'], function(entityID) { - var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']); - if (properties.type === 'Light') { - return { - url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL, - }; - } else if (properties.type === 'Zone') { - return { - url: ZONE_URL, - }; - } else { - return { - url: PARTICLE_SYSTEM_URL, - }; - } -}); - -var cameraManager = new CameraManager(); - -var grid = new Grid(); -var gridTool = new GridTool({ - horizontalGrid: grid, - createToolsWindow: createToolsWindow, - shouldUseEditTabletApp: shouldUseEditTabletApp -}); -gridTool.setVisible(false); - -var EntityShapeVisualizer = Script.require('./modules/entityShapeVisualizer.js'); -var entityShapeVisualizer = new EntityShapeVisualizer(["Zone"]); - -var entityListTool = new EntityListTool(shouldUseEditTabletApp); - -selectionManager.addEventListener(function () { - selectionDisplay.updateHandles(); - entityIconOverlayManager.updatePositions(); - entityShapeVisualizer.setEntities(selectionManager.selections); -}); - -var DEGREES_TO_RADIANS = Math.PI / 180.0; -var RADIANS_TO_DEGREES = 180.0 / Math.PI; - -var MIN_ANGULAR_SIZE = 2; -var MAX_ANGULAR_SIZE = 45; -var allowLargeModels = true; -var allowSmallModels = true; - -var DEFAULT_DIMENSION = 0.20; - -var DEFAULT_DIMENSIONS = { - x: DEFAULT_DIMENSION, - y: DEFAULT_DIMENSION, - z: DEFAULT_DIMENSION -}; - -var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); - -var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select"; -var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; -var MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "Show Lights and Particle Systems in Create Mode"; -var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Create Mode"; - -var MENU_CREATE_ENTITIES_GRABBABLE = "Create Entities As Grabbable (except Zones, Particles, and Lights)"; -var MENU_ALLOW_SELECTION_LARGE = "Allow Selecting of Large Models"; -var MENU_ALLOW_SELECTION_SMALL = "Allow Selecting of Small Models"; -var MENU_ALLOW_SELECTION_LIGHTS = "Allow Selecting of Lights"; - -var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; -var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; -var SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "showLightsAndParticlesInEditMode"; -var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; - -var SETTING_EDIT_PREFIX = "Edit/"; - - -var CREATE_ENABLED_ICON = "icons/tablet-icons/edit-i.svg"; -var CREATE_DISABLED_ICON = "icons/tablet-icons/edit-disabled.svg"; - -// marketplace info, etc. not quite ready yet. -var SHOULD_SHOW_PROPERTY_MENU = false; -var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain."; -var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain."; - -var isActive = false; -var createButton = null; - -var IMPORTING_SVO_OVERLAY_WIDTH = 144; -var IMPORTING_SVO_OVERLAY_HEIGHT = 30; -var IMPORTING_SVO_OVERLAY_MARGIN = 5; -var IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34; -var importingSVOImageOverlay = Overlays.addOverlay("image", { - imageURL: Script.resolvePath("assets") + "/images/hourglass.svg", - width: 20, - height: 20, - alpha: 1.0, - x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH, - y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT, - visible: false -}); -var importingSVOTextOverlay = Overlays.addOverlay("text", { - font: { - size: 14 - }, - text: "Importing SVO...", - leftMargin: IMPORTING_SVO_OVERLAY_LEFT_MARGIN, - x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH - IMPORTING_SVO_OVERLAY_MARGIN, - y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT - IMPORTING_SVO_OVERLAY_MARGIN, - width: IMPORTING_SVO_OVERLAY_WIDTH, - height: IMPORTING_SVO_OVERLAY_HEIGHT, - backgroundColor: { - red: 80, - green: 80, - blue: 80 - }, - backgroundAlpha: 0.7, - visible: false -}); - -var MARKETPLACE_URL = Account.metaverseServerURL + "/marketplace"; -var marketplaceWindow = new OverlayWebWindow({ - title: 'Marketplace', - source: "about:blank", - width: 900, - height: 700, - visible: false -}); - -function showMarketplace(marketplaceID) { - var url = MARKETPLACE_URL; - if (marketplaceID) { - url = url + "/items/" + marketplaceID; - } - marketplaceWindow.setURL(url); - marketplaceWindow.setVisible(true); - marketplaceWindow.raise(); - - UserActivityLogger.logAction("opened_marketplace"); -} - -function hideMarketplace() { - marketplaceWindow.setVisible(false); - marketplaceWindow.setURL("about:blank"); -} - -// function toggleMarketplace() { -// if (marketplaceWindow.visible) { -// hideMarketplace(); -// } else { -// showMarketplace(); -// } -// } - -function adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation) { - // Adjust the position such that the bounding box (registration, dimensions and orientation) lies behind the original - // position in the given direction. - var CORNERS = [ - { x: 0, y: 0, z: 0 }, - { x: 0, y: 0, z: 1 }, - { x: 0, y: 1, z: 0 }, - { x: 0, y: 1, z: 1 }, - { x: 1, y: 0, z: 0 }, - { x: 1, y: 0, z: 1 }, - { x: 1, y: 1, z: 0 }, - { x: 1, y: 1, z: 1 }, - ]; - - // Go through all corners and find least (most negative) distance in front of position. - var distance = 0; - for (var i = 0, length = CORNERS.length; i < length; i++) { - var cornerVector = - Vec3.multiplyQbyV(orientation, Vec3.multiplyVbyV(Vec3.subtract(CORNERS[i], registration), dimensions)); - var cornerDistance = Vec3.dot(cornerVector, direction); - distance = Math.min(cornerDistance, distance); - } - position = Vec3.sum(Vec3.multiply(distance, direction), position); - return position; -} - -var GRABBABLE_ENTITIES_MENU_CATEGORY = "Edit"; - -// Handles any edit mode updates required when domains have switched -function checkEditPermissionsAndUpdate() { - if ((createButton === null) || (createButton === undefined)) { - //--EARLY EXIT--( nothing to safely update ) - return; - } - - var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); - createButton.editProperties({ - icon: (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON), - captionColor: (hasRezPermissions ? "#ffffff" : "#888888"), - }); - - if (!hasRezPermissions && isActive) { - that.setActive(false); - tablet.gotoHomeScreen(); - } -} - -// Copies the properties in `b` into `a`. `a` will be modified. -function copyProperties(a, b) { - for (var key in b) { - a[key] = b[key]; - } - return a; -} - -const DEFAULT_DYNAMIC_PROPERTIES = { - dynamic: true, - damping: 0.39347, - angularDamping: 0.39347, - gravity: { x: 0, y: -9.8, z: 0 }, -}; - -const DEFAULT_NON_DYNAMIC_PROPERTIES = { - dynamic: false, - damping: 0, - angularDamping: 0, - gravity: { x: 0, y: 0, z: 0 }, -}; - -const DEFAULT_ENTITY_PROPERTIES = { - All: { - description: "", - rotation: { x: 0, y: 0, z: 0, w: 1 }, - collidesWith: "static,dynamic,kinematic,otherAvatar,myAvatar", - collisionSoundURL: "", - cloneable: false, - ignoreIK: true, - canCastShadow: true, - href: "", - script: "", - serverScripts:"", - velocity: { - x: 0, - y: 0, - z: 0 - }, - angularVelocity: { - x: 0, - y: 0, - z: 0 - }, - restitution: 0.5, - friction: 0.5, - density: 1000, - dynamic: false, - }, - Shape: { - shape: "Box", - dimensions: { x: 0.2, y: 0.2, z: 0.2 }, - color: { red: 0, green: 180, blue: 239 }, - }, - Text: { - text: "Text", - dimensions: { - x: 0.65, - y: 0.3, - z: 0.01 - }, - textColor: { red: 255, green: 255, blue: 255 }, - backgroundColor: { red: 0, green: 0, blue: 0 }, - lineHeight: 0.06, - faceCamera: false, - }, - Zone: { - dimensions: { - x: 10, - y: 10, - z: 10 - }, - flyingAllowed: true, - ghostingAllowed: true, - filter: "", - keyLightMode: "inherit", - keyLightColor: { red: 255, green: 255, blue: 255 }, - keyLight: { - intensity: 1.0, - direction: { - x: 0.0, - y: -0.707106769084930, // 45 degrees - z: 0.7071067690849304 - }, - castShadows: true - }, - ambientLightMode: "inherit", - ambientLight: { - ambientIntensity: 0.5, - ambientURL: "" - }, - hazeMode: "inherit", - haze: { - hazeRange: 1000, - hazeAltitudeEffect: false, - hazeBaseRef: 0, - hazeColor: { - red: 128, - green: 154, - blue: 179 - }, - hazeBackgroundBlend: 0, - hazeEnableGlare: false, - hazeGlareColor: { - red: 255, - green: 229, - blue: 179 - }, - }, - shapeType: "box", - bloomMode: "inherit", - avatarPriority: "inherit" - }, - Model: { - collisionShape: "none", - compoundShapeURL: "", - animation: { - url: "", - running: false, - allowTranslation: false, - loop: true, - hold: false, - currentFrame: 0, - firstFrame: 0, - lastFrame: 100000, - fps: 30.0, - } - }, - Image: { - dimensions: { - x: 0.5385, - y: 0.2819, - z: 0.0092 - }, - shapeType: "box", - collisionless: true, - keepAspectRatio: false, - imageURL: DEFAULT_IMAGE - }, - Web: { - dimensions: { - x: 1.6, - y: 0.9, - z: 0.01 - }, - sourceUrl: "https://highfidelity.com/", - dpi: 30, - }, - ParticleEffect: { - lifespan: 1.5, - maxParticles: 10, - textures: "https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png", - emitRate: 5.5, - emitSpeed: 0, - speedSpread: 0, - emitDimensions: { x: 0, y: 0, z: 0 }, - emitOrientation: { x: 0, y: 0, z: 0, w: 1 }, - emitterShouldTrail: true, - particleRadius: 0.25, - radiusStart: 0, - radiusSpread: 0, - particleColor: { - red: 255, - green: 255, - blue: 255 - }, - colorSpread: { - red: 0, - green: 0, - blue: 0 - }, - alpha: 0, - alphaStart: 1, - alphaSpread: 0, - emitAcceleration: { - x: 0, - y: 2.5, - z: 0 - }, - accelerationSpread: { - x: 0, - y: 0, - z: 0 - }, - particleSpin: 0, - spinSpread: 0, - rotateWithEntity: false, - polarStart: 0, - polarFinish: Math.PI, - azimuthStart: -Math.PI, - azimuthFinish: Math.PI - }, - Light: { - color: { red: 255, green: 255, blue: 255 }, - intensity: 5.0, - dimensions: DEFAULT_LIGHT_DIMENSIONS, - falloffRadius: 1.0, - isSpotlight: false, - exponent: 1.0, - cutoff: 75.0, - }, -}; - -var toolBar = (function () { - var EDIT_SETTING = "io.highfidelity.isEditing"; // for communication with other scripts - var that = {}, - toolBar, - activeButton = null, - systemToolbar = null, - dialogWindow = null, - tablet = null; - - function createNewEntity(requestedProperties) { - var dimensions = requestedProperties.dimensions ? requestedProperties.dimensions : DEFAULT_DIMENSIONS; - var position = getPositionToCreateEntity(); - var entityID = null; - - var properties = {}; - - copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.All); - - var type = requestedProperties.type; - if (type === "Box" || type === "Sphere") { - copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.Shape); - } else { - copyProperties(properties, DEFAULT_ENTITY_PROPERTIES[type]); - } - - // We apply the requested properties first so that they take priority over any default properties. - copyProperties(properties, requestedProperties); - - if (properties.dynamic) { - copyProperties(properties, DEFAULT_DYNAMIC_PROPERTIES); - } else { - copyProperties(properties, DEFAULT_NON_DYNAMIC_PROPERTIES); - } - - - if (position !== null && position !== undefined) { - var direction; - if (Camera.mode === "entity" || Camera.mode === "independent") { - direction = Camera.orientation; - } else { - direction = MyAvatar.orientation; - } - direction = Vec3.multiplyQbyV(direction, Vec3.UNIT_Z); - - var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web", "Material"]; - if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { - - // Adjust position of entity per bounding box prior to creating it. - var registration = properties.registration; - if (registration === undefined) { - var DEFAULT_REGISTRATION = { x: 0.5, y: 0.5, z: 0.5 }; - registration = DEFAULT_REGISTRATION; - } - - var orientation = properties.orientation; - if (orientation === undefined) { - properties.orientation = MyAvatar.orientation; - var DEFAULT_ORIENTATION = properties.orientation; - orientation = DEFAULT_ORIENTATION; - } else { - // If the orientation is already defined, we perform the corresponding rotation assuming that - // our start referential is the avatar referential. - properties.orientation = Quat.multiply(MyAvatar.orientation, properties.orientation); - var DEFAULT_ORIENTATION = properties.orientation; - orientation = DEFAULT_ORIENTATION; - } - - position = adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation); - } - - position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions); - properties.position = position; - - if (!properties.grab) { - properties.grab = {}; - if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) && - !(properties.type === "Zone" || properties.type === "Light" || properties.type === "ParticleEffect")) { - properties.grab.grabbable = true; - } else { - properties.grab.grabbable = false; - } - } - - entityID = Entities.addEntity(properties); - SelectionManager.addEntity(entityID, false, this); - SelectionManager.saveProperties(); - pushCommandForSelections([{ - entityID: entityID, - properties: properties - }], [], true); - - var POST_ADJUST_ENTITY_TYPES = ["Model"]; - if (POST_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { - // Adjust position of entity per bounding box after it has been created and auto-resized. - var initialDimensions = Entities.getEntityProperties(entityID, ["dimensions"]).dimensions; - var DIMENSIONS_CHECK_INTERVAL = 200; - var MAX_DIMENSIONS_CHECKS = 10; - var dimensionsCheckCount = 0; - var dimensionsCheckFunction = function () { - dimensionsCheckCount++; - var properties = Entities.getEntityProperties(entityID, ["dimensions", "registrationPoint", "rotation"]); - if (!Vec3.equal(properties.dimensions, initialDimensions)) { - position = adjustPositionPerBoundingBox(position, direction, properties.registrationPoint, - properties.dimensions, properties.rotation); - position = grid.snapToSurface(grid.snapToGrid(position, false, properties.dimensions), - properties.dimensions); - Entities.editEntity(entityID, { - position: position - }); - selectionManager._update(false, this); - } else if (dimensionsCheckCount < MAX_DIMENSIONS_CHECKS) { - Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL); - } - }; - Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL); - } - } else { - Window.notifyEditError("Can't create " + properties.type + ": " + - properties.type + " would be out of bounds."); - } - - selectionManager.clearSelections(this); - entityListTool.sendUpdate(); - selectionManager.setSelections([entityID], this); - - Window.setFocus(); - - return entityID; - } - - function closeExistingDialogWindow() { - if (dialogWindow) { - dialogWindow.close(); - dialogWindow = null; - } - } - - function cleanup() { - that.setActive(false); - if (tablet) { - tablet.removeButton(activeButton); - } - if (systemToolbar) { - systemToolbar.removeButton(EDIT_TOGGLE_BUTTON); - } - } - - var buttonHandlers = {}; // only used to tablet mode - - function addButton(name, handler) { - buttonHandlers[name] = handler; - } - - var SHAPE_TYPE_NONE = 0; - var SHAPE_TYPE_SIMPLE_HULL = 1; - var SHAPE_TYPE_SIMPLE_COMPOUND = 2; - var SHAPE_TYPE_STATIC_MESH = 3; - var SHAPE_TYPE_BOX = 4; - var SHAPE_TYPE_SPHERE = 5; - var DYNAMIC_DEFAULT = false; - - var MATERIAL_MODE_UV = 0; - var MATERIAL_MODE_PROJECTED = 1; - - function handleNewModelDialogResult(result) { - if (result) { - var url = result.url; - var shapeType; - switch (result.collisionShapeIndex) { - case SHAPE_TYPE_SIMPLE_HULL: - shapeType = "simple-hull"; - break; - case SHAPE_TYPE_SIMPLE_COMPOUND: - shapeType = "simple-compound"; - break; - case SHAPE_TYPE_STATIC_MESH: - shapeType = "static-mesh"; - break; - case SHAPE_TYPE_BOX: - shapeType = "box"; - break; - case SHAPE_TYPE_SPHERE: - shapeType = "sphere"; - break; - default: - shapeType = "none"; - } - - var dynamic = result.dynamic !== null ? result.dynamic : DYNAMIC_DEFAULT; - if (shapeType === "static-mesh" && dynamic) { - // The prompt should prevent this case - print("Error: model cannot be both static mesh and dynamic. This should never happen."); - } else if (url) { - createNewEntity({ - type: "Model", - modelURL: url, - shapeType: shapeType, - grab: { - grabbable: result.grabbable - }, - dynamic: dynamic, - }); - } - } - } - - function handleNewMaterialDialogResult(result) { - if (result) { - var materialURL = result.textInput; - //var materialMappingMode; - //switch (result.comboBox) { - // case MATERIAL_MODE_PROJECTED: - // materialMappingMode = "projected"; - // break; - // default: - // shapeType = "uv"; - //} - var materialData = ""; - if (materialURL.startsWith("materialData")) { - materialData = JSON.stringify({ - "materials": {} - }); - } - - var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1; - if (materialURL) { - createNewEntity({ - type: "Material", - materialURL: materialURL, - //materialMappingMode: materialMappingMode, - priority: DEFAULT_LAYERED_MATERIAL_PRIORITY, - materialData: materialData - }); - } - } - } - - function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - tablet.popFromStack(); - switch (message.method) { - case "newModelDialogAdd": - handleNewModelDialogResult(message.params); - closeExistingDialogWindow(); - break; - case "newModelDialogCancel": - closeExistingDialogWindow(); - break; - case "newEntityButtonClicked": - buttonHandlers[message.params.buttonName](); - break; - case "newMaterialDialogAdd": - handleNewMaterialDialogResult(message.params); - closeExistingDialogWindow(); - break; - case "newMaterialDialogCancel": - closeExistingDialogWindow(); - break; - } - } - - var entitiesToDelete = []; - var deletedEntityTimer = null; - var DELETE_ENTITY_TIMER_TIMEOUT = 100; - - function checkDeletedEntityAndUpdate(entityID) { - // Allow for multiple entity deletes before updating the entities selected. - entitiesToDelete.push(entityID); - if (deletedEntityTimer !== null) { - Script.clearTimeout(deletedEntityTimer); - } - deletedEntityTimer = Script.setTimeout(function () { - if (entitiesToDelete.length > 0) { - selectionManager.removeEntities(entitiesToDelete, this); - } - entityListTool.removeEntities(entitiesToDelete, selectionManager.selections); - entitiesToDelete = []; - deletedEntityTimer = null; - }, DELETE_ENTITY_TIMER_TIMEOUT); - } - - function initialize() { - Script.scriptEnding.connect(cleanup); - Window.domainChanged.connect(function () { - if (isActive) { - tablet.gotoHomeScreen(); - } - that.setActive(false); - that.clearEntityList(); - checkEditPermissionsAndUpdate(); - }); - - HMD.displayModeChanged.connect(function() { - if (isActive) { - tablet.gotoHomeScreen(); - } - that.setActive(false); - }); - - Entities.canAdjustLocksChanged.connect(function (canAdjustLocks) { - if (isActive && !canAdjustLocks) { - that.setActive(false); - } - checkEditPermissionsAndUpdate(); - }); - - Entities.canRezChanged.connect(checkEditPermissionsAndUpdate); - Entities.canRezTmpChanged.connect(checkEditPermissionsAndUpdate); - Entities.canRezCertifiedChanged.connect(checkEditPermissionsAndUpdate); - Entities.canRezTmpCertifiedChanged.connect(checkEditPermissionsAndUpdate); - var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); - - Entities.deletingEntity.connect(checkDeletedEntityAndUpdate); - - var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON); - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - activeButton = tablet.addButton({ - captionColor: hasRezPermissions ? "#ffffff" : "#888888", - icon: createButtonIconRsrc, - activeIcon: "icons/tablet-icons/edit-a.svg", - text: "CREATE", - sortOrder: 10 - }); - createButton = activeButton; - tablet.screenChanged.connect(function (type, url) { - var isGoingToHomescreenOnDesktop = (!shouldUseEditTabletApp() && - (url === 'hifi/tablet/TabletHome.qml' || url === '')); - if (isActive && (type !== "QML" || url !== Script.resolvePath("create/Edit.qml")) && !isGoingToHomescreenOnDesktop) { - that.setActive(false); - } - }); - tablet.fromQml.connect(fromQml); - createToolsWindow.fromQml.addListener(fromQml); - - createButton.clicked.connect(function() { - if ( ! (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()) ) { - Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG); - return; - } - - that.toggle(); - }); - - addButton("importEntitiesButton", function() { - Window.browseChanged.connect(onFileOpenChanged); - Window.browseAsync("Select Model to Import", "", "*.json"); - }); - - addButton("openAssetBrowserButton", function() { - Window.showAssetServer(); - }); - function createNewEntityDialogButtonCallback(entityType) { - return function() { - if (shouldUseEditTabletApp()) { - // tablet version of new-model dialog - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - tablet.pushOntoStack(Script.resolvePath("create/New" + entityType + "Dialog.qml")); - } else { - closeExistingDialogWindow(); - var qmlPath = Script.resolvePath("create/New" + entityType + "Window.qml"); - var DIALOG_WINDOW_SIZE = { x: 500, y: 300 }; - dialogWindow = Desktop.createWindow(qmlPath, { - title: "New " + entityType + " Entity", - flags: Desktop.ALWAYS_ON_TOP | Desktop.CLOSE_BUTTON_HIDES, - presentationMode: Desktop.PresentationMode.NATIVE, - size: DIALOG_WINDOW_SIZE, - visible: true - }); - dialogWindow.fromQml.connect(fromQml); - } - }; - } - - addButton("newModelButton", createNewEntityDialogButtonCallback("Model")); - - addButton("newShapeButton", function () { - createNewEntity({ - type: "Shape", - shape: "Cube", - }); - }); - - addButton("newLightButton", function () { - createNewEntity({ - type: "Light", - }); - }); - - addButton("newTextButton", function () { - createNewEntity({ - type: "Text", - }); - }); - - addButton("newImageButton", function () { - createNewEntity({ - type: "Image", - }); - }); - - addButton("newWebButton", function () { - createNewEntity({ - type: "Web", - }); - }); - - addButton("newZoneButton", function () { - createNewEntity({ - type: "Zone", - }); - }); - - addButton("newParticleButton", function () { - createNewEntity({ - type: "ParticleEffect", - }); - }); - - addButton("newMaterialButton", createNewEntityDialogButtonCallback("Material")); - - var deactivateCreateIfDesktopWindowsHidden = function() { - if (!shouldUseEditTabletApp() && !entityListTool.isVisible() && !createToolsWindow.isVisible()) { - that.setActive(false); - } - }; - entityListTool.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden); - createToolsWindow.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden); - - that.setActive(false); - } - - that.clearEntityList = function () { - entityListTool.clearEntityList(); - }; - - that.toggle = function () { - that.setActive(!isActive); - if (!isActive) { - tablet.gotoHomeScreen(); - } - }; - - that.setActive = function (active) { - ContextOverlay.enabled = !active; - Settings.setValue(EDIT_SETTING, active); - if (active) { - Controller.captureEntityClickEvents(); - } else { - Controller.releaseEntityClickEvents(); - - closeExistingDialogWindow(); - } - if (active === isActive) { - return; - } - if (active && !Entities.canRez() && !Entities.canRezTmp() && !Entities.canRezCertified() && !Entities.canRezTmpCertified()) { - Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG); - return; - } - Messages.sendLocalMessage("edit-events", JSON.stringify({ - enabled: active - })); - isActive = active; - activeButton.editProperties({isActive: isActive}); - undoHistory.setEnabled(isActive); - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - - if (!isActive) { - entityListTool.setVisible(false); - gridTool.setVisible(false); - grid.setEnabled(false); - propertiesTool.setVisible(false); - selectionManager.clearSelections(this); - cameraManager.disable(); - selectionDisplay.disableTriggerMapping(); - tablet.landscape = false; - Controller.disableMapping(CONTROLLER_MAPPING_NAME); - } else { - if (shouldUseEditTabletApp()) { - tablet.loadQMLSource(Script.resolvePath("create/Edit.qml"), true); - } else { - // make other apps inactive while in desktop mode - tablet.gotoHomeScreen(); - } - UserActivityLogger.enabledEdit(); - entityListTool.setVisible(true); - entityListTool.sendUpdate(); - gridTool.setVisible(true); - grid.setEnabled(true); - propertiesTool.setVisible(true); - selectionDisplay.enableTriggerMapping(); - print("starting tablet in landscape mode"); - tablet.landscape = true; - Controller.enableMapping(CONTROLLER_MAPPING_NAME); - // Not sure what the following was meant to accomplish, but it currently causes - // everybody else to think that Interface has lost focus overall. fogbugzid:558 - // Window.setFocus(); - } - entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); - Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - }; - - initialize(); - return that; -})(); - -var selectedEntityID; -var orientation; -var intersection; - - -function rayPlaneIntersection(pickRay, point, normal) { // - // - // This version of the test returns the intersection of a line with a plane - // - var collides = Vec3.dot(pickRay.direction, normal); - - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides; - - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); -} - -function rayPlaneIntersection2(pickRay, point, normal) { - // - // This version of the test returns false if the ray is directed away from the plane - // - var collides = Vec3.dot(pickRay.direction, normal); - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides; - if (t < 0.0) { - return false; - } else { - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); - } -} - -function findClickedEntity(event) { - var pickZones = event.isControl; - - if (pickZones) { - Entities.setZonesArePickable(true); - } - - var pickRay = Camera.computePickRay(event.x, event.y); - var tabletIDs = getMainTabletIDs(); - if (tabletIDs.length > 0) { - var overlayResult = Overlays.findRayIntersection(pickRay, true, tabletIDs); - if (overlayResult.intersects) { - return null; - } - } - - var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking - var iconResult = entityIconOverlayManager.findRayIntersection(pickRay); - iconResult.accurate = true; - - if (pickZones) { - Entities.setZonesArePickable(false); - } - - var result; - - if (iconResult.intersects) { - result = iconResult; - } else if (entityResult.intersects) { - result = entityResult; - } else { - return null; - } - - if (!result.accurate) { - return null; - } - - var foundEntity = result.entityID; - return { - pickRay: pickRay, - entityID: foundEntity, - intersection: result.intersection - }; -} - -// Handles selections on overlays while in edit mode by querying entities from -// entityIconOverlayManager. -function handleOverlaySelectionToolUpdates(channel, message, sender) { - var wantDebug = false; - if (sender !== MyAvatar.sessionUUID || channel !== 'entityToolUpdates') - return; - - var data = JSON.parse(message); - - if (data.method === "selectOverlay") { - if (!selectionDisplay.triggered() || selectionDisplay.triggeredHand === data.hand) { - if (wantDebug) { - print("setting selection to overlay " + data.overlayID); - } - var entity = entityIconOverlayManager.findEntity(data.overlayID); - - if (entity !== null) { - selectionManager.setSelections([entity], this); - } - } - } -} - -function handleMessagesReceived(channel, message, sender) { - switch( channel ){ - case 'entityToolUpdates': { - handleOverlaySelectionToolUpdates( channel, message, sender ); - break; - } - default: { - return; - } - } -} - -Messages.subscribe("entityToolUpdates"); -Messages.messageReceived.connect(handleMessagesReceived); - -var mouseHasMovedSincePress = false; -var mousePressStartTime = 0; -var mousePressStartPosition = { - x: 0, - y: 0 -}; -var mouseDown = false; - -function mousePressEvent(event) { - mouseDown = true; - mousePressStartPosition = { - x: event.x, - y: event.y - }; - mousePressStartTime = Date.now(); - mouseHasMovedSincePress = false; - mouseCapturedByTool = false; - - if (propertyMenu.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { - mouseCapturedByTool = true; - return; - } - if (isActive) { - if (cameraManager.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) { - // Event handled; do nothing. - return; - } - } -} - -var mouseCapturedByTool = false; -var lastMousePosition = null; -var CLICK_TIME_THRESHOLD = 500 * 1000; // 500 ms -var CLICK_MOVE_DISTANCE_THRESHOLD = 20; -var IDLE_MOUSE_TIMEOUT = 200; - -var lastMouseMoveEvent = null; - -function mouseMoveEventBuffered(event) { - lastMouseMoveEvent = event; -} - -function mouseMove(event) { - if (mouseDown && !mouseHasMovedSincePress) { - var timeSincePressMicro = Date.now() - mousePressStartTime; - - var dX = mousePressStartPosition.x - event.x; - var dY = mousePressStartPosition.y - event.y; - var sqDist = (dX * dX) + (dY * dY); - - // If less than CLICK_TIME_THRESHOLD has passed since the mouse click AND the mouse has moved - // less than CLICK_MOVE_DISTANCE_THRESHOLD distance, then don't register this as a mouse move - // yet. The goal is to provide mouse clicks that are more lenient to small movements. - if (timeSincePressMicro < CLICK_TIME_THRESHOLD && sqDist < CLICK_MOVE_DISTANCE_THRESHOLD) { - return; - } - mouseHasMovedSincePress = true; - } - - if (!isActive) { - return; - } - - // allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing - if (selectionDisplay.mouseMoveEvent(event) || propertyMenu.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) { - return; - } - - lastMousePosition = { - x: event.x, - y: event.y - }; -} - -function mouseReleaseEvent(event) { - mouseDown = false; - - if (lastMouseMoveEvent) { - mouseMove(lastMouseMoveEvent); - lastMouseMoveEvent = null; - } - if (propertyMenu.mouseReleaseEvent(event)) { - return true; - } - if (isActive && selectionManager.hasSelection()) { - tooltip.show(false); - } - if (mouseCapturedByTool) { - - return; - } - - cameraManager.mouseReleaseEvent(event); - - if (!mouseHasMovedSincePress) { - mouseClickEvent(event); - } -} - -function wasTabletOrEditHandleClicked(event) { - var rayPick = Camera.computePickRay(event.x, event.y); - var result = Overlays.findRayIntersection(rayPick, true); - if (result.intersects) { - var overlayID = result.overlayID; - var tabletIDs = getMainTabletIDs(); - if (tabletIDs.indexOf(overlayID) >= 0) { - return true; - } else if (selectionDisplay.isEditHandle(overlayID)) { - return true; - } - } - return false; -} - -function mouseClickEvent(event) { - var wantDebug = false; - var result, properties, tabletClicked; - if (isActive && event.isLeftButton) { - result = findClickedEntity(event); - var tabletOrEditHandleClicked = wasTabletOrEditHandleClicked(event); - if (tabletOrEditHandleClicked) { - return; - } - - if (result === null || result === undefined) { - if (!event.isShifted) { - selectionManager.clearSelections(this); - } - return; - } - toolBar.setActive(true); - var pickRay = result.pickRay; - var foundEntity = result.entityID; - if (HMD.tabletID && foundEntity === HMD.tabletID) { - return; - } - properties = Entities.getEntityProperties(foundEntity); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - if (wantDebug) { - print("Checking properties: " + properties.id + " " + " - Half Diagonal:" + halfDiagonal); - } - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X === A + ((P-A).B)B - // d = |P-X| - - var A = pickRay.origin; - var B = Vec3.normalize(pickRay.direction); - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * - 180 / Math.PI; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && - (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - selectedEntityID = foundEntity; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, P, Quat.getForward(orientation)); - - if (!event.isShifted) { - selectionManager.setSelections([foundEntity], this); - } else { - selectionManager.addEntity(foundEntity, true, this); - } - selectionManager.saveProperties(); - - if (wantDebug) { - print("Model selected: " + foundEntity); - } - selectionDisplay.select(selectedEntityID, event); - - if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) { - cameraManager.enable(); - cameraManager.focus(selectionManager.worldPosition, - selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - } - } - } else if (event.isRightButton) { - result = findClickedEntity(event); - if (result) { - if (SHOULD_SHOW_PROPERTY_MENU !== true) { - return; - } - properties = Entities.getEntityProperties(result.entityID); - if (properties.marketplaceID) { - propertyMenu.marketplaceID = properties.marketplaceID; - propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace"); - } else { - propertyMenu.marketplaceID = null; - propertyMenu.updateMenuItemText(showMenuItem, "No marketplace info"); - } - propertyMenu.setPosition(event.x, event.y); - propertyMenu.show(); - } else { - propertyMenu.hide(); - } - } -} - -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEventBuffered); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - - -// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already -// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that -// added it. -var modelMenuAddedDelete = false; -var originalLightsArePickable = Entities.getLightsArePickable(); - -function setupModelMenus() { - // adj our menuitems - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Undo", - shortcutKey: 'Ctrl+Z', - position: 0, - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Redo", - shortcutKey: 'Ctrl+Y', - position: 1, - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Entities", - isSeparator: true - }); - if (!Menu.menuItemExists("Edit", "Delete")) { - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Delete", - shortcutKeyEvent: { - text: "delete" - }, - afterItem: "Entities", - }); - modelMenuAddedDelete = true; - } - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Parent Entity to Last", - afterItem: "Entities" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Unparent Entity", - afterItem: "Parent Entity to Last" - }); - - Menu.addMenuItem({ - menuName: GRABBABLE_ENTITIES_MENU_CATEGORY, - menuItemName: MENU_CREATE_ENTITIES_GRABBABLE, - afterItem: "Unparent Entity", - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, true) - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_ALLOW_SELECTION_LARGE, - afterItem: MENU_CREATE_ENTITIES_GRABBABLE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, true) - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_ALLOW_SELECTION_SMALL, - afterItem: MENU_ALLOW_SELECTION_LARGE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, true) - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_ALLOW_SELECTION_LIGHTS, - afterItem: MENU_ALLOW_SELECTION_SMALL, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, false) - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Select All Entities In Box", - afterItem: "Allow Selecting of Lights" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Select All Entities Touching Box", - afterItem: "Select All Entities In Box" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Export Entities", - afterItem: "Entities" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Import Entities", - afterItem: "Export Entities" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Import Entities from URL", - afterItem: "Import Entities" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_AUTO_FOCUS_ON_SELECT, - isCheckable: true, - isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_EASE_ON_FOCUS, - afterItem: MENU_AUTO_FOCUS_ON_SELECT, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, - afterItem: MENU_EASE_ON_FOCUS, - isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, - afterItem: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false" - }); - - Entities.setLightsArePickable(false); -} - -setupModelMenus(); // do this when first running our script. - -function cleanupModelMenus() { - Menu.removeMenuItem("Edit", "Undo"); - Menu.removeMenuItem("Edit", "Redo"); - - Menu.removeSeparator("Edit", "Entities"); - if (modelMenuAddedDelete) { - // delete our menuitems - Menu.removeMenuItem("Edit", "Delete"); - } - - Menu.removeMenuItem("Edit", "Parent Entity to Last"); - Menu.removeMenuItem("Edit", "Unparent Entity"); - Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); - Menu.removeMenuItem("Edit", "Select All Entities In Box"); - Menu.removeMenuItem("Edit", "Select All Entities Touching Box"); - - Menu.removeMenuItem("Edit", "Export Entities"); - Menu.removeMenuItem("Edit", "Import Entities"); - Menu.removeMenuItem("Edit", "Import Entities from URL"); - - Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT); - Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS); - Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE); - Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE); - Menu.removeMenuItem("Edit", MENU_CREATE_ENTITIES_GRABBABLE); -} - -Script.scriptEnding.connect(function () { - toolBar.setActive(false); - Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)); - Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); - Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - - Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LARGE)); - Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, Menu.isOptionChecked(MENU_ALLOW_SELECTION_SMALL)); - Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LIGHTS)); - - - progressDialog.cleanup(); - cleanupModelMenus(); - tooltip.cleanup(); - selectionDisplay.cleanup(); - entityShapeVisualizer.cleanup(); - Entities.setLightsArePickable(originalLightsArePickable); - - Overlays.deleteOverlay(importingSVOImageOverlay); - Overlays.deleteOverlay(importingSVOTextOverlay); - - Controller.keyReleaseEvent.disconnect(keyReleaseEvent); - Controller.keyPressEvent.disconnect(keyPressEvent); - - Controller.mousePressEvent.disconnect(mousePressEvent); - Controller.mouseMoveEvent.disconnect(mouseMoveEventBuffered); - Controller.mouseReleaseEvent.disconnect(mouseReleaseEvent); - - Messages.messageReceived.disconnect(handleMessagesReceived); - Messages.unsubscribe("entityToolUpdates"); - createButton = null; -}); - -var lastOrientation = null; -var lastPosition = null; - -// Do some stuff regularly, like check for placement of various overlays -Script.update.connect(function (deltaTime) { - progressDialog.move(); - selectionDisplay.checkControllerMove(); - var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1); - var dPosition = Vec3.distance(Camera.position, lastPosition); - if (dOrientation > 0.001 || dPosition > 0.001) { - propertyMenu.hide(); - lastOrientation = Camera.orientation; - lastPosition = Camera.position; - } - if (lastMouseMoveEvent) { - mouseMove(lastMouseMoveEvent); - lastMouseMoveEvent = null; - } -}); - -function insideBox(center, dimensions, point) { - return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) && - (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) && - (Math.abs(point.z - center.z) <= (dimensions.z / 2.0)); -} - -function selectAllEntitiesInCurrentSelectionBox(keepIfTouching) { - if (selectionManager.hasSelection()) { - // Get all entities touching the bounding box of the current selection - var boundingBoxCorner = Vec3.subtract(selectionManager.worldPosition, - Vec3.multiply(selectionManager.worldDimensions, 0.5)); - var entities = Entities.findEntitiesInBox(boundingBoxCorner, selectionManager.worldDimensions); - - if (!keepIfTouching) { - var isValid; - if (selectionManager.localPosition === null || selectionManager.localPosition === undefined) { - isValid = function (position) { - return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position); - }; - } else { - isValid = function (position) { - var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation), - Vec3.subtract(position, - selectionManager.localPosition)); - return insideBox(Vec3.ZERO, selectionManager.localDimensions, localPosition); - }; - } - for (var i = 0; i < entities.length; ++i) { - var properties = Entities.getEntityProperties(entities[i]); - if (!isValid(properties.position)) { - entities.splice(i, 1); - --i; - } - } - } - selectionManager.setSelections(entities, this); - } -} - -function sortSelectedEntities(selected) { - var sortedEntities = selected.slice(); - var begin = 0; - while (begin < sortedEntities.length) { - var elementRemoved = false; - var next = begin + 1; - while (next < sortedEntities.length) { - var beginID = sortedEntities[begin]; - var nextID = sortedEntities[next]; - - if (Entities.isChildOfParent(beginID, nextID)) { - sortedEntities[begin] = nextID; - sortedEntities[next] = beginID; - sortedEntities.splice(next, 1); - elementRemoved = true; - break; - } else if (Entities.isChildOfParent(nextID, beginID)) { - sortedEntities.splice(next, 1); - elementRemoved = true; - break; - } - next++; - } - if (!elementRemoved) { - begin++; - } - } - return sortedEntities; -} - -function recursiveDelete(entities, childrenList, deletedIDs, entityHostType) { - var wantDebug = false; - var entitiesLength = entities.length; - var initialPropertySets = Entities.getMultipleEntityProperties(entities); - var entityHostTypes = Entities.getMultipleEntityProperties(entities, 'entityHostType'); - for (var i = 0; i < entitiesLength; ++i) { - var entityID = entities[i]; - - if (entityHostTypes[i].entityHostType !== entityHostType) { - if (wantDebug) { - console.log("Skipping deletion of entity " + entityID + " with conflicting entityHostType: " + - entityHostTypes[i].entityHostType + ", expected: " + entityHostType); - } - continue; - } - - var children = Entities.getChildrenIDs(entityID); - var grandchildrenList = []; - recursiveDelete(children, grandchildrenList, deletedIDs, entityHostType); - childrenList.push({ - entityID: entityID, - properties: initialPropertySets[i], - children: grandchildrenList - }); - deletedIDs.push(entityID); - Entities.deleteEntity(entityID); - } -} - -function unparentSelectedEntities() { - if (SelectionManager.hasSelection()) { - var selectedEntities = selectionManager.selections; - var parentCheck = false; - - if (selectedEntities.length < 1) { - Window.notifyEditError("You must have an entity selected in order to unparent it."); - return; - } - selectedEntities.forEach(function (id, index) { - var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID; - if (parentId !== null && parentId.length > 0 && parentId !== Uuid.NULL) { - 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 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}); - } - }); - - if (parentCheck) { - Window.notify("Entities parented"); - } else { - Window.notify("Entities are already parented to last"); - } - } else { - Window.notifyEditError("You have nothing selected to parent"); - } -} -function deleteSelectedEntities() { - if (SelectionManager.hasSelection()) { - var deletedIDs = []; - - SelectionManager.saveProperties(); - var savedProperties = []; - var newSortedSelection = sortSelectedEntities(selectionManager.selections); - var entityHostTypes = Entities.getMultipleEntityProperties(newSortedSelection, 'entityHostType'); - for (var i = 0; i < newSortedSelection.length; ++i) { - var entityID = newSortedSelection[i]; - var initialProperties = SelectionManager.savedProperties[entityID]; - if (initialProperties.locked || - (initialProperties.avatarEntity && initialProperties.owningAvatarID !== MyAvatar.sessionUUID)) { - continue; - } - var children = Entities.getChildrenIDs(entityID); - var childList = []; - recursiveDelete(children, childList, deletedIDs, entityHostTypes[i].entityHostType); - savedProperties.push({ - entityID: entityID, - properties: initialProperties, - children: childList - }); - deletedIDs.push(entityID); - Entities.deleteEntity(entityID); - } - - if (savedProperties.length > 0) { - SelectionManager.clearSelections(this); - pushCommandForSelections([], savedProperties); - entityListTool.deleteEntities(deletedIDs); - } - } -} - -function toggleSelectedEntitiesLocked() { - if (SelectionManager.hasSelection()) { - var locked = !Entities.getEntityProperties(SelectionManager.selections[0], ["locked"]).locked; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - Entities.editEntity(entityID, { - locked: locked - }); - } - entityListTool.sendUpdate(); - selectionManager._update(false, this); - } -} - -function toggleSelectedEntitiesVisible() { - if (SelectionManager.hasSelection()) { - var visible = !Entities.getEntityProperties(SelectionManager.selections[0], ["visible"]).visible; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - Entities.editEntity(entityID, { - visible: visible - }); - } - entityListTool.sendUpdate(); - selectionManager._update(false, this); - } -} - -function onFileSaveChanged(filename) { - Window.saveFileChanged.disconnect(onFileSaveChanged); - if (filename !== "") { - var success = Clipboard.exportEntities(filename, selectionManager.selections); - if (!success) { - Window.notifyEditError("Export failed."); - } - } -} - -function onFileOpenChanged(filename) { - // disconnect the event, otherwise the requests will stack up - try { - // Not all calls to onFileOpenChanged() connect an event. - Window.browseChanged.disconnect(onFileOpenChanged); - } catch (e) { - // Ignore. - } - - var importURL = null; - if (filename !== "") { - importURL = filename; - if (!/^(http|https):\/\//.test(filename)) { - importURL = "file:///" + importURL; - } - } - if (importURL) { - if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) { - toolBar.toggle(); - } - importSVO(importURL); - } -} - -function onPromptTextChanged(prompt) { - Window.promptTextChanged.disconnect(onPromptTextChanged); - if (prompt !== "") { - if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) { - toolBar.toggle(); - } - importSVO(prompt); - } -} - -function handleMenuEvent(menuItem) { - if (menuItem === "Allow Selecting of Small Models") { - allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); - } else if (menuItem === "Allow Selecting of Large Models") { - allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); - } else if (menuItem === "Allow Selecting of Lights") { - Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); - } else if (menuItem === "Delete") { - deleteSelectedEntities(); - } else if (menuItem === "Undo") { - undoHistory.undo(); - } else if (menuItem === "Redo") { - undoHistory.redo(); - } else if (menuItem === "Parent Entity to Last") { - parentSelectedEntities(); - } else if (menuItem === "Unparent Entity") { - unparentSelectedEntities(); - } else if (menuItem === "Export Entities") { - if (!selectionManager.hasSelection()) { - Window.notifyEditError("No entities have been selected."); - } else { - Window.saveFileChanged.connect(onFileSaveChanged); - Window.saveAsync("Select Where to Save", "", "*.json"); - } - } else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") { - if (menuItem === "Import Entities") { - Window.browseChanged.connect(onFileOpenChanged); - Window.browseAsync("Select Model to Import", "", "*.json"); - } else { - Window.promptTextChanged.connect(onPromptTextChanged); - Window.promptAsync("URL of SVO to import", ""); - } - } else if (menuItem === "Select All Entities In Box") { - selectAllEntitiesInCurrentSelectionBox(false); - } else if (menuItem === "Select All Entities Touching Box") { - selectAllEntitiesInCurrentSelectionBox(true); - } else if (menuItem === MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) { - entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); - } else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) { - Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - } else if (menuItem === MENU_CREATE_ENTITIES_GRABBABLE) { - Settings.setValue(SETTING_EDIT_PREFIX + menuItem, Menu.isOptionChecked(menuItem)); - } - tooltip.show(false); -} - -var HALF_TREE_SCALE = 16384; - -function getPositionToCreateEntity(extra) { - var CREATE_DISTANCE = 2; - var position; - var delta = extra !== undefined ? extra : 0; - if (Camera.mode === "entity" || Camera.mode === "independent") { - position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getForward(Camera.orientation), CREATE_DISTANCE + delta)); - } else { - position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getForward(MyAvatar.orientation), CREATE_DISTANCE + delta)); - } - - if (position.x > HALF_TREE_SCALE || position.y > HALF_TREE_SCALE || position.z > HALF_TREE_SCALE) { - return null; - } - return position; -} - -function importSVO(importURL) { - if (!Entities.canRez() && !Entities.canRezTmp() && - !Entities.canRezCertified() && !Entities.canRezTmpCertified()) { - Window.notifyEditError(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); - return; - } - - Overlays.editOverlay(importingSVOTextOverlay, { - visible: true - }); - Overlays.editOverlay(importingSVOImageOverlay, { - visible: true - }); - - var success = Clipboard.importEntities(importURL); - - if (success) { - var VERY_LARGE = 10000; - var isLargeImport = Clipboard.getClipboardContentsLargestDimension() >= VERY_LARGE; - var position = Vec3.ZERO; - if (!isLargeImport) { - position = getPositionToCreateEntity(Clipboard.getClipboardContentsLargestDimension() / 2); - } - if (position !== null && position !== undefined) { - var pastedEntityIDs = Clipboard.pasteEntities(position); - if (!isLargeImport) { - // The first entity in Clipboard gets the specified position with the rest being relative to it. Therefore, move - // entities after they're imported so that they're all the correct distance in front of and with geometric mean - // centered on the avatar/camera direction. - var deltaPosition = Vec3.ZERO; - var entityPositions = []; - var entityParentIDs = []; - - var propType = Entities.getEntityProperties(pastedEntityIDs[0], ["type"]).type; - var NO_ADJUST_ENTITY_TYPES = ["Zone", "Light", "ParticleEffect"]; - if (NO_ADJUST_ENTITY_TYPES.indexOf(propType) === -1) { - var targetDirection; - if (Camera.mode === "entity" || Camera.mode === "independent") { - targetDirection = Camera.orientation; - } else { - targetDirection = MyAvatar.orientation; - } - targetDirection = Vec3.multiplyQbyV(targetDirection, Vec3.UNIT_Z); - - var targetPosition = getPositionToCreateEntity(); - var deltaParallel = HALF_TREE_SCALE; // Distance to move entities parallel to targetDirection. - var deltaPerpendicular = Vec3.ZERO; // Distance to move entities perpendicular to targetDirection. - for (var i = 0, length = pastedEntityIDs.length; i < length; i++) { - var curLoopEntityProps = Entities.getEntityProperties(pastedEntityIDs[i], ["position", "dimensions", - "registrationPoint", "rotation", "parentID"]); - var adjustedPosition = adjustPositionPerBoundingBox(targetPosition, targetDirection, - curLoopEntityProps.registrationPoint, curLoopEntityProps.dimensions, curLoopEntityProps.rotation); - var delta = Vec3.subtract(adjustedPosition, curLoopEntityProps.position); - var distance = Vec3.dot(delta, targetDirection); - deltaParallel = Math.min(distance, deltaParallel); - deltaPerpendicular = Vec3.sum(Vec3.subtract(delta, Vec3.multiply(distance, targetDirection)), - deltaPerpendicular); - entityPositions[i] = curLoopEntityProps.position; - entityParentIDs[i] = curLoopEntityProps.parentID; - } - deltaPerpendicular = Vec3.multiply(1 / pastedEntityIDs.length, deltaPerpendicular); - deltaPosition = Vec3.sum(Vec3.multiply(deltaParallel, targetDirection), deltaPerpendicular); - } - - if (grid.getSnapToGrid()) { - var firstEntityProps = Entities.getEntityProperties(pastedEntityIDs[0], ["position", "dimensions", - "registrationPoint"]); - var positionPreSnap = Vec3.sum(deltaPosition, firstEntityProps.position); - position = grid.snapToSurface(grid.snapToGrid(positionPreSnap, false, firstEntityProps.dimensions, - firstEntityProps.registrationPoint), firstEntityProps.dimensions, firstEntityProps.registrationPoint); - deltaPosition = Vec3.subtract(position, firstEntityProps.position); - } - - if (!Vec3.equal(deltaPosition, Vec3.ZERO)) { - for (var editEntityIndex = 0, numEntities = pastedEntityIDs.length; editEntityIndex < numEntities; editEntityIndex++) { - if (Uuid.isNull(entityParentIDs[editEntityIndex])) { - Entities.editEntity(pastedEntityIDs[editEntityIndex], { - position: Vec3.sum(deltaPosition, entityPositions[editEntityIndex]) - }); - } - } - } - } - - if (isActive) { - selectionManager.setSelections(pastedEntityIDs, this); - } - } else { - Window.notifyEditError("Can't import entities: entities would be out of bounds."); - } - } else { - Window.notifyEditError("There was an error importing the entity file."); - } - - Overlays.editOverlay(importingSVOTextOverlay, { - visible: false - }); - Overlays.editOverlay(importingSVOImageOverlay, { - visible: false - }); -} -Window.svoImportRequested.connect(importSVO); - -Menu.menuItemEvent.connect(handleMenuEvent); - -var keyPressEvent = function (event) { - if (isActive) { - cameraManager.keyPressEvent(event); - } -}; -var keyReleaseEvent = function (event) { - if (isActive) { - cameraManager.keyReleaseEvent(event); - } -}; -Controller.keyReleaseEvent.connect(keyReleaseEvent); -Controller.keyPressEvent.connect(keyPressEvent); - -function deleteKey(value) { - if (value === 0) { // on release - deleteSelectedEntities(); - } -} -function deselectKey(value) { - if (value === 0) { // on release - selectionManager.clearSelections(this); - } -} -function toggleKey(value) { - if (value === 0) { // on release - selectionDisplay.toggleSpaceMode(); - } -} -function focusKey(value) { - if (value === 0) { // on release - cameraManager.enable(); - if (selectionManager.hasSelection()) { - cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - } - } -} -function gridKey(value) { - if (value === 0) { // on release - if (selectionManager.hasSelection()) { - grid.moveToSelection(); - } - } -} -function recursiveAdd(newParentID, parentData) { - if (parentData.children !== undefined) { - var children = parentData.children; - for (var i = 0; i < children.length; i++) { - var childProperties = children[i].properties; - childProperties.parentID = newParentID; - var newChildID = Entities.addEntity(childProperties); - recursiveAdd(newChildID, children[i]); - } - } -} - -var UndoHistory = function(onUpdate) { - this.history = []; - // The current position is the index of the last executed action in the history array. - // - // -1 0 1 2 3 <- position - // A B C D <- actions in history - // - // If our lastExecutedIndex is 1, the last executed action is B. - // If we undo, we undo B (index 1). If we redo, we redo C (index 2). - this.lastExecutedIndex = -1; - this.enabled = true; - this.onUpdate = onUpdate; -}; - -UndoHistory.prototype.pushCommand = function(undoFn, undoArgs, redoFn, redoArgs) { - if (!this.enabled) { - return; - } - // Delete any history following the last executed action. - this.history.splice(this.lastExecutedIndex + 1); - this.history.push({ - undoFn: undoFn, - undoArgs: undoArgs, - redoFn: redoFn, - redoArgs: redoArgs - }); - this.lastExecutedIndex++; - - if (this.onUpdate) { - this.onUpdate(); - } -}; -UndoHistory.prototype.setEnabled = function(enabled) { - this.enabled = enabled; - if (this.onUpdate) { - this.onUpdate(); - } -}; -UndoHistory.prototype.canUndo = function() { - return this.enabled && this.lastExecutedIndex >= 0; -}; -UndoHistory.prototype.canRedo = function() { - return this.enabled && this.lastExecutedIndex < this.history.length - 1; -}; -UndoHistory.prototype.undo = function() { - if (!this.canUndo()) { - console.warn("Cannot undo action"); - return; - } - - var command = this.history[this.lastExecutedIndex]; - command.undoFn(command.undoArgs); - this.lastExecutedIndex--; - - if (this.onUpdate) { - this.onUpdate(); - } -}; -UndoHistory.prototype.redo = function() { - if (!this.canRedo()) { - console.warn("Cannot redo action"); - return; - } - - var command = this.history[this.lastExecutedIndex + 1]; - command.redoFn(command.redoArgs); - this.lastExecutedIndex++; - - if (this.onUpdate) { - this.onUpdate(); - } -}; - -function updateUndoRedoMenuItems() { - Menu.setMenuEnabled("Edit > Undo", undoHistory.canUndo()); - Menu.setMenuEnabled("Edit > Redo", undoHistory.canRedo()); -} -var undoHistory = new UndoHistory(updateUndoRedoMenuItems); -updateUndoRedoMenuItems(); - -// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently -// possible to create an entity with a specific id, earlier undo commands to the deleted entity -// will fail if there isn't a way to find the new entity id. -var DELETED_ENTITY_MAP = {}; - -function applyEntityProperties(data) { - var editEntities = data.editEntities; - var createEntities = data.createEntities; - var deleteEntities = data.deleteEntities; - var selectedEntityIDs = []; - var selectEdits = createEntities.length === 0 || !data.selectCreated; - var i, entityID, entityProperties; - for (i = 0; i < createEntities.length; i++) { - entityID = createEntities[i].entityID; - entityProperties = createEntities[i].properties; - var newEntityID = Entities.addEntity(entityProperties); - recursiveAdd(newEntityID, createEntities[i]); - DELETED_ENTITY_MAP[entityID] = newEntityID; - if (data.selectCreated) { - selectedEntityIDs.push(newEntityID); - } - } - for (i = 0; i < deleteEntities.length; i++) { - entityID = deleteEntities[i].entityID; - if (DELETED_ENTITY_MAP[entityID] !== undefined) { - entityID = DELETED_ENTITY_MAP[entityID]; - } - Entities.deleteEntity(entityID); - var index = selectedEntityIDs.indexOf(entityID); - if (index >= 0) { - selectedEntityIDs.splice(index, 1); - } - } - for (i = 0; i < editEntities.length; i++) { - entityID = editEntities[i].entityID; - if (DELETED_ENTITY_MAP[entityID] !== undefined) { - entityID = DELETED_ENTITY_MAP[entityID]; - } - entityProperties = editEntities[i].properties; - if (entityProperties !== null) { - Entities.editEntity(entityID, entityProperties); - } - if (selectEdits) { - selectedEntityIDs.push(entityID); - } - } - - // We might be getting an undo while edit.js is disabled. If that is the case, don't set - // our selections, causing the edit widgets to display. - if (isActive) { - selectionManager.setSelections(selectedEntityIDs, this); - selectionManager.saveProperties(); - } -} - -// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the -// redo command, and the saved properties for the undo command. Also, include create and delete entity data. -function pushCommandForSelections(createdEntityData, deletedEntityData, doNotSaveEditProperties) { - doNotSaveEditProperties = false; - var undoData = { - editEntities: [], - createEntities: deletedEntityData || [], - deleteEntities: createdEntityData || [], - selectCreated: true - }; - var redoData = { - editEntities: [], - createEntities: createdEntityData || [], - deleteEntities: deletedEntityData || [], - selectCreated: true - }; - for (var i = 0; i < SelectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - var initialProperties = SelectionManager.savedProperties[entityID]; - var currentProperties = null; - if (!initialProperties) { - continue; - } - - if (doNotSaveEditProperties) { - initialProperties = null; - } else { - currentProperties = Entities.getEntityProperties(entityID); - } - - undoData.editEntities.push({ - entityID: entityID, - properties: initialProperties - }); - redoData.editEntities.push({ - entityID: entityID, - properties: currentProperties - }); - } - undoHistory.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); -} - -var ServerScriptStatusMonitor = function(entityID, statusCallback) { - var self = this; - - self.entityID = entityID; - self.active = true; - self.sendRequestTimerID = null; - - var onStatusReceived = function(success, isRunning, status, errorInfo) { - if (self.active) { - statusCallback({ - statusRetrieved: success, - isRunning: isRunning, - status: status, - errorInfo: errorInfo - }); - self.sendRequestTimerID = Script.setTimeout(function() { - if (self.active) { - Entities.getServerScriptStatus(entityID, onStatusReceived); - } - }, 1000); - } - }; - self.stop = function() { - self.active = false; - }; - - Entities.getServerScriptStatus(entityID, onStatusReceived); -}; - -var PropertiesTool = function (opts) { - var that = {}; - - var webView = null; - webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - webView.setVisible = function(value) {}; - - var visible = false; - - // This keeps track of the last entity ID that was selected. If multiple entities - // are selected or if no entity is selected this will be `null`. - var currentSelectedEntityID = null; - var statusMonitor = null; - var blockPropertyUpdates = false; - - that.setVisible = function (newVisible) { - visible = newVisible; - webView.setVisible(shouldUseEditTabletApp() && visible); - createToolsWindow.setVisible(!shouldUseEditTabletApp() && visible); - }; - - that.setVisible(false); - - function emitScriptEvent(data) { - var dataString = JSON.stringify(data); - webView.emitScriptEvent(dataString); - createToolsWindow.emitScriptEvent(dataString); - } - - function updateScriptStatus(info) { - info.type = "server_script_status"; - emitScriptEvent(info); - } - - function resetScriptStatus() { - updateScriptStatus({ - statusRetrieved: undefined, - isRunning: undefined, - status: "", - errorInfo: "" - }); - } - - that.setSpaceMode = function(spaceMode) { - emitScriptEvent({ - type: 'setSpaceMode', - spaceMode: spaceMode - }) - }; - - function updateSelections(selectionUpdated, caller) { - if (blockPropertyUpdates) { - return; - } - - var data = { - type: 'update', - spaceMode: selectionDisplay.getSpaceMode(), - isPropertiesToolUpdate: caller === this, - }; - - if (selectionUpdated) { - resetScriptStatus(); - - if (selectionManager.selections.length !== 1) { - if (statusMonitor !== null) { - statusMonitor.stop(); - statusMonitor = null; - } - currentSelectedEntityID = null; - } else if (currentSelectedEntityID !== selectionManager.selections[0]) { - if (statusMonitor !== null) { - statusMonitor.stop(); - } - var entityID = selectionManager.selections[0]; - currentSelectedEntityID = entityID; - statusMonitor = new ServerScriptStatusMonitor(entityID, updateScriptStatus); - } - } - - var selections = []; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entity = {}; - entity.id = selectionManager.selections[i]; - entity.properties = Entities.getEntityProperties(selectionManager.selections[i]); - if (entity.properties.rotation !== undefined) { - entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); - } - if (entity.properties.localRotation !== undefined) { - entity.properties.localRotation = Quat.safeEulerAngles(entity.properties.localRotation); - } - if (entity.properties.emitOrientation !== undefined) { - entity.properties.emitOrientation = Quat.safeEulerAngles(entity.properties.emitOrientation); - } - if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) { - entity.properties.keyLight.direction = Vec3.toPolar(entity.properties.keyLight.direction); - entity.properties.keyLight.direction.z = 0.0; - } - selections.push(entity); - } - data.selections = selections; - - emitScriptEvent(data); - } - selectionManager.addEventListener(updateSelections, this); - - - var onWebEventReceived = function(data) { - try { - data = JSON.parse(data); - } catch(e) { - return; - } - var i, properties, dY, diff, newPosition; - if (data.type === "update") { - - if (data.properties || data.propertiesMap) { - var propertiesMap = data.propertiesMap; - if (propertiesMap === undefined) { - propertiesMap = [{ - entityIDs: data.ids, - properties: data.properties, - }]; - } - - var sendListUpdate = false; - propertiesMap.forEach(function(propertiesObject) { - var properties = propertiesObject.properties; - var updateEntityIDs = propertiesObject.entityIDs; - if (properties.dynamic === false) { - // this object is leaving dynamic, so we zero its velocities - properties.localVelocity = Vec3.ZERO; - properties.localAngularVelocity = Vec3.ZERO; - } - if (properties.rotation !== undefined) { - properties.rotation = Quat.fromVec3Degrees(properties.rotation); - } - if (properties.localRotation !== undefined) { - properties.localRotation = Quat.fromVec3Degrees(properties.localRotation); - } - if (properties.emitOrientation !== undefined) { - properties.emitOrientation = Quat.fromVec3Degrees(properties.emitOrientation); - } - if (properties.keyLight !== undefined && properties.keyLight.direction !== undefined) { - var currentKeyLightDirection = Vec3.toPolar(Entities.getEntityProperties(selectionManager.selections[0], ['keyLight.direction']).keyLight.direction); - if (properties.keyLight.direction.x === undefined) { - properties.keyLight.direction.x = currentKeyLightDirection.x; - } - if (properties.keyLight.direction.y === undefined) { - properties.keyLight.direction.y = currentKeyLightDirection.y; - } - properties.keyLight.direction = Vec3.fromPolar(properties.keyLight.direction.x, properties.keyLight.direction.y); - } - - updateEntityIDs.forEach(function (entityID) { - Entities.editEntity(entityID, properties); - }); - - if (properties.name !== undefined || properties.modelURL !== undefined || properties.materialURL !== undefined || - properties.visible !== undefined || properties.locked !== undefined) { - - sendListUpdate = true; - } - - }); - if (sendListUpdate) { - entityListTool.sendUpdate(); - } - } - - - if (data.onlyUpdateEntities) { - blockPropertyUpdates = true; - } else { - pushCommandForSelections(); - SelectionManager.saveProperties(); - } - selectionManager._update(false, this); - blockPropertyUpdates = false; - } else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') { - data.ids.forEach(function(entityID) { - Entities.editEntity(entityID, data.properties); - }); - } else if (data.type === "showMarketplace") { - showMarketplace(); - } else if (data.type === "action") { - if (data.action === "moveSelectionToGrid") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); - diff = { - x: 0, - y: dY, - z: 0 - }; - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition - }); - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "moveAllToGrid") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; - dY = grid.getOrigin().y - bottomY; - diff = { - x: 0, - y: dY, - z: 0 - }; - newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition - }); - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "resetToNaturalDimensions") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var naturalDimensions = properties.naturalDimensions; - - // If any of the natural dimensions are not 0, resize - if (properties.type === "Model" && naturalDimensions.x === 0 && naturalDimensions.y === 0 && - naturalDimensions.z === 0) { - Window.notifyEditError("Cannot reset entity to its natural dimensions: Model URL" + - " is invalid or the model has not yet been loaded."); - } else { - Entities.editEntity(selectionManager.selections[i], { - dimensions: properties.naturalDimensions - }); - } - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "previewCamera") { - if (selectionManager.hasSelection()) { - Camera.mode = "entity"; - Camera.cameraEntity = selectionManager.selections[0]; - } - } else if (data.action === "rescaleDimensions") { - var multiplier = data.percentage / 100.0; - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - Entities.editEntity(selectionManager.selections[i], { - dimensions: Vec3.multiply(multiplier, properties.dimensions) - }); - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "reloadClientScripts") { - if (selectionManager.hasSelection()) { - var timestamp = Date.now(); - for (i = 0; i < selectionManager.selections.length; i++) { - Entities.editEntity(selectionManager.selections[i], { - scriptTimestamp: timestamp - }); - } - } - } else if (data.action === "reloadServerScripts") { - if (selectionManager.hasSelection()) { - for (i = 0; i < selectionManager.selections.length; i++) { - Entities.reloadServerScripts(selectionManager.selections[i]); - } - } - } - } else if (data.type === "propertiesPageReady") { - updateSelections(true); - } else if (data.type === "tooltipsRequest") { - emitScriptEvent({ - type: 'tooltipsReply', - tooltips: Script.require('./assets/data/createAppTooltips.json'), - hmdActive: HMD.active, - }); - } else if (data.type === "propertyRangeRequest") { - var propertyRanges = {}; - data.properties.forEach(function (property) { - propertyRanges[property] = Entities.getPropertyInfo(property); - }); - emitScriptEvent({ - type: 'propertyRangeReply', - propertyRanges: propertyRanges, - }); - } else if (data.type === "materialTargetRequest") { - var parentModelData; - var properties = Entities.getEntityProperties(data.entityID, ["type", "parentID"]); - if (properties.type === "Material" && properties.parentID !== Uuid.NULL) { - var parentType = Entities.getEntityProperties(properties.parentID, ["type"]).type; - if (parentType === "Model" || Entities.getNestableType(properties.parentID) === "avatar") { - parentModelData = Graphics.getModel(properties.parentID); - } else if (parentType === "Shape" || parentType === "Box" || parentType === "Sphere") { - parentModelData = {}; - parentModelData.numMeshes = 1; - parentModelData.materialNames = []; - } - } - emitScriptEvent({ - type: 'materialTargetReply', - entityID: data.entityID, - materialTargetData: parentModelData, - }); - } - }; - - HMD.displayModeChanged.connect(function() { - emitScriptEvent({ - type: 'hmdActiveChanged', - hmdActive: HMD.active, - }); - }); - - createToolsWindow.webEventReceived.addListener(this, onWebEventReceived); - - webView.webEventReceived.connect(this, onWebEventReceived); - - return that; -}; - - -var PopupMenu = function () { - var self = this; - - var MENU_ITEM_HEIGHT = 21; - var MENU_ITEM_SPACING = 1; - var TEXT_MARGIN = 7; - - var overlays = []; - var overlayInfo = {}; - - var visible = false; - - var upColor = { - red: 0, - green: 0, - blue: 0 - }; - var downColor = { - red: 192, - green: 192, - blue: 192 - }; - var overColor = { - red: 128, - green: 128, - blue: 128 - }; - - self.onSelectMenuItem = function () {}; - - self.addMenuItem = function (name) { - var id = Overlays.addOverlay("text", { - text: name, - backgroundAlpha: 1.0, - backgroundColor: upColor, - topMargin: TEXT_MARGIN, - leftMargin: TEXT_MARGIN, - width: 210, - height: MENU_ITEM_HEIGHT, - font: { - size: 12 - }, - visible: false - }); - overlays.push(id); - overlayInfo[id] = { - name: name - }; - return id; - }; - - self.updateMenuItemText = function (id, newText) { - Overlays.editOverlay(id, { - text: newText - }); - }; - - self.setPosition = function (x, y) { - for (var key in overlayInfo) { - Overlays.editOverlay(key, { - x: x, - y: y - }); - y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING; - } - }; - - self.onSelected = function () {}; - - var pressingOverlay = null; - var hoveringOverlay = null; - - self.mousePressEvent = function (event) { - if (event.isLeftButton) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (overlay in overlayInfo) { - pressingOverlay = overlay; - Overlays.editOverlay(pressingOverlay, { - backgroundColor: downColor - }); - } else { - self.hide(); - } - return false; - } - }; - self.mouseMoveEvent = function (event) { - if (visible) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (!pressingOverlay) { - if (hoveringOverlay !== null && overlay !== hoveringOverlay) { - Overlays.editOverlay(hoveringOverlay, { - backgroundColor: upColor - }); - hoveringOverlay = null; - } - if (overlay !== hoveringOverlay && overlay in overlayInfo) { - Overlays.editOverlay(overlay, { - backgroundColor: overColor - }); - hoveringOverlay = overlay; - } - } - } - return false; - }; - self.mouseReleaseEvent = function (event) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (pressingOverlay !== null && pressingOverlay !== undefined) { - if (overlay === pressingOverlay) { - self.onSelectMenuItem(overlayInfo[overlay].name); - } - Overlays.editOverlay(pressingOverlay, { - backgroundColor: upColor - }); - pressingOverlay = null; - self.hide(); - } - }; - - self.setVisible = function (newVisible) { - if (newVisible !== visible) { - visible = newVisible; - for (var key in overlayInfo) { - Overlays.editOverlay(key, { - visible: newVisible - }); - } - } - }; - self.show = function () { - self.setVisible(true); - }; - self.hide = function () { - self.setVisible(false); - }; - - function cleanup() { - ContextOverlay.enabled = true; - 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); - - Entities.canRezChanged.disconnect(checkEditPermissionsAndUpdate); - Entities.canRezTmpChanged.disconnect(checkEditPermissionsAndUpdate); - Entities.canRezCertifiedChanged.disconnect(checkEditPermissionsAndUpdate); - Entities.canRezTmpCertifiedChanged.disconnect(checkEditPermissionsAndUpdate); - } - - Controller.mousePressEvent.connect(self.mousePressEvent); - Controller.mouseMoveEvent.connect(self.mouseMoveEvent); - Controller.mouseReleaseEvent.connect(self.mouseReleaseEvent); - Script.scriptEnding.connect(cleanup); - - return this; -}; - -function whenPressed(fn) { - return function(value) { - if (value > 0) { - fn(); - } - }; -} - -function whenReleased(fn) { - return function(value) { - if (value === 0) { - fn(); - } - }; -} - -var isOnMacPlatform = Controller.getValue(Controller.Hardware.Application.PlatformMac); - -var mapping = Controller.newMapping(CONTROLLER_MAPPING_NAME); -if (isOnMacPlatform) { - mapping.from([Controller.Hardware.Keyboard.Backspace]).to(deleteKey); -} else { - mapping.from([Controller.Hardware.Keyboard.Delete]).to(deleteKey); -} -mapping.from([Controller.Hardware.Keyboard.T]).to(toggleKey); -mapping.from([Controller.Hardware.Keyboard.F]).to(focusKey); -mapping.from([Controller.Hardware.Keyboard.G]).to(gridKey); -mapping.from([Controller.Hardware.Keyboard.X]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.cutSelectedEntities() })); -mapping.from([Controller.Hardware.Keyboard.C]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.copySelectedEntities() })); -mapping.from([Controller.Hardware.Keyboard.V]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.pasteEntities() })); -mapping.from([Controller.Hardware.Keyboard.D]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.duplicateSelection() })); - -// Bind undo to ctrl-shift-z to maintain backwards-compatibility -mapping.from([Controller.Hardware.Keyboard.Z]) - .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift]) - .to(whenPressed(function() { undoHistory.redo() })); - - -mapping.from([Controller.Hardware.Keyboard.P]) - .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift]) - .to(whenReleased(function() { unparentSelectedEntities(); })); - -mapping.from([Controller.Hardware.Keyboard.P]) - .when([Controller.Hardware.Keyboard.Control, !Controller.Hardware.Keyboard.Shift]) - .to(whenReleased(function() { parentSelectedEntities(); })); - -keyUpEventFromUIWindow = function(keyUpEvent) { - var WANT_DEBUG_MISSING_SHORTCUTS = false; - - var pressedValue = 0.0; - - if ((!isOnMacPlatform && keyUpEvent.keyCodeString === "Delete") - || (isOnMacPlatform && keyUpEvent.keyCodeString === "Backspace")) { - - deleteKey(pressedValue); - } else if (keyUpEvent.keyCodeString === "T") { - toggleKey(pressedValue); - } else if (keyUpEvent.keyCodeString === "F") { - focusKey(pressedValue); - } else if (keyUpEvent.keyCodeString === "G") { - gridKey(pressedValue); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "X") { - selectionManager.cutSelectedEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "C") { - selectionManager.copySelectedEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "V") { - selectionManager.pasteEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "D") { - selectionManager.duplicateSelection(); - } else if (!isOnMacPlatform && keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") { - undoHistory.undo(); // undo is only handled via handleMenuItem on Mac - } else if (keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { - parentSelectedEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { - unparentSelectedEntities(); - } else if (!isOnMacPlatform && - ((keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") || - (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "Y"))) { - undoHistory.redo(); // redo is only handled via handleMenuItem on Mac - } else if (WANT_DEBUG_MISSING_SHORTCUTS) { - console.warn("unhandled key event: " + JSON.stringify(keyUpEvent)) - } -}; - -var propertyMenu = new PopupMenu(); - -propertyMenu.onSelectMenuItem = function (name) { - - if (propertyMenu.marketplaceID) { - showMarketplace(propertyMenu.marketplaceID); - } -}; - -var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); - -var propertiesTool = new PropertiesTool(); - -selectionDisplay.onSpaceModeChange = function(spaceMode) { - entityListTool.setSpaceMode(spaceMode); - propertiesTool.setSpaceMode(spaceMode); -}; - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/html/entityList.html b/scripts/simplifiedUI/system/html/entityList.html deleted file mode 100644 index 986e5c09b0..0000000000 --- a/scripts/simplifiedUI/system/html/entityList.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - Entity List - - - - - - - - - - - - - -
- -
- - -
- - - -
-
-
-
-
- -
-
-
- -
- - -
-
-
-
- Y -
- -
- - -
-
-
- - - - -
-
-
- -
-
-
- -
-
-
- There are no entities to display. Please check your filters or create an entity to begin. -
-
-
- - - diff --git a/scripts/simplifiedUI/system/html/entityProperties.html b/scripts/simplifiedUI/system/html/entityProperties.html deleted file mode 100644 index 67f03a33a2..0000000000 --- a/scripts/simplifiedUI/system/html/entityProperties.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Properties - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/scripts/simplifiedUI/system/html/js/createAppTooltip.js b/scripts/simplifiedUI/system/html/js/createAppTooltip.js deleted file mode 100644 index 3eb206d8a3..0000000000 --- a/scripts/simplifiedUI/system/html/js/createAppTooltip.js +++ /dev/null @@ -1,116 +0,0 @@ -// createAppTooltip.js -// -// Created by Thijs Wenker on 17 Oct 2018 -// Copyright 2018 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 - -const CREATE_APP_TOOLTIP_OFFSET = 20; -const TOOLTIP_DELAY = 500; // ms -const TOOLTIP_DEBUG = false; - -function CreateAppTooltip() { - this._tooltipData = null; - this._tooltipDiv = null; - this._delayTimeout = null; - this._isEnabled = false; -} - -CreateAppTooltip.prototype = { - _tooltipData: null, - _tooltipDiv: null, - _delayTimeout: null, - _isEnabled: null, - - _removeTooltipIfExists: function() { - if (this._delayTimeout !== null) { - window.clearTimeout(this._delayTimeout); - this._delayTimeout = null; - } - - if (this._tooltipDiv !== null) { - this._tooltipDiv.remove(); - this._tooltipDiv = null; - } - }, - - setIsEnabled: function(isEnabled) { - this._isEnabled = isEnabled; - }, - - setTooltipData: function(tooltipData) { - this._tooltipData = tooltipData; - }, - - registerTooltipElement: function(element, tooltipID, jsPropertyName) { - element.addEventListener("mouseover", function() { - if (!this._isEnabled) { - return; - } - - this._removeTooltipIfExists(); - - this._delayTimeout = window.setTimeout(function() { - let tooltipData = this._tooltipData[tooltipID]; - - if (!tooltipData || tooltipData.tooltip === "") { - if (!TOOLTIP_DEBUG) { - return; - } - tooltipData = { tooltip: 'PLEASE SET THIS TOOLTIP' }; - } - - let elementRect = element.getBoundingClientRect(); - let elTip = document.createElement("div"); - elTip.className = "create-app-tooltip"; - - let elTipDescription = document.createElement("div"); - elTipDescription.className = "create-app-tooltip-description"; - elTipDescription.innerText = tooltipData.tooltip; - elTip.appendChild(elTipDescription); - - let jsAttribute = jsPropertyName; - if (tooltipData.jsPropertyName) { - jsAttribute = tooltipData.jsPropertyName; - } - - if (!tooltipData.skipJSProperty) { - let elTipJSAttribute = document.createElement("div"); - elTipJSAttribute.className = "create-app-tooltip-js-attribute"; - elTipJSAttribute.innerText = `JS Attribute: ${jsAttribute}`; - elTip.appendChild(elTipJSAttribute); - } - - document.body.appendChild(elTip); - - let elementTop = window.pageYOffset + elementRect.top; - - let desiredTooltipTop = elementTop + element.clientHeight + CREATE_APP_TOOLTIP_OFFSET; - let desiredTooltipLeft = window.pageXOffset + elementRect.left; - - if ((window.innerHeight + window.pageYOffset) < (desiredTooltipTop + elTip.clientHeight)) { - // show above when otherwise out of bounds - elTip.style.top = elementTop - CREATE_APP_TOOLTIP_OFFSET - elTip.clientHeight; - } else { - // show tooltip below by default - elTip.style.top = desiredTooltipTop; - } - if ((window.innerWidth + window.pageXOffset) < (desiredTooltipLeft + elTip.clientWidth)) { - elTip.style.left = document.body.clientWidth + window.pageXOffset - elTip.offsetWidth; - } else { - elTip.style.left = desiredTooltipLeft; - } - - this._tooltipDiv = elTip; - }.bind(this), TOOLTIP_DELAY); - }.bind(this), false); - element.addEventListener("mouseout", function() { - if (!this._isEnabled) { - return; - } - - this._removeTooltipIfExists(); - }.bind(this), false); - } -}; diff --git a/scripts/simplifiedUI/system/libraries/EditEntityList.qml b/scripts/simplifiedUI/system/libraries/EditEntityList.qml deleted file mode 100644 index 4fc5ff19ef..0000000000 --- a/scripts/simplifiedUI/system/libraries/EditEntityList.qml +++ /dev/null @@ -1,12 +0,0 @@ -import QtQuick 2.7 -import QtQuick.Controls 2.2 -import QtWebChannel 1.0 -import QtGraphicalEffects 1.0 -import "qrc:///qml/controls" as HifiControls - -HifiControls.WebView { - id: entityListToolWebView - url: Qt.resolvedUrl("../html/entityList.html") - enabled: true - blurOnCtrlShift: false -} diff --git a/scripts/simplifiedUI/system/libraries/entityList.js b/scripts/simplifiedUI/system/libraries/entityList.js deleted file mode 100644 index 585e4e06a5..0000000000 --- a/scripts/simplifiedUI/system/libraries/entityList.js +++ /dev/null @@ -1,330 +0,0 @@ -"use strict"; - -// entityList.js -// -// Copyright 2014 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 -// - -/* global EntityListTool, Tablet, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages, - cameraManager, MENU_EASE_ON_FOCUS, deleteSelectedEntities, toggleSelectedEntitiesLocked, toggleSelectedEntitiesVisible, - keyUpEventFromUIWindow, Script, SelectionDisplay, SelectionManager, Clipboard */ - -var PROFILING_ENABLED = false; -var profileIndent = ''; -const PROFILE_NOOP = function(_name, fn, args) { - fn.apply(this, args); -}; -const PROFILE = !PROFILING_ENABLED ? PROFILE_NOOP : function(name, fn, args) { - console.log("PROFILE-Script " + profileIndent + "(" + name + ") Begin"); - var previousIndent = profileIndent; - profileIndent += ' '; - var before = Date.now(); - fn.apply(this, args); - var delta = Date.now() - before; - profileIndent = previousIndent; - console.log("PROFILE-Script " + profileIndent + "(" + name + ") End " + delta + "ms"); -}; - -EntityListTool = function(shouldUseEditTabletApp) { - var that = {}; - - var CreateWindow = Script.require('../modules/createWindow.js'); - - var TITLE_OFFSET = 60; - var ENTITY_LIST_WIDTH = 495; - var MAX_DEFAULT_CREATE_TOOLS_HEIGHT = 778; - var entityListWindow = new CreateWindow( - Script.resolvePath("../create/EditEntityList.qml"), - 'Entity List', - 'com.highfidelity.create.entityListWindow', - function () { - var windowHeight = Window.innerHeight - TITLE_OFFSET; - if (windowHeight > MAX_DEFAULT_CREATE_TOOLS_HEIGHT) { - windowHeight = MAX_DEFAULT_CREATE_TOOLS_HEIGHT; - } - return { - size: { - x: ENTITY_LIST_WIDTH, - y: windowHeight - }, - position: { - x: Window.x, - y: Window.y + TITLE_OFFSET - } - }; - }, - false - ); - - var webView = null; - webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - webView.setVisible = function(value){ }; - - var filterInView = false; - var searchRadius = 100; - - var visible = false; - - that.webView = webView; - - that.setVisible = function(newVisible) { - visible = newVisible; - webView.setVisible(shouldUseEditTabletApp() && visible); - entityListWindow.setVisible(!shouldUseEditTabletApp() && visible); - }; - - that.isVisible = function() { - return entityListWindow.isVisible(); - }; - - that.setVisible(false); - - function emitJSONScriptEvent(data) { - var dataString; - PROFILE("Script-JSON.stringify", function() { - dataString = JSON.stringify(data); - }); - PROFILE("Script-emitScriptEvent", function() { - webView.emitScriptEvent(dataString); - if (entityListWindow.window) { - entityListWindow.window.emitScriptEvent(dataString); - } - }); - } - - that.toggleVisible = function() { - that.setVisible(!visible); - }; - - selectionManager.addEventListener(function(isSelectionUpdate, caller) { - if (caller === that) { - // ignore events that we emitted from the entity list itself - return; - } - var selectedIDs = []; - - for (var i = 0; i < selectionManager.selections.length; i++) { - selectedIDs.push(selectionManager.selections[i]); - } - - emitJSONScriptEvent({ - type: 'selectionUpdate', - selectedIDs: selectedIDs - }); - }); - - that.setSpaceMode = function(spaceMode) { - emitJSONScriptEvent({ - type: 'setSpaceMode', - spaceMode: spaceMode - }); - }; - - that.clearEntityList = function() { - emitJSONScriptEvent({ - type: 'clearEntityList' - }); - }; - - that.removeEntities = function (deletedIDs, selectedIDs) { - emitJSONScriptEvent({ - type: 'removeEntities', - deletedIDs: deletedIDs, - selectedIDs: selectedIDs - }); - }; - - that.deleteEntities = function (deletedIDs) { - emitJSONScriptEvent({ - type: "deleted", - ids: deletedIDs - }); - }; - - function valueIfDefined(value) { - return value !== undefined ? value : ""; - } - - function entityIsBaked(properties) { - if (properties.type === "Model") { - var lowerModelURL = properties.modelURL.toLowerCase(); - return lowerModelURL.endsWith(".baked.fbx") || lowerModelURL.endsWith(".baked.fst"); - } else if (properties.type === "Zone") { - var lowerSkyboxURL = properties.skybox ? properties.skybox.url.toLowerCase() : ""; - var lowerAmbientURL = properties.ambientLight ? properties.ambientLight.ambientURL.toLowerCase() : ""; - return (lowerSkyboxURL === "" || lowerSkyboxURL.endsWith(".texmeta.json")) && - (lowerAmbientURL === "" || lowerAmbientURL.endsWith(".texmeta.json")); - } else { - return false; - } - } - - that.sendUpdate = function() { - PROFILE('Script-sendUpdate', function() { - var entities = []; - - var ids; - PROFILE("findEntities", function() { - if (filterInView) { - ids = Entities.findEntitiesInFrustum(Camera.frustum); - } else { - ids = Entities.findEntities(MyAvatar.position, searchRadius); - } - }); - - var cameraPosition = Camera.position; - PROFILE("getMultipleProperties", function () { - var multipleProperties = Entities.getMultipleEntityProperties(ids, ['name', 'type', 'locked', - 'visible', 'renderInfo', 'modelURL', 'materialURL', 'imageURL', 'script', 'certificateID', - 'skybox.url', 'ambientLight.url']); - for (var i = 0; i < multipleProperties.length; i++) { - var properties = multipleProperties[i]; - - if (!filterInView || Vec3.distance(properties.position, cameraPosition) <= searchRadius) { - var url = ""; - if (properties.type === "Model") { - url = properties.modelURL; - } else if (properties.type === "Material") { - url = properties.materialURL; - } else if (properties.type === "Image") { - url = properties.imageURL; - } - entities.push({ - id: ids[i], - name: properties.name, - type: properties.type, - url: url, - locked: properties.locked, - visible: properties.visible, - certificateID: properties.certificateID, - verticesCount: (properties.renderInfo !== undefined ? - valueIfDefined(properties.renderInfo.verticesCount) : ""), - texturesCount: (properties.renderInfo !== undefined ? - valueIfDefined(properties.renderInfo.texturesCount) : ""), - texturesSize: (properties.renderInfo !== undefined ? - valueIfDefined(properties.renderInfo.texturesSize) : ""), - hasTransparent: (properties.renderInfo !== undefined ? - valueIfDefined(properties.renderInfo.hasTransparent) : ""), - isBaked: entityIsBaked(properties), - drawCalls: (properties.renderInfo !== undefined ? - valueIfDefined(properties.renderInfo.drawCalls) : ""), - hasScript: properties.script !== "" - }); - } - } - }); - - var selectedIDs = []; - for (var j = 0; j < selectionManager.selections.length; j++) { - selectedIDs.push(selectionManager.selections[j]); - } - - emitJSONScriptEvent({ - type: "update", - entities: entities, - selectedIDs: selectedIDs, - spaceMode: SelectionDisplay.getSpaceMode(), - }); - }); - }; - - function onFileSaveChanged(filename) { - Window.saveFileChanged.disconnect(onFileSaveChanged); - if (filename !== "") { - var success = Clipboard.exportEntities(filename, selectionManager.selections); - if (!success) { - Window.notifyEditError("Export failed."); - } - } - } - - var onWebEventReceived = function(data) { - try { - data = JSON.parse(data); - } catch(e) { - print("entityList.js: Error parsing JSON"); - return; - } - - if (data.type === "selectionUpdate") { - var ids = data.entityIds; - var entityIDs = []; - for (var i = 0; i < ids.length; i++) { - entityIDs.push(ids[i]); - } - selectionManager.setSelections(entityIDs, that); - if (data.focus) { - cameraManager.enable(); - cameraManager.focus(selectionManager.worldPosition, - selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - } - } else if (data.type === "refresh") { - that.sendUpdate(); - } else if (data.type === "teleport") { - if (selectionManager.hasSelection()) { - MyAvatar.position = selectionManager.worldPosition; - } - } else if (data.type === "export") { - if (!selectionManager.hasSelection()) { - Window.notifyEditError("No entities have been selected."); - } else { - Window.saveFileChanged.connect(onFileSaveChanged); - Window.saveAsync("Select Where to Save", "", "*.json"); - } - } else if (data.type === "pal") { - var sessionIds = {}; // Collect the sessionsIds of all selected entities, w/o duplicates. - selectionManager.selections.forEach(function (id) { - var lastEditedBy = Entities.getEntityProperties(id, 'lastEditedBy').lastEditedBy; - if (lastEditedBy) { - sessionIds[lastEditedBy] = true; - } - }); - var dedupped = Object.keys(sessionIds); - if (!selectionManager.selections.length) { - Window.alert('No objects selected.'); - } else if (!dedupped.length) { - Window.alert('There were no recent users of the ' + selectionManager.selections.length + ' selected objects.'); - } else { - // No need to subscribe if we're just sending. - Messages.sendMessage('com.highfidelity.pal', JSON.stringify({method: 'select', params: [dedupped, true, false]}), 'local'); - } - } else if (data.type === "delete") { - deleteSelectedEntities(); - } else if (data.type === "toggleLocked") { - toggleSelectedEntitiesLocked(); - } else if (data.type === "toggleVisible") { - toggleSelectedEntitiesVisible(); - } else if (data.type === "filterInView") { - filterInView = data.filterInView === true; - } else if (data.type === "radius") { - searchRadius = data.radius; - } else if (data.type === "cut") { - SelectionManager.cutSelectedEntities(); - } else if (data.type === "copy") { - SelectionManager.copySelectedEntities(); - } else if (data.type === "paste") { - SelectionManager.pasteEntities(); - } else if (data.type === "duplicate") { - SelectionManager.duplicateSelection(); - that.sendUpdate(); - } else if (data.type === "rename") { - Entities.editEntity(data.entityID, {name: data.name}); - // make sure that the name also gets updated in the properties window - SelectionManager._update(); - } else if (data.type === "toggleSpaceMode") { - SelectionDisplay.toggleSpaceMode(); - } else if (data.type === 'keyUpEvent') { - keyUpEventFromUIWindow(data.keyUpEvent); - } - }; - - webView.webEventReceived.connect(onWebEventReceived); - entityListWindow.webEventReceived.addListener(onWebEventReceived); - that.interactiveWindowHidden = entityListWindow.interactiveWindowHidden; - - return that; -}; diff --git a/scripts/simplifiedUI/system/libraries/entitySelectionTool.js b/scripts/simplifiedUI/system/libraries/entitySelectionTool.js deleted file mode 100644 index 3fdc1d6652..0000000000 --- a/scripts/simplifiedUI/system/libraries/entitySelectionTool.js +++ /dev/null @@ -1,2925 +0,0 @@ -// -// entitySelectionTool.js -// examples -// -// Created by Brad hefta-Gaub on 10/1/14. -// Modified by Daniela Fontes * @DanielaFifo and Tiago Andrade @TagoWill on 4/7/2017 -// Modified by David Back on 1/9/2018 -// Copyright 2014 High Fidelity, Inc. -// -// This script implements a class useful for building tools for editing entities. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* global SelectionManager, SelectionDisplay, grid, rayPlaneIntersection, rayPlaneIntersection2, pushCommandForSelections, - getMainTabletIDs, getControllerWorldLocation, TRIGGER_ON_VALUE */ - -const SPACE_LOCAL = "local"; -const SPACE_WORLD = "world"; -const HIGHLIGHT_LIST_NAME = "editHandleHighlightList"; - -Script.include([ - "./controllers.js", - "./controllerDispatcherUtils.js", - "./utils.js" -]); - - -function deepCopy(v) { - return JSON.parse(JSON.stringify(v)); -} - -SelectionManager = (function() { - var that = {}; - - // FUNCTION: SUBSCRIBE TO UPDATE MESSAGES - function subscribeToUpdateMessages() { - Messages.subscribe("entityToolUpdates"); - Messages.messageReceived.connect(handleEntitySelectionToolUpdates); - } - - // FUNCTION: HANDLE ENTITY SELECTION TOOL UPDATES - function handleEntitySelectionToolUpdates(channel, message, sender) { - if (channel !== 'entityToolUpdates') { - return; - } - if (sender !== MyAvatar.sessionUUID) { - return; - } - - var wantDebug = false; - var messageParsed; - try { - messageParsed = JSON.parse(message); - } catch (err) { - print("ERROR: entitySelectionTool.handleEntitySelectionToolUpdates - got malformed message"); - return; - } - - if (messageParsed.method === "selectEntity") { - if (!SelectionDisplay.triggered() || SelectionDisplay.triggeredHand === messageParsed.hand) { - if (wantDebug) { - print("setting selection to " + messageParsed.entityID); - } - that.setSelections([messageParsed.entityID], that); - } - } else if (messageParsed.method === "clearSelection") { - if (!SelectionDisplay.triggered() || SelectionDisplay.triggeredHand === messageParsed.hand) { - that.clearSelections(); - } - } else if (messageParsed.method === "pointingAt") { - if (messageParsed.hand === Controller.Standard.RightHand) { - that.pointingAtDesktopWindowRight = messageParsed.desktopWindow; - that.pointingAtTabletRight = messageParsed.tablet; - } else { - that.pointingAtDesktopWindowLeft = messageParsed.desktopWindow; - that.pointingAtTabletLeft = messageParsed.tablet; - } - } - } - - subscribeToUpdateMessages(); - - // disabling this for now as it is causing rendering issues with the other handle overlays - /* - var COLOR_ORANGE_HIGHLIGHT = { red: 255, green: 99, blue: 9 }; - var editHandleOutlineStyle = { - outlineUnoccludedColor: COLOR_ORANGE_HIGHLIGHT, - outlineOccludedColor: COLOR_ORANGE_HIGHLIGHT, - fillUnoccludedColor: COLOR_ORANGE_HIGHLIGHT, - fillOccludedColor: COLOR_ORANGE_HIGHLIGHT, - outlineUnoccludedAlpha: 1, - outlineOccludedAlpha: 0, - fillUnoccludedAlpha: 0, - fillOccludedAlpha: 0, - outlineWidth: 3, - isOutlineSmooth: true - }; - Selection.enableListHighlight(HIGHLIGHT_LIST_NAME, editHandleOutlineStyle); - */ - - that.savedProperties = {}; - that.selections = []; - var listeners = []; - - that.localRotation = Quat.IDENTITY; - that.localPosition = Vec3.ZERO; - that.localDimensions = Vec3.ZERO; - that.localRegistrationPoint = Vec3.HALF; - - that.worldRotation = Quat.IDENTITY; - that.worldPosition = Vec3.ZERO; - that.worldDimensions = Vec3.ZERO; - that.worldRegistrationPoint = Vec3.HALF; - that.centerPosition = Vec3.ZERO; - - that.pointingAtDesktopWindowLeft = false; - that.pointingAtDesktopWindowRight = false; - that.pointingAtTabletLeft = false; - that.pointingAtTabletRight = false; - - that.saveProperties = function() { - that.savedProperties = {}; - for (var i = 0; i < that.selections.length; i++) { - var entityID = that.selections[i]; - that.savedProperties[entityID] = Entities.getEntityProperties(entityID); - } - }; - - that.addEventListener = function(func, thisContext) { - listeners.push({ - callback: func, - thisContext: thisContext - }); - }; - - that.hasSelection = function() { - return that.selections.length > 0; - }; - - that.setSelections = function(entityIDs, caller) { - that.selections = []; - for (var i = 0; i < entityIDs.length; i++) { - var entityID = entityIDs[i]; - that.selections.push(entityID); - Selection.addToSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID); - } - - that._update(true, caller); - }; - - that.addEntity = function(entityID, toggleSelection, caller) { - if (entityID) { - var idx = -1; - for (var i = 0; i < that.selections.length; i++) { - if (entityID === that.selections[i]) { - idx = i; - break; - } - } - if (idx === -1) { - that.selections.push(entityID); - Selection.addToSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID); - } else if (toggleSelection) { - that.selections.splice(idx, 1); - Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID); - } - } - - that._update(true, caller); - }; - - function removeEntityByID(entityID) { - var idx = that.selections.indexOf(entityID); - if (idx >= 0) { - that.selections.splice(idx, 1); - Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID); - } - } - - that.removeEntity = function (entityID, caller) { - removeEntityByID(entityID); - that._update(true, caller); - }; - - that.removeEntities = function(entityIDs, caller) { - for (var i = 0, length = entityIDs.length; i < length; i++) { - removeEntityByID(entityIDs[i]); - } - that._update(true, caller); - }; - - that.clearSelections = function(caller) { - that.selections = []; - that._update(true, caller); - }; - - that.addChildrenEntities = function(parentEntityID, entityList, entityHostType) { - var wantDebug = false; - var children = Entities.getChildrenIDs(parentEntityID); - var entityHostTypes = Entities.getMultipleEntityProperties(children, 'entityHostType'); - for (var i = 0; i < children.length; i++) { - var childID = children[i]; - - if (entityHostTypes[i].entityHostType !== entityHostType) { - if (wantDebug) { - console.log("Skipping addition of entity " + childID + " with conflicting entityHostType: " + - entityHostTypes[i].entityHostType + ", expected: " + entityHostType); - } - continue; - } - - if (entityList.indexOf(childID) < 0) { - entityList.push(childID); - } - that.addChildrenEntities(childID, entityList, entityHostType); - } - }; - - // Determine if an entity is being grabbed. - // This is mostly a heuristic - there is no perfect way to know if an entity is being - // grabbed. - // - // @return {boolean} true if the given entity with `properties` is being grabbed by an avatar - function nonDynamicEntityIsBeingGrabbedByAvatar(properties) { - if (properties.dynamic || Uuid.isNull(properties.parentID)) { - return false; - } - - var avatar = AvatarList.getAvatar(properties.parentID); - if (Uuid.isNull(avatar.sessionUUID)) { - return false; - } - - var grabJointNames = [ - 'RightHand', 'LeftHand', - '_CONTROLLER_RIGHTHAND', '_CONTROLLER_LEFTHAND', - '_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND', '_CAMERA_RELATIVE_CONTROLLER_LEFTHAND', - '_FARGRAB_RIGHTHAND', '_FARGRAB_LEFTHAND', '_FARGRAB_MOUSE' - ]; - - for (var i = 0; i < grabJointNames.length; ++i) { - if (avatar.getJointIndex(grabJointNames[i]) === properties.parentJointIndex) { - return true; - } - } - - return false; - } - - var entityClipboard = { - entities: {}, // Map of id -> properties for copied entities - position: { x: 0, y: 0, z: 0 }, - dimensions: { x: 0, y: 0, z: 0 }, - }; - - that.duplicateSelection = function() { - var entitiesToDuplicate = []; - var duplicatedEntityIDs = []; - var duplicatedChildrenWithOldParents = []; - var originalEntityToNewEntityID = []; - - SelectionManager.saveProperties(); - - // build list of entities to duplicate by including any unselected children of selected parent entities - var originalEntityIDs = Object.keys(that.savedProperties); - var entityHostTypes = Entities.getMultipleEntityProperties(originalEntityIDs, 'entityHostType'); - for (var i = 0; i < originalEntityIDs.length; i++) { - var originalEntityID = originalEntityIDs[i]; - if (entitiesToDuplicate.indexOf(originalEntityID) === -1) { - entitiesToDuplicate.push(originalEntityID); - } - that.addChildrenEntities(originalEntityID, entitiesToDuplicate, entityHostTypes[i].entityHostType); - } - - // duplicate entities from above and store their original to new entity mappings and children needing re-parenting - for (var i = 0; i < entitiesToDuplicate.length; i++) { - var originalEntityID = entitiesToDuplicate[i]; - var properties = that.savedProperties[originalEntityID]; - if (properties === undefined) { - properties = Entities.getEntityProperties(originalEntityID); - } - if (!properties.locked && (!properties.avatarEntity || properties.owningAvatarID === MyAvatar.sessionUUID)) { - if (nonDynamicEntityIsBeingGrabbedByAvatar(properties)) { - properties.parentID = null; - properties.parentJointIndex = null; - properties.localPosition = properties.position; - properties.localRotation = properties.rotation; - } - - properties.localVelocity = Vec3.ZERO; - properties.localAngularVelocity = Vec3.ZERO; - - delete properties.actionData; - var newEntityID = Entities.addEntity(properties); - - // Re-apply actions from the original entity - var actionIDs = Entities.getActionIDs(properties.id); - for (var j = 0; j < actionIDs.length; ++j) { - var actionID = actionIDs[j]; - var actionArguments = Entities.getActionArguments(properties.id, actionID); - if (actionArguments) { - var type = actionArguments.type; - if (type === 'hold' || type === 'far-grab') { - continue; - } - delete actionArguments.ttl; - Entities.addAction(type, newEntityID, actionArguments); - } - } - - duplicatedEntityIDs.push({ - entityID: newEntityID, - properties: properties - }); - if (properties.parentID !== Uuid.NULL) { - duplicatedChildrenWithOldParents[newEntityID] = properties.parentID; - } - originalEntityToNewEntityID[originalEntityID] = newEntityID; - } - } - - // re-parent duplicated children to the duplicate entities of their original parents (if they were duplicated) - Object.keys(duplicatedChildrenWithOldParents).forEach(function(childIDNeedingNewParent) { - var originalParentID = duplicatedChildrenWithOldParents[childIDNeedingNewParent]; - var newParentID = originalEntityToNewEntityID[originalParentID]; - if (newParentID) { - Entities.editEntity(childIDNeedingNewParent, { parentID: newParentID }); - for (var i = 0; i < duplicatedEntityIDs.length; i++) { - var duplicatedEntity = duplicatedEntityIDs[i]; - if (duplicatedEntity.entityID === childIDNeedingNewParent) { - duplicatedEntity.properties.parentID = newParentID; - } - } - } - }); - - return duplicatedEntityIDs; - }; - - // Create the entities in entityProperties, maintaining parent-child relationships. - // @param entityProperties {array} - Array of entity property objects - that.createEntities = function(entityProperties) { - var entitiesToCreate = []; - var createdEntityIDs = []; - var createdChildrenWithOldParents = []; - var originalEntityToNewEntityID = []; - - that.saveProperties(); - - for (var i = 0; i < entityProperties.length; ++i) { - var properties = entityProperties[i]; - if (properties.parentID in originalEntityToNewEntityID) { - properties.parentID = originalEntityToNewEntityID[properties.parentID]; - } else { - delete properties.parentID; - } - - delete properties.actionData; - var newEntityID = Entities.addEntity(properties); - - if (newEntityID) { - createdEntityIDs.push({ - entityID: newEntityID, - properties: properties - }); - if (properties.parentID !== Uuid.NULL) { - createdChildrenWithOldParents[newEntityID] = properties.parentID; - } - originalEntityToNewEntityID[properties.id] = newEntityID; - properties.id = newEntityID; - } - } - - return createdEntityIDs; - }; - - that.cutSelectedEntities = function() { - that.copySelectedEntities(); - deleteSelectedEntities(); - }; - - that.copySelectedEntities = function() { - var entityProperties = Entities.getMultipleEntityProperties(that.selections); - var entityHostTypes = Entities.getMultipleEntityProperties(that.selections, 'entityHostType'); - var entities = {}; - entityProperties.forEach(function(props) { - entities[props.id] = props; - }); - - function appendChildren(entityID, entities, entityHostType) { - var wantDebug = false; - var childrenIDs = Entities.getChildrenIDs(entityID); - var entityHostTypes = Entities.getMultipleEntityProperties(childrenIDs, 'entityHostType'); - for (var i = 0; i < childrenIDs.length; ++i) { - var id = childrenIDs[i]; - - if (entityHostTypes[i].entityHostType !== entityHostType) { - if (wantDebug) { - console.warn("Skipping addition of entity " + id + " with conflicting entityHostType: " + - entityHostTypes[i].entityHostType + ", expected: " + entityHostType); - } - continue; - } - - if (!(id in entities)) { - entities[id] = Entities.getEntityProperties(id); - appendChildren(id, entities, entityHostType); - } - } - } - - var len = entityProperties.length; - for (var i = 0; i < len; ++i) { - appendChildren(entityProperties[i].id, entities, entityHostTypes[i].entityHostType); - } - - for (var id in entities) { - var parentID = entities[id].parentID; - entities[id].root = !(parentID in entities); - } - - entityClipboard.entities = []; - - var ids = Object.keys(entities); - while (ids.length > 0) { - // Go through all remaining entities. - // If an entity does not have a parent left, move it into the list - for (var i = 0; i < ids.length; ++i) { - var id = ids[i]; - var parentID = entities[id].parentID; - if (parentID in entities) { - continue; - } - entityClipboard.entities.push(entities[id]); - delete entities[id]; - } - ids = Object.keys(entities); - } - - // Calculate size - if (entityClipboard.entities.length === 0) { - entityClipboard.dimensions = { x: 0, y: 0, z: 0 }; - entityClipboard.position = { x: 0, y: 0, z: 0 }; - } else { - var properties = entityClipboard.entities; - var brn = properties[0].boundingBox.brn; - var tfl = properties[0].boundingBox.tfl; - for (var i = 1; i < properties.length; i++) { - var bb = properties[i].boundingBox; - brn.x = Math.min(bb.brn.x, brn.x); - brn.y = Math.min(bb.brn.y, brn.y); - brn.z = Math.min(bb.brn.z, brn.z); - tfl.x = Math.max(bb.tfl.x, tfl.x); - tfl.y = Math.max(bb.tfl.y, tfl.y); - tfl.z = Math.max(bb.tfl.z, tfl.z); - } - entityClipboard.dimensions = { - x: tfl.x - brn.x, - y: tfl.y - brn.y, - z: tfl.z - brn.z - }; - entityClipboard.position = { - x: brn.x + entityClipboard.dimensions.x / 2, - y: brn.y + entityClipboard.dimensions.y / 2, - z: brn.z + entityClipboard.dimensions.z / 2 - }; - } - }; - - that.pasteEntities = function() { - var dimensions = entityClipboard.dimensions; - var maxDimension = Math.max(dimensions.x, dimensions.y, dimensions.z); - var pastePosition = getPositionToCreateEntity(maxDimension); - var deltaPosition = Vec3.subtract(pastePosition, entityClipboard.position); - - var copiedProperties = []; - var ids = []; - entityClipboard.entities.forEach(function(originalProperties) { - var properties = deepCopy(originalProperties); - if (properties.root) { - properties.position = Vec3.sum(properties.position, deltaPosition); - delete properties.localPosition; - } else { - delete properties.position; - } - copiedProperties.push(properties); - }); - - var currentSelections = deepCopy(SelectionManager.selections); - - function redo(copiedProperties) { - var created = that.createEntities(copiedProperties); - var ids = []; - for (var i = 0; i < created.length; ++i) { - ids.push(created[i].entityID); - } - SelectionManager.setSelections(ids); - } - - function undo(copiedProperties) { - for (var i = 0; i < copiedProperties.length; ++i) { - Entities.deleteEntity(copiedProperties[i].id); - } - SelectionManager.setSelections(currentSelections); - } - - redo(copiedProperties); - undoHistory.pushCommand(undo, copiedProperties, redo, copiedProperties); - }; - - that._update = function(selectionUpdated, caller) { - var properties = null; - if (that.selections.length === 0) { - that.localDimensions = null; - that.localPosition = null; - that.worldDimensions = null; - that.worldPosition = null; - that.worldRotation = null; - } else if (that.selections.length === 1) { - properties = Entities.getEntityProperties(that.selections[0], - ['dimensions', 'position', 'rotation', 'registrationPoint', 'boundingBox', 'type']); - that.localDimensions = properties.dimensions; - that.localPosition = properties.position; - that.localRotation = properties.rotation; - that.localRegistrationPoint = properties.registrationPoint; - - that.worldDimensions = properties.boundingBox.dimensions; - that.worldPosition = properties.boundingBox.center; - that.worldRotation = Quat.IDENTITY; - - that.entityType = properties.type; - - if (selectionUpdated) { - SelectionDisplay.useDesiredSpaceMode(); - } - } else { - properties = Entities.getEntityProperties(that.selections[0], ['type', 'boundingBox']); - - that.entityType = properties.type; - - var brn = properties.boundingBox.brn; - var tfl = properties.boundingBox.tfl; - - for (var i = 1; i < that.selections.length; i++) { - properties = Entities.getEntityProperties(that.selections[i], 'boundingBox'); - var bb = properties.boundingBox; - brn.x = Math.min(bb.brn.x, brn.x); - brn.y = Math.min(bb.brn.y, brn.y); - brn.z = Math.min(bb.brn.z, brn.z); - tfl.x = Math.max(bb.tfl.x, tfl.x); - tfl.y = Math.max(bb.tfl.y, tfl.y); - tfl.z = Math.max(bb.tfl.z, tfl.z); - } - - that.localRotation = null; - that.localDimensions = null; - that.localPosition = null; - that.worldDimensions = { - x: tfl.x - brn.x, - y: tfl.y - brn.y, - z: tfl.z - brn.z - }; - that.worldRotation = Quat.IDENTITY; - that.worldPosition = { - x: brn.x + (that.worldDimensions.x / 2), - y: brn.y + (that.worldDimensions.y / 2), - z: brn.z + (that.worldDimensions.z / 2) - }; - - // For 1+ selections we can only modify selections in world space - SelectionDisplay.setSpaceMode(SPACE_WORLD, false); - } - - for (var j = 0; j < listeners.length; j++) { - try { - listeners[j].callback.call(listeners[j].thisContext, selectionUpdated === true, caller); - } catch (e) { - print("ERROR: entitySelectionTool.update got exception: " + JSON.stringify(e)); - } - } - }; - - return that; -})(); - -// Normalize degrees to be in the range (-180, 180) -function normalizeDegrees(degrees) { - var maxDegrees = 360; - var halfMaxDegrees = maxDegrees / 2; - degrees = ((degrees + halfMaxDegrees) % maxDegrees) - halfMaxDegrees; - if (degrees <= -halfMaxDegrees) { - degrees += maxDegrees; - } - return degrees; -} - -// SELECTION DISPLAY DEFINITION -SelectionDisplay = (function() { - var that = {}; - - const COLOR_GREEN = { red: 31, green: 198, blue: 166 }; - const COLOR_BLUE = { red: 0, green: 147, blue: 197 }; - const COLOR_RED = { red: 226, green: 51, blue: 77 }; - const COLOR_HOVER = { red: 227, green: 227, blue: 227 }; - const COLOR_ROTATE_CURRENT_RING = { red: 255, green: 99, blue: 9 }; - const COLOR_BOUNDING_EDGE = { red: 87, green: 87, blue: 87 }; - const COLOR_SCALE_CUBE = { red: 106, green: 106, blue: 106 }; - const COLOR_SCALE_CUBE_SELECTED = { red: 18, green: 18, blue: 18 }; - const COLOR_DEBUG_PICK_PLANE = { red: 255, green: 255, blue: 255 }; - const COLOR_DEBUG_PICK_PLANE_HIT = { red: 255, green: 165, blue: 0 }; - - const TRANSLATE_ARROW_CYLINDER_OFFSET = 0.1; - const TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE = 0.005; - const TRANSLATE_ARROW_CYLINDER_Y_MULTIPLE = 7.5; - const TRANSLATE_ARROW_CONE_CAMERA_DISTANCE_MULTIPLE = 0.025; - const TRANSLATE_ARROW_CONE_OFFSET_CYLINDER_DIMENSION_MULTIPLE = 0.83; - - const ROTATE_RING_CAMERA_DISTANCE_MULTIPLE = 0.15; - const ROTATE_CTRL_SNAP_ANGLE = 22.5; - const ROTATE_DEFAULT_SNAP_ANGLE = 1; - const ROTATE_DEFAULT_TICK_MARKS_ANGLE = 5; - const ROTATE_RING_IDLE_INNER_RADIUS = 0.92; - const ROTATE_RING_SELECTED_INNER_RADIUS = 0.9; - - // These are multipliers for sizing the rotation degrees display while rotating an entity - const ROTATE_DISPLAY_DISTANCE_MULTIPLIER = 2; - const ROTATE_DISPLAY_SIZE_X_MULTIPLIER = 0.2; - const ROTATE_DISPLAY_SIZE_Y_MULTIPLIER = 0.09; - const ROTATE_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.07; - - const STRETCH_CUBE_OFFSET = 0.06; - const STRETCH_CUBE_CAMERA_DISTANCE_MULTIPLE = 0.02; - const STRETCH_PANEL_WIDTH = 0.01; - - const SCALE_OVERLAY_CAMERA_DISTANCE_MULTIPLE = 0.02; - const SCALE_DIMENSIONS_CAMERA_DISTANCE_MULTIPLE = 0.5; - - const BOUNDING_EDGE_OFFSET = 0.5; - - const DUPLICATOR_OFFSET = { x: 0.9, y: -0.9, z: 0.9 }; - - const CTRL_KEY_CODE = 16777249; - - const RAIL_AXIS_LENGTH = 10000; - - const NEGATE_VECTOR = -1; - const NO_HAND = -1; - - const DEBUG_PICK_PLANE_HIT_LIMIT = 200; - const DEBUG_PICK_PLANE_HIT_CAMERA_DISTANCE_MULTIPLE = 0.01; - - const TRANSLATE_DIRECTION = { - X: 0, - Y: 1, - Z: 2 - }; - - const STRETCH_DIRECTION = { - X: 0, - Y: 1, - Z: 2, - ALL: 3 - }; - - const ROTATE_DIRECTION = { - PITCH: 0, - YAW: 1, - ROLL: 2 - }; - - const INEDIT_STATUS_CHANNEL = "Hifi-InEdit-Status"; - - /** - * The current space mode, this could have been a forced space mode since we do not support multi selection while in - * local space mode. - * @type {string} - should only be set to SPACE_LOCAL or SPACE_WORLD - */ - var spaceMode = SPACE_LOCAL; - - /** - * The desired space mode, this is the user set space mode, which should be respected whenever it is possible. In the case - * of multi entity selection this space mode may differ from the actual spaceMode. - * @type {string} - should only be set to SPACE_LOCAL or SPACE_WORLD - */ - var desiredSpaceMode = SPACE_LOCAL; - - var overlayNames = []; - var lastControllerPoses = [ - getControllerWorldLocation(Controller.Standard.LeftHand, true), - getControllerWorldLocation(Controller.Standard.RightHand, true) - ]; - - var worldRotationX; - var worldRotationY; - var worldRotationZ; - - var activeStretchCubePanelOffset = null; - - var previousHandle = null; - var previousHandleHelper = null; - var previousHandleColor; - - var ctrlPressed = false; - - that.replaceCollisionsAfterStretch = false; - - var handlePropertiesTranslateArrowCones = { - alpha: 1, - shape: "Cone", - solid: true, - visible: false, - ignorePickIntersection: true, - drawInFront: true - }; - var handlePropertiesTranslateArrowCylinders = { - alpha: 1, - shape: "Cylinder", - solid: true, - visible: false, - ignorePickIntersection: true, - drawInFront: true - }; - var handleTranslateXCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones); - var handleTranslateXCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders); - Overlays.editOverlay(handleTranslateXCone, { color: COLOR_RED }); - Overlays.editOverlay(handleTranslateXCylinder, { color: COLOR_RED }); - var handleTranslateYCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones); - var handleTranslateYCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders); - Overlays.editOverlay(handleTranslateYCone, { color: COLOR_GREEN }); - Overlays.editOverlay(handleTranslateYCylinder, { color: COLOR_GREEN }); - var handleTranslateZCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones); - var handleTranslateZCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders); - Overlays.editOverlay(handleTranslateZCone, { color: COLOR_BLUE }); - Overlays.editOverlay(handleTranslateZCylinder, { color: COLOR_BLUE }); - - var handlePropertiesRotateRings = { - alpha: 1, - solid: true, - startAt: 0, - endAt: 360, - innerRadius: ROTATE_RING_IDLE_INNER_RADIUS, - majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE, - majorTickMarksLength: 0.1, - visible: false, - ignorePickIntersection: true, - drawInFront: true - }; - var handleRotatePitchRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings); - Overlays.editOverlay(handleRotatePitchRing, { - color: COLOR_RED, - majorTickMarksColor: COLOR_RED - }); - var handleRotateYawRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings); - Overlays.editOverlay(handleRotateYawRing, { - color: COLOR_GREEN, - majorTickMarksColor: COLOR_GREEN - }); - var handleRotateRollRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings); - Overlays.editOverlay(handleRotateRollRing, { - color: COLOR_BLUE, - majorTickMarksColor: COLOR_BLUE - }); - - var handleRotateCurrentRing = Overlays.addOverlay("circle3d", { - alpha: 1, - color: COLOR_ROTATE_CURRENT_RING, - solid: true, - innerRadius: 0.9, - visible: false, - ignorePickIntersection: true, - drawInFront: true - }); - - var rotationDegreesDisplay = Overlays.addOverlay("text3d", { - text: "", - color: { red: 0, green: 0, blue: 0 }, - backgroundColor: { red: 255, green: 255, blue: 255 }, - alpha: 0.7, - backgroundAlpha: 0.7, - visible: false, - isFacingAvatar: true, - drawInFront: true, - ignorePickIntersection: true, - dimensions: { x: 0, y: 0 }, - lineHeight: 0.0, - topMargin: 0, - rightMargin: 0, - bottomMargin: 0, - leftMargin: 0 - }); - - var handlePropertiesStretchCubes = { - solid: true, - visible: false, - ignorePickIntersection: true, - drawInFront: true - }; - var handleStretchXCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes); - Overlays.editOverlay(handleStretchXCube, { color: COLOR_RED }); - var handleStretchYCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes); - Overlays.editOverlay(handleStretchYCube, { color: COLOR_GREEN }); - var handleStretchZCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes); - Overlays.editOverlay(handleStretchZCube, { color: COLOR_BLUE }); - - var handlePropertiesStretchPanel = { - alpha: 0.5, - solid: true, - visible: false, - ignorePickIntersection: true, - drawInFront: true - }; - var handleStretchXPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel); - Overlays.editOverlay(handleStretchXPanel, { color: COLOR_RED }); - var handleStretchYPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel); - Overlays.editOverlay(handleStretchYPanel, { color: COLOR_GREEN }); - var handleStretchZPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel); - Overlays.editOverlay(handleStretchZPanel, { color: COLOR_BLUE }); - - var handleScaleCube = Overlays.addOverlay("cube", { - size: 0.025, - color: COLOR_SCALE_CUBE, - solid: true, - visible: false, - ignorePickIntersection: true, - drawInFront: true, - borderSize: 1.4 - }); - - var handleBoundingBox = Overlays.addOverlay("cube", { - alpha: 1, - color: COLOR_BOUNDING_EDGE, - visible: false, - ignorePickIntersection: true, - drawInFront: true, - isSolid: false - }); - - var handleDuplicator = Overlays.addOverlay("cube", { - alpha: 1, - size: 0.05, - color: COLOR_GREEN, - solid: true, - visible: false, - ignorePickIntersection: true, - drawInFront: true, - borderSize: 1.4 - }); - - // setting to 0 alpha for now to keep this hidden vs using visible false - // because its used as the translate xz tool handle overlay - var selectionBox = Overlays.addOverlay("cube", { - size: 1, - color: COLOR_RED, - alpha: 0, - solid: false, - visible: false, - ignorePickIntersection: true, - dashed: false - }); - - // Handle for x-z translation of particle effect and light entities while inside the bounding box. - // Limitation: If multiple entities are selected, only the first entity's icon translates the selection. - var iconSelectionBox = Overlays.addOverlay("cube", { - size: 0.3, // Match entity icon size. - color: COLOR_RED, - alpha: 0, - solid: false, - visible: false, - ignorePickIntersection: true, - dashed: false - }); - - var xRailOverlay = Overlays.addOverlay("line3d", { - visible: false, - start: Vec3.ZERO, - end: Vec3.ZERO, - color: { - red: 255, - green: 0, - blue: 0 - }, - ignorePickIntersection: true // always ignore this - }); - var yRailOverlay = Overlays.addOverlay("line3d", { - visible: false, - start: Vec3.ZERO, - end: Vec3.ZERO, - color: { - red: 0, - green: 255, - blue: 0 - }, - ignorePickIntersection: true // always ignore this - }); - var zRailOverlay = Overlays.addOverlay("line3d", { - visible: false, - start: Vec3.ZERO, - end: Vec3.ZERO, - color: { - red: 0, - green: 0, - blue: 255 - }, - ignorePickIntersection: true // always ignore this - }); - - var allOverlays = [ - handleTranslateXCone, - handleTranslateXCylinder, - handleTranslateYCone, - handleTranslateYCylinder, - handleTranslateZCone, - handleTranslateZCylinder, - handleRotatePitchRing, - handleRotateYawRing, - handleRotateRollRing, - handleRotateCurrentRing, - rotationDegreesDisplay, - handleStretchXCube, - handleStretchYCube, - handleStretchZCube, - handleStretchXPanel, - handleStretchYPanel, - handleStretchZPanel, - handleScaleCube, - handleBoundingBox, - handleDuplicator, - selectionBox, - iconSelectionBox, - xRailOverlay, - yRailOverlay, - zRailOverlay - ]; - - const nonLayeredOverlays = [selectionBox, iconSelectionBox]; - - var maximumHandleInAllOverlays = handleDuplicator; - - overlayNames[handleTranslateXCone] = "handleTranslateXCone"; - overlayNames[handleTranslateXCylinder] = "handleTranslateXCylinder"; - overlayNames[handleTranslateYCone] = "handleTranslateYCone"; - overlayNames[handleTranslateYCylinder] = "handleTranslateYCylinder"; - overlayNames[handleTranslateZCone] = "handleTranslateZCone"; - overlayNames[handleTranslateZCylinder] = "handleTranslateZCylinder"; - - overlayNames[handleRotatePitchRing] = "handleRotatePitchRing"; - overlayNames[handleRotateYawRing] = "handleRotateYawRing"; - overlayNames[handleRotateRollRing] = "handleRotateRollRing"; - overlayNames[handleRotateCurrentRing] = "handleRotateCurrentRing"; - overlayNames[rotationDegreesDisplay] = "rotationDegreesDisplay"; - - overlayNames[handleStretchXCube] = "handleStretchXCube"; - overlayNames[handleStretchYCube] = "handleStretchYCube"; - overlayNames[handleStretchZCube] = "handleStretchZCube"; - overlayNames[handleStretchXPanel] = "handleStretchXPanel"; - overlayNames[handleStretchYPanel] = "handleStretchYPanel"; - overlayNames[handleStretchZPanel] = "handleStretchZPanel"; - - overlayNames[handleScaleCube] = "handleScaleCube"; - - overlayNames[handleBoundingBox] = "handleBoundingBox"; - - overlayNames[handleDuplicator] = "handleDuplicator"; - overlayNames[selectionBox] = "selectionBox"; - overlayNames[iconSelectionBox] = "iconSelectionBox"; - - var activeTool = null; - var handleTools = {}; - - var debugPickPlaneEnabled = false; - var debugPickPlane = Overlays.addOverlay("shape", { - shape: "Quad", - alpha: 0.25, - color: COLOR_DEBUG_PICK_PLANE, - solid: true, - visible: false, - ignorePickIntersection: true, - drawInFront: false - }); - var debugPickPlaneHits = []; - - // We get mouseMoveEvents from the handControllers, via handControllerPointer. - // But we dont' get mousePressEvents. - that.triggerClickMapping = Controller.newMapping(Script.resolvePath('') + '-click'); - that.triggerPressMapping = Controller.newMapping(Script.resolvePath('') + '-press'); - that.triggeredHand = NO_HAND; - that.pressedHand = NO_HAND; - that.editingHand = NO_HAND; - that.triggered = function() { - return that.triggeredHand !== NO_HAND; - }; - function pointingAtDesktopWindowOrTablet(hand) { - var pointingAtDesktopWindow = (hand === Controller.Standard.RightHand && - SelectionManager.pointingAtDesktopWindowRight) || - (hand === Controller.Standard.LeftHand && - SelectionManager.pointingAtDesktopWindowLeft); - var pointingAtTablet = (hand === Controller.Standard.RightHand && SelectionManager.pointingAtTabletRight) || - (hand === Controller.Standard.LeftHand && SelectionManager.pointingAtTabletLeft); - return pointingAtDesktopWindow || pointingAtTablet; - } - function makeClickHandler(hand) { - return function (clicked) { - // Don't allow both hands to trigger at the same time - if (that.triggered() && hand !== that.triggeredHand) { - return; - } - if (!that.triggered() && clicked && !pointingAtDesktopWindowOrTablet(hand)) { - that.triggeredHand = hand; - that.mousePressEvent({}); - } else if (that.triggered() && !clicked) { - that.triggeredHand = NO_HAND; - that.mouseReleaseEvent({}); - } - }; - } - function makePressHandler(hand) { - return function (value) { - if (value >= TRIGGER_ON_VALUE && !that.triggered() && !pointingAtDesktopWindowOrTablet(hand)) { - that.pressedHand = hand; - that.updateHighlight({}); - } else { - that.pressedHand = NO_HAND; - that.resetPreviousHandleColor(); - } - } - } - that.triggerClickMapping.from(Controller.Standard.RTClick).peek().to(makeClickHandler(Controller.Standard.RightHand)); - that.triggerClickMapping.from(Controller.Standard.LTClick).peek().to(makeClickHandler(Controller.Standard.LeftHand)); - that.triggerPressMapping.from(Controller.Standard.RT).peek().to(makePressHandler(Controller.Standard.RightHand)); - that.triggerPressMapping.from(Controller.Standard.LT).peek().to(makePressHandler(Controller.Standard.LeftHand)); - that.enableTriggerMapping = function() { - that.triggerClickMapping.enable(); - that.triggerPressMapping.enable(); - }; - that.disableTriggerMapping = function() { - that.triggerClickMapping.disable(); - that.triggerPressMapping.disable(); - }; - Script.scriptEnding.connect(that.disableTriggerMapping); - - // FUNCTION DEF(s): Intersection Check Helpers - function testRayIntersect(queryRay, overlayIncludes, overlayExcludes) { - var wantDebug = false; - if ((queryRay === undefined) || (queryRay === null)) { - if (wantDebug) { - print("testRayIntersect - EARLY EXIT -> queryRay is undefined OR null!"); - } - return null; - } - - // We want to first check the drawInFront overlays (i.e. the handles, but really everything except the selectionBoxes) - // so that you can click on them even when they're behind things - var overlayIncludesLayered = []; - var overlayIncludesNonLayered = []; - for (var i = 0; i < overlayIncludes.length; i++) { - var value = overlayIncludes[i]; - var contains = false; - for (var j = 0; j < nonLayeredOverlays.length; j++) { - if (nonLayeredOverlays[j] === value) { - contains = true; - break; - } - } - if (contains) { - overlayIncludesNonLayered.push(value); - } else { - overlayIncludesLayered.push(value); - } - } - - var intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludesLayered, overlayExcludes); - - if (!intersectObj.intersects && overlayIncludesNonLayered.length > 0) { - intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludesNonLayered, overlayExcludes); - } - - if (wantDebug) { - if (!overlayIncludes) { - print("testRayIntersect - no overlayIncludes provided."); - } - if (!overlayExcludes) { - print("testRayIntersect - no overlayExcludes provided."); - } - print("testRayIntersect - Hit: " + intersectObj.intersects); - print(" intersectObj.overlayID:" + intersectObj.overlayID + "[" + overlayNames[intersectObj.overlayID] + "]"); - print(" OverlayName: " + overlayNames[intersectObj.overlayID]); - print(" intersectObj.distance:" + intersectObj.distance); - print(" intersectObj.face:" + intersectObj.face); - Vec3.print(" intersectObj.intersection:", intersectObj.intersection); - } - - return intersectObj; - } - - function isPointInsideBox(point, box) { - var position = Vec3.subtract(point, box.position); - position = Vec3.multiplyQbyV(Quat.inverse(box.rotation), position); - return Math.abs(position.x) <= box.dimensions.x / 2 && Math.abs(position.y) <= box.dimensions.y / 2 - && Math.abs(position.z) <= box.dimensions.z / 2; - } - - that.isEditHandle = function(overlayID) { - var overlayIndex = allOverlays.indexOf(overlayID); - var maxHandleIndex = allOverlays.indexOf(maximumHandleInAllOverlays); - return overlayIndex >= 0 && overlayIndex <= maxHandleIndex; - }; - - // FUNCTION: MOUSE PRESS EVENT - that.mousePressEvent = function (event) { - var wantDebug = false; - if (wantDebug) { - print("=============== eST::MousePressEvent BEG ======================="); - } - if (!event.isLeftButton && !that.triggered()) { - // EARLY EXIT-(if another mouse button than left is pressed ignore it) - return false; - } - - var pickRay = generalComputePickRay(event.x, event.y); - // TODO_Case6491: Move this out to setup just to make it once - var interactiveOverlays = getMainTabletIDs(); - for (var key in handleTools) { - if (handleTools.hasOwnProperty(key)) { - interactiveOverlays.push(key); - } - } - - // Start with unknown mode, in case no tool can handle this. - activeTool = null; - - var results = testRayIntersect(pickRay, interactiveOverlays); - if (results.intersects) { - var hitOverlayID = results.overlayID; - if ((HMD.tabletID && hitOverlayID === HMD.tabletID) || (HMD.tabletScreenID && hitOverlayID === HMD.tabletScreenID) - || (HMD.homeButtonID && hitOverlayID === HMD.homeButtonID)) { - // EARLY EXIT-(mouse clicks on the tablet should override the edit affordances) - return false; - } - - var hitTool = handleTools[ hitOverlayID ]; - if (hitTool) { - activeTool = hitTool; - that.clearDebugPickPlane(); - if (activeTool.onBegin) { - that.editingHand = that.triggeredHand; - Messages.sendLocalMessage(INEDIT_STATUS_CHANNEL, JSON.stringify({ - method: "editing", - hand: that.editingHand === Controller.Standard.LeftHand ? LEFT_HAND : RIGHT_HAND, - editing: true - })); - activeTool.onBegin(event, pickRay, results); - } else { - print("ERROR: entitySelectionTool.mousePressEvent - ActiveTool(" + activeTool.mode + ") missing onBegin"); - } - } else { - print("ERROR: entitySelectionTool.mousePressEvent - Hit unexpected object, check interactiveOverlays"); - }// End_if (hitTool) - }// End_If(results.intersects) - - if (wantDebug) { - print(" DisplayMode: " + getMode()); - print("=============== eST::MousePressEvent END ======================="); - } - - // If mode is known then we successfully handled this; - // otherwise, we're missing a tool. - return activeTool; - }; - - that.resetPreviousHandleColor = function() { - if (previousHandle !== null) { - Overlays.editOverlay(previousHandle, { color: previousHandleColor }); - previousHandle = null; - } - if (previousHandleHelper !== null) { - Overlays.editOverlay(previousHandleHelper, { color: previousHandleColor }); - previousHandleHelper = null; - } - }; - - that.getHandleHelper = function(overlay) { - if (overlay === handleTranslateXCone) { - return handleTranslateXCylinder; - } else if (overlay === handleTranslateXCylinder) { - return handleTranslateXCone; - } else if (overlay === handleTranslateYCone) { - return handleTranslateYCylinder; - } else if (overlay === handleTranslateYCylinder) { - return handleTranslateYCone; - } else if (overlay === handleTranslateZCone) { - return handleTranslateZCylinder; - } else if (overlay === handleTranslateZCylinder) { - return handleTranslateZCone; - } - return Uuid.NULL; - }; - - that.updateHighlight = function(event) { - // if no tool is active, then just look for handles to highlight... - var pickRay = generalComputePickRay(event.x, event.y); - var result = testRayIntersect(pickRay, allOverlays); - var pickedColor; - var highlightNeeded = false; - - if (result.intersects) { - switch (result.overlayID) { - case handleTranslateXCone: - case handleTranslateXCylinder: - case handleRotatePitchRing: - case handleStretchXCube: - pickedColor = COLOR_RED; - highlightNeeded = true; - break; - case handleTranslateYCone: - case handleTranslateYCylinder: - case handleRotateYawRing: - case handleStretchYCube: - pickedColor = COLOR_GREEN; - highlightNeeded = true; - break; - case handleTranslateZCone: - case handleTranslateZCylinder: - case handleRotateRollRing: - case handleStretchZCube: - pickedColor = COLOR_BLUE; - highlightNeeded = true; - break; - case handleScaleCube: - pickedColor = COLOR_SCALE_CUBE; - highlightNeeded = true; - break; - default: - that.resetPreviousHandleColor(); - break; - } - - if (highlightNeeded) { - that.resetPreviousHandleColor(); - Overlays.editOverlay(result.overlayID, { color: COLOR_HOVER }); - previousHandle = result.overlayID; - previousHandleHelper = that.getHandleHelper(result.overlayID); - if (previousHandleHelper !== null) { - Overlays.editOverlay(previousHandleHelper, { color: COLOR_HOVER }); - } - previousHandleColor = pickedColor; - } - - } else { - that.resetPreviousHandleColor(); - } - }; - - // FUNCTION: MOUSE MOVE EVENT - var lastMouseEvent = null; - that.mouseMoveEvent = function(event) { - var wantDebug = false; - if (wantDebug) { - print("=============== eST::MouseMoveEvent BEG ======================="); - } - lastMouseEvent = event; - if (activeTool) { - if (wantDebug) { - print(" Trigger ActiveTool(" + activeTool.mode + ")'s onMove"); - } - activeTool.onMove(event); - - if (wantDebug) { - print(" Trigger SelectionManager::update"); - } - SelectionManager._update(false, that); - - if (wantDebug) { - print("=============== eST::MouseMoveEvent END ======================="); - } - // EARLY EXIT--(Move handled via active tool) - return true; - } - - that.updateHighlight(event); - - if (wantDebug) { - print("=============== eST::MouseMoveEvent END ======================="); - } - return false; - }; - - // FUNCTION: MOUSE RELEASE EVENT - that.mouseReleaseEvent = function(event) { - var wantDebug = false; - if (wantDebug) { - print("=============== eST::MouseReleaseEvent BEG ======================="); - } - var showHandles = false; - if (activeTool) { - if (activeTool.onEnd) { - if (wantDebug) { - print(" Triggering ActiveTool(" + activeTool.mode + ")'s onEnd"); - } - Messages.sendLocalMessage(INEDIT_STATUS_CHANNEL, JSON.stringify({ - method: "editing", - hand: that.editingHand === Controller.Standard.LeftHand ? LEFT_HAND : RIGHT_HAND, - editing: false - })); - that.editingHand = NO_HAND; - activeTool.onEnd(event); - } else if (wantDebug) { - print(" ActiveTool(" + activeTool.mode + ")'s missing onEnd"); - } - } - - showHandles = activeTool; // base on prior tool value - activeTool = null; - - // if something is selected, then reset the "original" properties for any potential next click+move operation - if (SelectionManager.hasSelection()) { - if (showHandles) { - if (wantDebug) { - print(" Triggering that.select"); - } - that.select(SelectionManager.selections[0], event); - } - } - - if (wantDebug) { - print("=============== eST::MouseReleaseEvent END ======================="); - } - }; - - // Control key remains active only while key is held down - that.keyReleaseEvent = function(event) { - if (event.key === CTRL_KEY_CODE) { - ctrlPressed = false; - that.updateActiveRotateRing(); - } - that.updateLastMouseEvent(event); - }; - - // Triggers notification on specific key driven events - that.keyPressEvent = function(event) { - if (event.key === CTRL_KEY_CODE) { - ctrlPressed = true; - that.updateActiveRotateRing(); - } - that.updateLastMouseEvent(event); - }; - - that.updateLastMouseEvent = function(event) { - if (activeTool && lastMouseEvent !== null) { - var change = lastMouseEvent.isShifted !== event.isShifted || lastMouseEvent.isMeta !== event.isMeta || - lastMouseEvent.isControl !== event.isControl || lastMouseEvent.isAlt !== event.isAlt; - lastMouseEvent.isShifted = event.isShifted; - lastMouseEvent.isMeta = event.isMeta; - lastMouseEvent.isControl = event.isControl; - lastMouseEvent.isAlt = event.isAlt; - if (change) { - activeTool.onMove(lastMouseEvent); - } - } - }; - - // NOTE: mousePressEvent and mouseMoveEvent from the main script should call us., so we don't hook these: - // Controller.mousePressEvent.connect(that.mousePressEvent); - // Controller.mouseMoveEvent.connect(that.mouseMoveEvent); - Controller.mouseReleaseEvent.connect(that.mouseReleaseEvent); - Controller.keyPressEvent.connect(that.keyPressEvent); - Controller.keyReleaseEvent.connect(that.keyReleaseEvent); - - that.checkControllerMove = function() { - if (SelectionManager.hasSelection()) { - var controllerPose = getControllerWorldLocation(that.triggeredHand, true); - var hand = (that.triggeredHand === Controller.Standard.LeftHand) ? 0 : 1; - if (controllerPose.valid && lastControllerPoses[hand].valid && that.triggered()) { - if (!Vec3.equal(controllerPose.position, lastControllerPoses[hand].position) || - !Vec3.equal(controllerPose.rotation, lastControllerPoses[hand].rotation)) { - that.mouseMoveEvent({}); - } - } - lastControllerPoses[hand] = controllerPose; - } - }; - - function controllerComputePickRay() { - var hand = that.triggered() ? that.triggeredHand : that.pressedHand; - var controllerPose = getControllerWorldLocation(hand, true); - if (controllerPose.valid) { - var controllerPosition = controllerPose.translation; - // This gets point direction right, but if you want general quaternion it would be more complicated: - var controllerDirection = Quat.getUp(controllerPose.rotation); - return {origin: controllerPosition, direction: controllerDirection}; - } - } - - function generalComputePickRay(x, y) { - return controllerComputePickRay() || Camera.computePickRay(x, y); - } - - function getControllerAvatarFramePositionFromPickRay(pickRay) { - var controllerPosition = Vec3.subtract(pickRay.origin, MyAvatar.position); - controllerPosition = Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), controllerPosition); - return controllerPosition; - } - - function getDistanceToCamera(position) { - var cameraPosition = Camera.getPosition(); - var toCameraDistance = Vec3.length(Vec3.subtract(cameraPosition, position)); - return toCameraDistance; - } - - function usePreviousPickRay(pickRayDirection, previousPickRayDirection, normal) { - return (Vec3.dot(pickRayDirection, normal) > 0 && Vec3.dot(previousPickRayDirection, normal) < 0) || - (Vec3.dot(pickRayDirection, normal) < 0 && Vec3.dot(previousPickRayDirection, normal) > 0); - } - - // @return string - The mode of the currently active tool; - // otherwise, "UNKNOWN" if there's no active tool. - function getMode() { - return (activeTool ? activeTool.mode : "UNKNOWN"); - } - - that.cleanup = function() { - for (var i = 0; i < allOverlays.length; i++) { - Overlays.deleteOverlay(allOverlays[i]); - } - that.clearDebugPickPlane(); - }; - - that.select = function(entityID, event) { - var properties = Entities.getEntityProperties(SelectionManager.selections[0]); - - if (event !== false) { - var wantDebug = false; - if (wantDebug) { - print("select() with EVENT...... "); - print(" event.y:" + event.y); - Vec3.print(" current position:", properties.position); - } - } - - that.updateHandles(); - }; - - - /** - * This callback is used for spaceMode changes. - * @callback spaceModeChangedCallback - * @param {string} spaceMode - */ - - /** - * set this property with a callback to keep track of spaceMode changes. - * @type {spaceModeChangedCallback} - */ - that.onSpaceModeChange = null; - - // FUNCTION: SET SPACE MODE - that.setSpaceMode = function(newSpaceMode, isDesiredChange) { - var wantDebug = false; - if (wantDebug) { - print("======> SetSpaceMode called. ========"); - } - - if (spaceMode !== newSpaceMode) { - if (wantDebug) { - print(" Updating SpaceMode From: " + spaceMode + " To: " + newSpaceMode); - } - if (isDesiredChange) { - desiredSpaceMode = newSpaceMode; - } - spaceMode = newSpaceMode; - - if (that.onSpaceModeChange !== null) { - that.onSpaceModeChange(newSpaceMode); - } - - that.updateHandles(); - } else if (wantDebug) { - print("WARNING: entitySelectionTool.setSpaceMode - Can't update SpaceMode. CurrentMode: " + - spaceMode + " DesiredMode: " + newSpaceMode); - } - if (wantDebug) { - print("====== SetSpaceMode called. <========"); - } - }; - - // FUNCTION: TOGGLE SPACE MODE - that.toggleSpaceMode = function() { - var wantDebug = false; - if (wantDebug) { - print("========> ToggleSpaceMode called. ========="); - } - if ((spaceMode === SPACE_WORLD) && (SelectionManager.selections.length > 1)) { - if (wantDebug) { - print("Local space editing is not available with multiple selections"); - } - return; - } - if (wantDebug) { - print("PreToggle: " + spaceMode); - } - that.setSpaceMode((spaceMode === SPACE_LOCAL) ? SPACE_WORLD : SPACE_LOCAL, true); - if (wantDebug) { - print("PostToggle: " + spaceMode); - print("======== ToggleSpaceMode called. <========="); - } - }; - - /** - * Switches the display mode back to the set desired display mode - */ - that.useDesiredSpaceMode = function() { - var wantDebug = false; - if (wantDebug) { - print("========> UseDesiredSpaceMode called. ========="); - } - that.setSpaceMode(desiredSpaceMode, false); - if (wantDebug) { - print("PostToggle: " + spaceMode); - print("======== UseDesiredSpaceMode called. <========="); - } - }; - - /** - * Get the currently set SpaceMode - * @returns {string} spaceMode - */ - that.getSpaceMode = function() { - return spaceMode; - }; - - function addHandleTool(overlay, tool) { - handleTools[overlay] = tool; - return tool; - } - - // @param: toolHandle: The overlayID associated with the tool - // that correlates to the tool you wish to query. - // @note: If toolHandle is null or undefined then activeTool - // will be checked against those values as opposed to - // the tool registered under toolHandle. Null & Undefined - // are treated as separate values. - // @return: bool - Indicates if the activeTool is that queried. - function isActiveTool(toolHandle) { - if (!toolHandle) { - // Allow isActiveTool(null) and similar to return true if there's - // no active tool - return (activeTool === toolHandle); - } - - if (!handleTools.hasOwnProperty(toolHandle)) { - print("WARNING: entitySelectionTool.isActiveTool - Encountered unknown grabberToolHandle: " + - toolHandle + ". Tools should be registered via addHandleTool."); - // EARLY EXIT - return false; - } - - return (activeTool === handleTools[ toolHandle ]); - } - - // FUNCTION: UPDATE HANDLES - that.updateHandles = function() { - var wantDebug = false; - if (wantDebug) { - print("======> Update Handles ======="); - print(" Selections Count: " + SelectionManager.selections.length); - print(" SpaceMode: " + spaceMode); - print(" DisplayMode: " + getMode()); - } - - if (SelectionManager.selections.length === 0) { - that.setOverlaysVisible(false); - that.clearDebugPickPlane(); - return; - } - - if (SelectionManager.hasSelection()) { - var position = SelectionManager.worldPosition; - var rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation; - var dimensions = spaceMode === SPACE_LOCAL ? SelectionManager.localDimensions : SelectionManager.worldDimensions; - var rotationInverse = Quat.inverse(rotation); - var toCameraDistance = getDistanceToCamera(position); - - var rotationDegrees = 90; - var localRotationX = Quat.fromPitchYawRollDegrees(0, 0, -rotationDegrees); - var rotationX = Quat.multiply(rotation, localRotationX); - worldRotationX = rotationX; - var localRotationY = Quat.fromPitchYawRollDegrees(0, rotationDegrees, 0); - var rotationY = Quat.multiply(rotation, localRotationY); - worldRotationY = rotationY; - var localRotationZ = Quat.fromPitchYawRollDegrees(rotationDegrees, 0, 0); - var rotationZ = Quat.multiply(rotation, localRotationZ); - worldRotationZ = rotationZ; - - var selectionBoxGeometry = { - position: position, - rotation: rotation, - dimensions: dimensions - }; - var isCameraInsideBox = isPointInsideBox(Camera.position, selectionBoxGeometry); - - // in HMD if outside the bounding box clamp the overlays to the bounding box for now so lasers can hit them - var maxHandleDimension = 0; - if (HMD.active && !isCameraInsideBox) { - maxHandleDimension = Math.max(dimensions.x, dimensions.y, dimensions.z); - } - - // UPDATE ROTATION RINGS - // rotateDimension is used as the base dimension for all overlays - var rotateDimension = Math.max(maxHandleDimension, toCameraDistance * ROTATE_RING_CAMERA_DISTANCE_MULTIPLE); - var rotateDimensions = { x: rotateDimension, y: rotateDimension, z: rotateDimension }; - if (!isActiveTool(handleRotatePitchRing)) { - Overlays.editOverlay(handleRotatePitchRing, { - position: position, - rotation: rotationY, - dimensions: rotateDimensions, - majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE - }); - } - if (!isActiveTool(handleRotateYawRing)) { - Overlays.editOverlay(handleRotateYawRing, { - position: position, - rotation: rotationZ, - dimensions: rotateDimensions, - majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE - }); - } - if (!isActiveTool(handleRotateRollRing)) { - Overlays.editOverlay(handleRotateRollRing, { - position: position, - rotation: rotationX, - dimensions: rotateDimensions, - majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE - }); - } - Overlays.editOverlay(handleRotateCurrentRing, { dimensions: rotateDimensions }); - that.updateActiveRotateRing(); - - // UPDATE TRANSLATION ARROWS - var arrowCylinderDimension = rotateDimension * TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE / - ROTATE_RING_CAMERA_DISTANCE_MULTIPLE; - var arrowCylinderDimensions = { - x: arrowCylinderDimension, - y: arrowCylinderDimension * TRANSLATE_ARROW_CYLINDER_Y_MULTIPLE, - z: arrowCylinderDimension - }; - var arrowConeDimension = rotateDimension * TRANSLATE_ARROW_CONE_CAMERA_DISTANCE_MULTIPLE / - ROTATE_RING_CAMERA_DISTANCE_MULTIPLE; - var arrowConeDimensions = { x: arrowConeDimension, y: arrowConeDimension, z: arrowConeDimension }; - var arrowCylinderOffset = rotateDimension * TRANSLATE_ARROW_CYLINDER_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE; - var arrowConeOffset = arrowCylinderDimensions.y * TRANSLATE_ARROW_CONE_OFFSET_CYLINDER_DIMENSION_MULTIPLE; - var cylinderXPosition = { x: arrowCylinderOffset, y: 0, z: 0 }; - cylinderXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderXPosition)); - Overlays.editOverlay(handleTranslateXCylinder, { - position: cylinderXPosition, - rotation: rotationX, - dimensions: arrowCylinderDimensions - }); - var cylinderXOffset = Vec3.subtract(cylinderXPosition, position); - var coneXPosition = Vec3.sum(cylinderXPosition, Vec3.multiply(Vec3.normalize(cylinderXOffset), arrowConeOffset)); - Overlays.editOverlay(handleTranslateXCone, { - position: coneXPosition, - rotation: rotationX, - dimensions: arrowConeDimensions - }); - var cylinderYPosition = { x: 0, y: arrowCylinderOffset, z: 0 }; - cylinderYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderYPosition)); - Overlays.editOverlay(handleTranslateYCylinder, { - position: cylinderYPosition, - rotation: rotationY, - dimensions: arrowCylinderDimensions - }); - var cylinderYOffset = Vec3.subtract(cylinderYPosition, position); - var coneYPosition = Vec3.sum(cylinderYPosition, Vec3.multiply(Vec3.normalize(cylinderYOffset), arrowConeOffset)); - Overlays.editOverlay(handleTranslateYCone, { - position: coneYPosition, - rotation: rotationY, - dimensions: arrowConeDimensions - }); - var cylinderZPosition = { x: 0, y: 0, z: arrowCylinderOffset }; - cylinderZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderZPosition)); - Overlays.editOverlay(handleTranslateZCylinder, { - position: cylinderZPosition, - rotation: rotationZ, - dimensions: arrowCylinderDimensions - }); - var cylinderZOffset = Vec3.subtract(cylinderZPosition, position); - var coneZPosition = Vec3.sum(cylinderZPosition, Vec3.multiply(Vec3.normalize(cylinderZOffset), arrowConeOffset)); - Overlays.editOverlay(handleTranslateZCone, { - position: coneZPosition, - rotation: rotationZ, - dimensions: arrowConeDimensions - }); - - // UPDATE SCALE CUBE - var scaleCubeRotation = spaceMode === SPACE_LOCAL ? rotation : Quat.IDENTITY; - var scaleCubeDimension = rotateDimension * SCALE_OVERLAY_CAMERA_DISTANCE_MULTIPLE / - ROTATE_RING_CAMERA_DISTANCE_MULTIPLE; - var scaleCubeDimensions = { x: scaleCubeDimension, y: scaleCubeDimension, z: scaleCubeDimension }; - Overlays.editOverlay(handleScaleCube, { - position: position, - rotation: scaleCubeRotation, - dimensions: scaleCubeDimensions - }); - - // UPDATE BOUNDING BOX - Overlays.editOverlay(handleBoundingBox, { - position: position, - rotation: rotation, - dimensions: dimensions - }); - - // UPDATE STRETCH HIGHLIGHT PANELS - var edgeOffsetX = BOUNDING_EDGE_OFFSET * dimensions.x; - var edgeOffsetY = BOUNDING_EDGE_OFFSET * dimensions.y; - var edgeOffsetZ = BOUNDING_EDGE_OFFSET * dimensions.z; - var RBFPosition = { x: edgeOffsetX, y: -edgeOffsetY, z: edgeOffsetZ }; - RBFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RBFPosition)); - var RTFPosition = { x: edgeOffsetX, y: edgeOffsetY, z: edgeOffsetZ }; - RTFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RTFPosition)); - var LTNPosition = { x: -edgeOffsetX, y: edgeOffsetY, z: -edgeOffsetZ }; - LTNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LTNPosition)); - var RTNPosition = { x: edgeOffsetX, y: edgeOffsetY, z: -edgeOffsetZ }; - RTNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RTNPosition)); - - var RBFPositionRotated = Vec3.multiplyQbyV(rotationInverse, RBFPosition); - var RTFPositionRotated = Vec3.multiplyQbyV(rotationInverse, RTFPosition); - var LTNPositionRotated = Vec3.multiplyQbyV(rotationInverse, LTNPosition); - var RTNPositionRotated = Vec3.multiplyQbyV(rotationInverse, RTNPosition); - var stretchPanelXDimensions = Vec3.subtract(RTNPositionRotated, RBFPositionRotated); - var tempY = Math.abs(stretchPanelXDimensions.y); - stretchPanelXDimensions.x = STRETCH_PANEL_WIDTH; - stretchPanelXDimensions.y = Math.abs(stretchPanelXDimensions.z); - stretchPanelXDimensions.z = tempY; - var stretchPanelXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: dimensions.x / 2, y: 0, z: 0 })); - Overlays.editOverlay(handleStretchXPanel, { - position: stretchPanelXPosition, - rotation: rotationZ, - dimensions: stretchPanelXDimensions - }); - var stretchPanelYDimensions = Vec3.subtract(LTNPositionRotated, RTFPositionRotated); - var tempX = Math.abs(stretchPanelYDimensions.x); - stretchPanelYDimensions.x = Math.abs(stretchPanelYDimensions.z); - stretchPanelYDimensions.y = STRETCH_PANEL_WIDTH; - stretchPanelYDimensions.z = tempX; - var stretchPanelYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: 0, y: dimensions.y / 2, z: 0 })); - Overlays.editOverlay(handleStretchYPanel, { - position: stretchPanelYPosition, - rotation: rotationY, - dimensions: stretchPanelYDimensions - }); - var stretchPanelZDimensions = Vec3.subtract(LTNPositionRotated, RBFPositionRotated); - tempX = Math.abs(stretchPanelZDimensions.x); - stretchPanelZDimensions.x = Math.abs(stretchPanelZDimensions.y); - stretchPanelZDimensions.y = tempX; - stretchPanelZDimensions.z = STRETCH_PANEL_WIDTH; - var stretchPanelZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: 0, y: 0, z: dimensions.z / 2 })); - Overlays.editOverlay(handleStretchZPanel, { - position: stretchPanelZPosition, - rotation: rotationX, - dimensions: stretchPanelZDimensions - }); - - // UPDATE STRETCH CUBES - var stretchCubeDimension = rotateDimension * STRETCH_CUBE_CAMERA_DISTANCE_MULTIPLE / - ROTATE_RING_CAMERA_DISTANCE_MULTIPLE; - var stretchCubeDimensions = { x: stretchCubeDimension, y: stretchCubeDimension, z: stretchCubeDimension }; - var stretchCubeOffset = rotateDimension * STRETCH_CUBE_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE; - var stretchXPosition, stretchYPosition, stretchZPosition; - if (isActiveTool(handleStretchXCube)) { - stretchXPosition = Vec3.subtract(stretchPanelXPosition, activeStretchCubePanelOffset); - } else { - stretchXPosition = { x: stretchCubeOffset, y: 0, z: 0 }; - stretchXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchXPosition)); - } - if (isActiveTool(handleStretchYCube)) { - stretchYPosition = Vec3.subtract(stretchPanelYPosition, activeStretchCubePanelOffset); - } else { - stretchYPosition = { x: 0, y: stretchCubeOffset, z: 0 }; - stretchYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchYPosition)); - } - if (isActiveTool(handleStretchZCube)) { - stretchZPosition = Vec3.subtract(stretchPanelZPosition, activeStretchCubePanelOffset); - } else { - stretchZPosition = { x: 0, y: 0, z: stretchCubeOffset }; - stretchZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchZPosition)); - } - Overlays.editOverlay(handleStretchXCube, { - position: stretchXPosition, - rotation: rotationX, - dimensions: stretchCubeDimensions - }); - Overlays.editOverlay(handleStretchYCube, { - position: stretchYPosition, - rotation: rotationY, - dimensions: stretchCubeDimensions - }); - Overlays.editOverlay(handleStretchZCube, { - position: stretchZPosition, - rotation: rotationZ, - dimensions: stretchCubeDimensions - }); - - // UPDATE SELECTION BOX (CURRENTLY INVISIBLE WITH 0 ALPHA FOR TRANSLATE XZ TOOL) - var inModeRotate = isActiveTool(handleRotatePitchRing) || - isActiveTool(handleRotateYawRing) || - isActiveTool(handleRotateRollRing); - selectionBoxGeometry.visible = !inModeRotate && !isCameraInsideBox; - selectionBoxGeometry.ignorePickIntersection = !selectionBoxGeometry.visible; - Overlays.editOverlay(selectionBox, selectionBoxGeometry); - - // UPDATE ICON TRANSLATE HANDLE - if (SelectionManager.entityType === "ParticleEffect" || SelectionManager.entityType === "Light") { - var iconSelectionBoxGeometry = { - position: position, - rotation: rotation - }; - iconSelectionBoxGeometry.visible = !inModeRotate && isCameraInsideBox; - iconSelectionBoxGeometry.ignorePickIntersection = !iconSelectionBoxGeometry.visible; - Overlays.editOverlay(iconSelectionBox, iconSelectionBoxGeometry); - } else { - Overlays.editOverlay(iconSelectionBox, { - visible: false, - ignorePickIntersection: true - }); - } - - // UPDATE DUPLICATOR (CURRENTLY HIDDEN FOR NOW) - var handleDuplicatorOffset = { - x: DUPLICATOR_OFFSET.x * dimensions.x, - y: DUPLICATOR_OFFSET.y * dimensions.y, - z: DUPLICATOR_OFFSET.z * dimensions.z - }; - var handleDuplicatorPos = Vec3.sum(position, Vec3.multiplyQbyV(rotation, handleDuplicatorOffset)); - Overlays.editOverlay(handleDuplicator, { - position: handleDuplicatorPos, - rotation: rotation, - dimensions: scaleCubeDimensions - }); - } - - that.setHandleTranslateXVisible(!activeTool || isActiveTool(handleTranslateXCone) || - isActiveTool(handleTranslateXCylinder)); - that.setHandleTranslateYVisible(!activeTool || isActiveTool(handleTranslateYCone) || - isActiveTool(handleTranslateYCylinder)); - that.setHandleTranslateZVisible(!activeTool || isActiveTool(handleTranslateZCone) || - isActiveTool(handleTranslateZCylinder)); - that.setHandleRotatePitchVisible(!activeTool || isActiveTool(handleRotatePitchRing)); - that.setHandleRotateYawVisible(!activeTool || isActiveTool(handleRotateYawRing)); - that.setHandleRotateRollVisible(!activeTool || isActiveTool(handleRotateRollRing)); - - var showScaleStretch = !activeTool && SelectionManager.selections.length === 1 && spaceMode === SPACE_LOCAL; - that.setHandleStretchXVisible(showScaleStretch || isActiveTool(handleStretchXCube)); - that.setHandleStretchYVisible(showScaleStretch || isActiveTool(handleStretchYCube)); - that.setHandleStretchZVisible(showScaleStretch || isActiveTool(handleStretchZCube)); - that.setHandleScaleVisible(showScaleStretch || isActiveTool(handleScaleCube)); - - var showOutlineForZone = (SelectionManager.selections.length === 1 && - typeof SelectionManager.savedProperties[SelectionManager.selections[0]] !== "undefined" && - SelectionManager.savedProperties[SelectionManager.selections[0]].type === "Zone"); - that.setHandleBoundingBoxVisible(showOutlineForZone || (!isActiveTool(handleRotatePitchRing) && - !isActiveTool(handleRotateYawRing) && - !isActiveTool(handleRotateRollRing))); - - // keep duplicator always hidden for now since you can hold Alt to duplicate while - // translating an entity - we may bring duplicator back for HMD only later - // that.setHandleDuplicatorVisible(!activeTool || isActiveTool(handleDuplicator)); - - if (wantDebug) { - print("====== Update Handles <======="); - } - }; - Script.update.connect(that.updateHandles); - - // FUNCTION: UPDATE ACTIVE ROTATE RING - that.updateActiveRotateRing = function() { - var activeRotateRing = null; - if (isActiveTool(handleRotatePitchRing)) { - activeRotateRing = handleRotatePitchRing; - } else if (isActiveTool(handleRotateYawRing)) { - activeRotateRing = handleRotateYawRing; - } else if (isActiveTool(handleRotateRollRing)) { - activeRotateRing = handleRotateRollRing; - } - if (activeRotateRing !== null) { - var tickMarksAngle = ctrlPressed ? ROTATE_CTRL_SNAP_ANGLE : ROTATE_DEFAULT_TICK_MARKS_ANGLE; - Overlays.editOverlay(activeRotateRing, { majorTickMarksAngle: tickMarksAngle }); - } - }; - - // FUNCTION: SET OVERLAYS VISIBLE - that.setOverlaysVisible = function(isVisible) { - for (var i = 0, length = allOverlays.length; i < length; i++) { - Overlays.editOverlay(allOverlays[i], { visible: isVisible, ignorePickIntersection: !isVisible }); - } - }; - - // FUNCTION: SET HANDLE TRANSLATE VISIBLE - that.setHandleTranslateVisible = function(isVisible) { - that.setHandleTranslateXVisible(isVisible); - that.setHandleTranslateYVisible(isVisible); - that.setHandleTranslateZVisible(isVisible); - }; - - that.setHandleTranslateXVisible = function(isVisible) { - Overlays.editOverlay(handleTranslateXCone, { visible: isVisible, ignorePickIntersection: !isVisible }); - Overlays.editOverlay(handleTranslateXCylinder, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - that.setHandleTranslateYVisible = function(isVisible) { - Overlays.editOverlay(handleTranslateYCone, { visible: isVisible, ignorePickIntersection: !isVisible }); - Overlays.editOverlay(handleTranslateYCylinder, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - that.setHandleTranslateZVisible = function(isVisible) { - Overlays.editOverlay(handleTranslateZCone, { visible: isVisible, ignorePickIntersection: !isVisible }); - Overlays.editOverlay(handleTranslateZCylinder, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - // FUNCTION: SET HANDLE ROTATE VISIBLE - that.setHandleRotateVisible = function(isVisible) { - that.setHandleRotatePitchVisible(isVisible); - that.setHandleRotateYawVisible(isVisible); - that.setHandleRotateRollVisible(isVisible); - }; - - that.setHandleRotatePitchVisible = function(isVisible) { - Overlays.editOverlay(handleRotatePitchRing, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - that.setHandleRotateYawVisible = function(isVisible) { - Overlays.editOverlay(handleRotateYawRing, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - that.setHandleRotateRollVisible = function(isVisible) { - Overlays.editOverlay(handleRotateRollRing, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - // FUNCTION: SET HANDLE STRETCH VISIBLE - that.setHandleStretchVisible = function(isVisible) { - that.setHandleStretchXVisible(isVisible); - that.setHandleStretchYVisible(isVisible); - that.setHandleStretchZVisible(isVisible); - }; - - that.setHandleStretchXVisible = function(isVisible) { - Overlays.editOverlay(handleStretchXCube, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - that.setHandleStretchYVisible = function(isVisible) { - Overlays.editOverlay(handleStretchYCube, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - that.setHandleStretchZVisible = function(isVisible) { - Overlays.editOverlay(handleStretchZCube, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - // FUNCTION: SET HANDLE SCALE VISIBLE - that.setHandleScaleVisible = function(isVisible) { - that.setHandleScaleVisible(isVisible); - that.setHandleBoundingBoxVisible(isVisible); - }; - - that.setHandleScaleVisible = function(isVisible) { - Overlays.editOverlay(handleScaleCube, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - that.setHandleBoundingBoxVisible = function(isVisible) { - Overlays.editOverlay(handleBoundingBox, { visible: isVisible, ignorePickIntersection: true }); - }; - - // FUNCTION: SET HANDLE DUPLICATOR VISIBLE - that.setHandleDuplicatorVisible = function(isVisible) { - Overlays.editOverlay(handleDuplicator, { visible: isVisible, ignorePickIntersection: !isVisible }); - }; - - // FUNCTION: DEBUG PICK PLANE - that.showDebugPickPlane = function(pickPlanePosition, pickPlaneNormal) { - var planePlusNormal = Vec3.sum(pickPlanePosition, pickPlaneNormal); - var rotation = Quat.lookAtSimple(planePlusNormal, pickPlanePosition); - var dimensionXZ = getDistanceToCamera(pickPlanePosition) * 1.25; - var dimensions = { x:dimensionXZ, y:dimensionXZ, z:STRETCH_PANEL_WIDTH }; - Overlays.editOverlay(debugPickPlane, { - position: pickPlanePosition, - rotation: rotation, - dimensions: dimensions, - visible: true - }); - }; - - that.showDebugPickPlaneHit = function(pickHitPosition) { - var dimension = getDistanceToCamera(pickHitPosition) * DEBUG_PICK_PLANE_HIT_CAMERA_DISTANCE_MULTIPLE; - var pickPlaneHit = Overlays.addOverlay("shape", { - alpha: 0.5, - shape: "Sphere", - solid: true, - visible: true, - ignorePickIntersection: true, - drawInFront: false, - color: COLOR_DEBUG_PICK_PLANE_HIT, - position: pickHitPosition, - dimensions: { x: dimension, y: dimension, z: dimension } - }); - debugPickPlaneHits.push(pickPlaneHit); - if (debugPickPlaneHits.length > DEBUG_PICK_PLANE_HIT_LIMIT) { - var removedPickPlaneHit = debugPickPlaneHits.shift(); - Overlays.deleteOverlay(removedPickPlaneHit); - } - }; - - that.clearDebugPickPlane = function() { - Overlays.editOverlay(debugPickPlane, { visible: false }); - for (var i = 0; i < debugPickPlaneHits.length; i++) { - Overlays.deleteOverlay(debugPickPlaneHits[i]); - } - debugPickPlaneHits = []; - }; - - // TOOL DEFINITION: HANDLE TRANSLATE XZ TOOL - function addHandleTranslateXZTool(overlay, mode, doDuplicate) { - var initialPick = null; - var isConstrained = false; - var constrainMajorOnly = false; - var startPosition = null; - var duplicatedEntityIDs = null; - var pickPlanePosition = null; - var pickPlaneNormal = { x: 0, y: 1, z: 0 }; - var greatestDimension = 0.0; - var startingDistance = 0.0; - var startingElevation = 0.0; - addHandleTool(overlay, { - mode: mode, - onBegin: function(event, pickRay, pickResult) { - var wantDebug = false; - if (wantDebug) { - print("================== TRANSLATE_XZ(Beg) -> ======================="); - Vec3.print(" pickRay", pickRay); - Vec3.print(" pickRay.origin", pickRay.origin); - Vec3.print(" pickResult.intersection", pickResult.intersection); - } - - // Duplicate entities if alt is pressed. This will make a - // copy of the selected entities and move the _original_ entities, not - // the new ones. - if (event.isAlt || doDuplicate) { - duplicatedEntityIDs = SelectionManager.duplicateSelection(); - var ids = []; - for (var i = 0; i < duplicatedEntityIDs.length; ++i) { - ids.push(duplicatedEntityIDs[i].entityID); - } - SelectionManager.setSelections(ids); - } else { - duplicatedEntityIDs = null; - } - - SelectionManager.saveProperties(); - that.resetPreviousHandleColor(); - - that.setHandleTranslateVisible(false); - that.setHandleRotateVisible(false); - that.setHandleScaleVisible(false); - that.setHandleStretchVisible(false); - that.setHandleDuplicatorVisible(false); - - startPosition = SelectionManager.worldPosition; - pickPlanePosition = pickResult.intersection; - greatestDimension = Math.max(Math.max(SelectionManager.worldDimensions.x, - SelectionManager.worldDimensions.y), - SelectionManager.worldDimensions.z); - startingDistance = Vec3.distance(pickRay.origin, SelectionManager.position); - startingElevation = this.elevation(pickRay.origin, pickPlanePosition); - if (wantDebug) { - print(" longest dimension: " + greatestDimension); - print(" starting distance: " + startingDistance); - print(" starting elevation: " + startingElevation); - } - - initialPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal); - - if (debugPickPlaneEnabled) { - that.showDebugPickPlane(pickPlanePosition, pickPlaneNormal); - that.showDebugPickPlaneHit(initialPick); - } - - isConstrained = false; - if (wantDebug) { - print("================== TRANSLATE_XZ(End) <- ======================="); - } - }, - onEnd: function(event, reason) { - pushCommandForSelections(duplicatedEntityIDs); - if (isConstrained) { - Overlays.editOverlay(xRailOverlay, { - visible: false, - ignorePickIntersection: true - }); - Overlays.editOverlay(zRailOverlay, { - visible: false, - ignorePickIntersection: true - }); - } - }, - elevation: function(origin, intersection) { - return (origin.y - intersection.y) / Vec3.distance(origin, intersection); - }, - onMove: function(event) { - var wantDebug = false; - var pickRay = generalComputePickRay(event.x, event.y); - - var newPick = rayPlaneIntersection2(pickRay, pickPlanePosition, pickPlaneNormal); - - // If the pick ray doesn't hit the pick plane in this direction, do nothing. - // this will happen when someone drags across the horizon from the side they started on. - if (!newPick) { - if (wantDebug) { - print(" "+ mode + "Pick ray does not intersect XZ plane."); - } - - // EARLY EXIT--(Invalid ray detected.) - return; - } - - if (debugPickPlaneEnabled) { - that.showDebugPickPlaneHit(newPick); - } - - var vector = Vec3.subtract(newPick, initialPick); - - // If the mouse is too close to the horizon of the pick plane, stop moving - var MIN_ELEVATION = 0.02; // largest dimension of object divided by distance to it - var elevation = this.elevation(pickRay.origin, newPick); - if (wantDebug) { - print("Start Elevation: " + startingElevation + ", elevation: " + elevation); - } - if ((startingElevation > 0.0 && elevation < MIN_ELEVATION) || - (startingElevation < 0.0 && elevation > -MIN_ELEVATION)) { - if (wantDebug) { - print(" "+ mode + " - too close to horizon!"); - } - - // EARLY EXIT--(Don't proceed past the reached limit.) - return; - } - - // If the angular size of the object is too small, stop moving - var MIN_ANGULAR_SIZE = 0.01; // Radians - if (greatestDimension > 0) { - var angularSize = Math.atan(greatestDimension / Vec3.distance(pickRay.origin, newPick)); - if (wantDebug) { - print("Angular size = " + angularSize); - } - if (angularSize < MIN_ANGULAR_SIZE) { - return; - } - } - - // If shifted, constrain to one axis - if (event.isShifted) { - if (Math.abs(vector.x) > Math.abs(vector.z)) { - vector.z = 0; - } else { - vector.x = 0; - } - if (!isConstrained) { - var xStart = Vec3.sum(startPosition, { - x: -RAIL_AXIS_LENGTH, - y: 0, - z: 0 - }); - var xEnd = Vec3.sum(startPosition, { - x: RAIL_AXIS_LENGTH, - y: 0, - z: 0 - }); - var zStart = Vec3.sum(startPosition, { - x: 0, - y: 0, - z: -RAIL_AXIS_LENGTH - }); - var zEnd = Vec3.sum(startPosition, { - x: 0, - y: 0, - z: RAIL_AXIS_LENGTH - }); - Overlays.editOverlay(xRailOverlay, { - start: xStart, - end: xEnd, - visible: true, - ignorePickIntersection: true - }); - Overlays.editOverlay(zRailOverlay, { - start: zStart, - end: zEnd, - visible: true, - ignorePickIntersection: true - }); - isConstrained = true; - } - } else { - if (isConstrained) { - Overlays.editOverlay(xRailOverlay, { - visible: false, - ignorePickIntersection: true - }); - Overlays.editOverlay(zRailOverlay, { - visible: false, - ignorePickIntersection: true - }); - isConstrained = false; - } - } - - constrainMajorOnly = event.isControl; - var negateAndHalve = -0.5; - var cornerPosition = Vec3.sum(startPosition, Vec3.multiply(negateAndHalve, SelectionManager.worldDimensions)); - vector = Vec3.subtract( - grid.snapToGrid(Vec3.sum(cornerPosition, vector), constrainMajorOnly), - cornerPosition); - - // editing a parent will cause all the children to automatically follow along, so don't - // edit any entity who has an ancestor in SelectionManager.selections - var toMove = SelectionManager.selections.filter(function (selection) { - if (SelectionManager.selections.indexOf(SelectionManager.savedProperties[selection].parentID) >= 0) { - return false; // a parent is also being moved, so don't issue an edit for this entity - } else { - return true; - } - }); - - for (var i = 0; i < toMove.length; i++) { - var properties = SelectionManager.savedProperties[toMove[i]]; - if (!properties) { - continue; - } - var newPosition = Vec3.sum(properties.position, { - x: vector.x, - y: 0, - z: vector.z - }); - Entities.editEntity(toMove[i], { - position: newPosition - }); - - if (wantDebug) { - print("translateXZ... "); - Vec3.print(" vector:", vector); - Vec3.print(" newPosition:", properties.position); - Vec3.print(" newPosition:", newPosition); - } - } - - SelectionManager._update(false, this); - } - }); - } - - // TOOL DEFINITION: HANDLE TRANSLATE TOOL - function addHandleTranslateTool(overlay, mode, direction) { - var pickPlanePosition = null; - var pickPlaneNormal = null; - var initialPick = null; - var projectionVector = null; - var previousPickRay = null; - var rotation = null; - addHandleTool(overlay, { - mode: mode, - onBegin: function(event, pickRay, pickResult) { - // Duplicate entities if alt is pressed. This will make a - // copy of the selected entities and move the _original_ entities, not - // the new ones. - if (event.isAlt) { - duplicatedEntityIDs = SelectionManager.duplicateSelection(); - var ids = []; - for (var i = 0; i < duplicatedEntityIDs.length; ++i) { - ids.push(duplicatedEntityIDs[i].entityID); - } - SelectionManager.setSelections(ids); - } else { - duplicatedEntityIDs = null; - } - - var axisVector; - if (direction === TRANSLATE_DIRECTION.X) { - axisVector = { x: 1, y: 0, z: 0 }; - } else if (direction === TRANSLATE_DIRECTION.Y) { - axisVector = { x: 0, y: 1, z: 0 }; - } else if (direction === TRANSLATE_DIRECTION.Z) { - axisVector = { x: 0, y: 0, z: 1 }; - } - - rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation; - axisVector = Vec3.multiplyQbyV(rotation, axisVector); - pickPlaneNormal = Vec3.cross(Vec3.cross(pickRay.direction, axisVector), axisVector); - pickPlanePosition = SelectionManager.worldPosition; - initialPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal); - - SelectionManager.saveProperties(); - that.resetPreviousHandleColor(); - - that.setHandleTranslateXVisible(direction === TRANSLATE_DIRECTION.X); - that.setHandleTranslateYVisible(direction === TRANSLATE_DIRECTION.Y); - that.setHandleTranslateZVisible(direction === TRANSLATE_DIRECTION.Z); - that.setHandleRotateVisible(false); - that.setHandleStretchVisible(false); - that.setHandleScaleVisible(false); - that.setHandleDuplicatorVisible(false); - - previousPickRay = pickRay; - - if (debugPickPlaneEnabled) { - that.showDebugPickPlane(pickPlanePosition, pickPlaneNormal); - that.showDebugPickPlaneHit(initialPick); - } - }, - onEnd: function(event, reason) { - pushCommandForSelections(duplicatedEntityIDs); - }, - onMove: function(event) { - var pickRay = generalComputePickRay(event.x, event.y); - - // Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around - if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, pickPlaneNormal)) { - pickRay = previousPickRay; - } - - var newPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal); - if (debugPickPlaneEnabled) { - that.showDebugPickPlaneHit(newPick); - } - - var vector = Vec3.subtract(newPick, initialPick); - - if (direction === TRANSLATE_DIRECTION.X) { - projectionVector = { x: 1, y: 0, z: 0 }; - } else if (direction === TRANSLATE_DIRECTION.Y) { - projectionVector = { x: 0, y: 1, z: 0 }; - } else if (direction === TRANSLATE_DIRECTION.Z) { - projectionVector = { x: 0, y: 0, z: 1 }; - } - projectionVector = Vec3.multiplyQbyV(rotation, projectionVector); - - var dotVector = Vec3.dot(vector, projectionVector); - vector = Vec3.multiply(dotVector, projectionVector); - var gridOrigin = grid.getOrigin(); - vector = Vec3.subtract(grid.snapToGrid(Vec3.sum(vector, gridOrigin)), gridOrigin); - - var wantDebug = false; - if (wantDebug) { - print("translateUpDown... "); - print(" event.y:" + event.y); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - } - - // editing a parent will cause all the children to automatically follow along, so don't - // edit any entity who has an ancestor in SelectionManager.selections - var toMove = SelectionManager.selections.filter(function (selection) { - if (SelectionManager.selections.indexOf(SelectionManager.savedProperties[selection].parentID) >= 0) { - return false; // a parent is also being moved, so don't issue an edit for this entity - } else { - return true; - } - }); - - for (var i = 0; i < toMove.length; i++) { - var id = toMove[i]; - var properties = SelectionManager.savedProperties[id]; - var newPosition = Vec3.sum(properties.position, vector); - Entities.editEntity(id, { position: newPosition }); - } - - previousPickRay = pickRay; - - SelectionManager._update(false, this); - } - }); - } - - // TOOL DEFINITION: HANDLE STRETCH TOOL - function addHandleStretchTool(overlay, mode, directionEnum) { - var initialPick = null; - var initialPosition = null; - var initialDimensions = null; - var rotation = null; - var registrationPoint = null; - var pickPlanePosition = null; - var pickPlaneNormal = null; - var previousPickRay = null; - var directionVector = null; - var axisVector = null; - var signs = null; - var mask = null; - var stretchPanel = null; - var handleStretchCube = null; - var deltaPivot = null; - addHandleTool(overlay, { - mode: mode, - onBegin: function(event, pickRay, pickResult) { - if (directionEnum === STRETCH_DIRECTION.X) { - stretchPanel = handleStretchXPanel; - handleStretchCube = handleStretchXCube; - directionVector = { x: -1, y: 0, z: 0 }; - } else if (directionEnum === STRETCH_DIRECTION.Y) { - stretchPanel = handleStretchYPanel; - handleStretchCube = handleStretchYCube; - directionVector = { x: 0, y: -1, z: 0 }; - } else if (directionEnum === STRETCH_DIRECTION.Z) { - stretchPanel = handleStretchZPanel; - handleStretchCube = handleStretchZCube; - directionVector = { x: 0, y: 0, z: -1 }; - } - - rotation = SelectionManager.localRotation; - initialPosition = SelectionManager.localPosition; - initialDimensions = SelectionManager.localDimensions; - registrationPoint = SelectionManager.localRegistrationPoint; - - axisVector = Vec3.multiply(NEGATE_VECTOR, directionVector); - axisVector = Vec3.multiplyQbyV(rotation, axisVector); - - signs = { - x: directionVector.x < 0 ? -1 : (directionVector.x > 0 ? 1 : 0), - y: directionVector.y < 0 ? -1 : (directionVector.y > 0 ? 1 : 0), - z: directionVector.z < 0 ? -1 : (directionVector.z > 0 ? 1 : 0) - }; - mask = { - x: Math.abs(directionVector.x) > 0 ? 1 : 0, - y: Math.abs(directionVector.y) > 0 ? 1 : 0, - z: Math.abs(directionVector.z) > 0 ? 1 : 0 - }; - - var pivot = directionVector; - var offset = Vec3.multiply(directionVector, NEGATE_VECTOR); - - // Modify range of registrationPoint to be [-0.5, 0.5] - var centeredRP = Vec3.subtract(registrationPoint, { - x: 0.5, - y: 0.5, - z: 0.5 - }); - - // Scale pivot to be in the same range as registrationPoint - var scaledPivot = Vec3.multiply(0.5, pivot); - deltaPivot = Vec3.subtract(centeredRP, scaledPivot); - - var scaledOffset = Vec3.multiply(0.5, offset); - - // Offset from the registration point - var offsetRP = Vec3.subtract(scaledOffset, centeredRP); - - // Scaled offset in world coordinates - var scaledOffsetWorld = Vec3.multiplyVbyV(initialDimensions, offsetRP); - - pickPlaneNormal = Vec3.cross(Vec3.cross(pickRay.direction, axisVector), axisVector); - pickPlanePosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld)); - initialPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal); - - that.setHandleTranslateVisible(false); - that.setHandleRotateVisible(false); - that.setHandleScaleVisible(true); - that.setHandleStretchXVisible(directionEnum === STRETCH_DIRECTION.X); - that.setHandleStretchYVisible(directionEnum === STRETCH_DIRECTION.Y); - that.setHandleStretchZVisible(directionEnum === STRETCH_DIRECTION.Z); - that.setHandleDuplicatorVisible(false); - - SelectionManager.saveProperties(); - that.resetPreviousHandleColor(); - - var collisionToRemove = "myAvatar"; - var properties = Entities.getEntityProperties(SelectionManager.selections[0]); - if (properties.collidesWith.indexOf(collisionToRemove) > -1) { - var newCollidesWith = properties.collidesWith.replace(collisionToRemove, ""); - Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith}); - that.replaceCollisionsAfterStretch = true; - } - - if (stretchPanel !== null) { - Overlays.editOverlay(stretchPanel, { visible: true, ignorePickIntersection: false }); - } - var stretchCubePosition = Overlays.getProperty(handleStretchCube, "position"); - var stretchPanelPosition = Overlays.getProperty(stretchPanel, "position"); - activeStretchCubePanelOffset = Vec3.subtract(stretchPanelPosition, stretchCubePosition); - - previousPickRay = pickRay; - - if (debugPickPlaneEnabled) { - that.showDebugPickPlane(pickPlanePosition, pickPlaneNormal); - that.showDebugPickPlaneHit(initialPick); - } - }, - onEnd: function(event, reason) { - if (that.replaceCollisionsAfterStretch) { - var newCollidesWith = SelectionManager.savedProperties[SelectionManager.selections[0]].collidesWith; - Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith}); - that.replaceCollisionsAfterStretch = false; - } - - if (stretchPanel !== null) { - Overlays.editOverlay(stretchPanel, { visible: false, ignorePickIntersection: true }); - } - activeStretchCubePanelOffset = null; - - pushCommandForSelections(); - }, - onMove: function(event) { - var pickRay = generalComputePickRay(event.x, event.y); - - // Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around - if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, pickPlaneNormal)) { - pickRay = previousPickRay; - } - - var newPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal); - if (debugPickPlaneEnabled) { - that.showDebugPickPlaneHit(newPick); - } - - var changeInDimensions = Vec3.subtract(newPick, initialPick); - var dotVector = Vec3.dot(changeInDimensions, axisVector); - changeInDimensions = Vec3.multiply(dotVector, axisVector); - changeInDimensions = Vec3.multiplyQbyV(Quat.inverse(rotation), changeInDimensions); - changeInDimensions = Vec3.multiplyVbyV(mask, changeInDimensions); - changeInDimensions = grid.snapToSpacing(changeInDimensions); - changeInDimensions = Vec3.multiply(NEGATE_VECTOR, Vec3.multiplyVbyV(signs, changeInDimensions)); - - var newDimensions = Vec3.sum(initialDimensions, changeInDimensions); - - var minimumDimension = Entities.getPropertyInfo("dimensions").minimum; - if (newDimensions.x < minimumDimension) { - newDimensions.x = minimumDimension; - changeInDimensions.x = minimumDimension - initialDimensions.x; - } - if (newDimensions.y < minimumDimension) { - newDimensions.y = minimumDimension; - changeInDimensions.y = minimumDimension - initialDimensions.y; - } - if (newDimensions.z < minimumDimension) { - newDimensions.z = minimumDimension; - changeInDimensions.z = minimumDimension - initialDimensions.z; - } - - var changeInPosition = Vec3.multiplyQbyV(rotation, Vec3.multiplyVbyV(deltaPivot, changeInDimensions)); - var newPosition = Vec3.sum(initialPosition, changeInPosition); - - Entities.editEntity(SelectionManager.selections[0], { - position: newPosition, - dimensions: newDimensions - }); - - var wantDebug = false; - if (wantDebug) { - print(mode); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - previousPickRay = pickRay; - - SelectionManager._update(false, this); - } - }); - } - - // TOOL DEFINITION: HANDLE SCALE TOOL - function addHandleScaleTool(overlay, mode) { - var initialPick = null; - var initialPosition = null; - var initialDimensions = null; - var pickPlanePosition = null; - var pickPlaneNormal = null; - var previousPickRay = null; - addHandleTool(overlay, { - mode: mode, - onBegin: function(event, pickRay, pickResult) { - initialPosition = SelectionManager.localPosition; - initialDimensions = SelectionManager.localDimensions; - - pickPlanePosition = initialPosition; - pickPlaneNormal = Vec3.subtract(pickRay.origin, pickPlanePosition); - initialPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal); - - that.setHandleTranslateVisible(false); - that.setHandleRotateVisible(false); - that.setHandleScaleVisible(true); - that.setHandleStretchVisible(false); - that.setHandleDuplicatorVisible(false); - - SelectionManager.saveProperties(); - that.resetPreviousHandleColor(); - - var collisionToRemove = "myAvatar"; - var properties = Entities.getEntityProperties(SelectionManager.selections[0]); - if (properties.collidesWith.indexOf(collisionToRemove) > -1) { - var newCollidesWith = properties.collidesWith.replace(collisionToRemove, ""); - Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith}); - that.replaceCollisionsAfterStretch = true; - } - - previousPickRay = pickRay; - - if (debugPickPlaneEnabled) { - that.showDebugPickPlane(pickPlanePosition, pickPlaneNormal); - that.showDebugPickPlaneHit(initialPick); - } - }, - onEnd: function(event, reason) { - if (that.replaceCollisionsAfterStretch) { - var newCollidesWith = SelectionManager.savedProperties[SelectionManager.selections[0]].collidesWith; - Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith}); - that.replaceCollisionsAfterStretch = false; - } - - pushCommandForSelections(); - }, - onMove: function(event) { - var pickRay = generalComputePickRay(event.x, event.y); - - // Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around - if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, pickPlaneNormal)) { - pickRay = previousPickRay; - } - - var newPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal); - if (debugPickPlaneEnabled) { - that.showDebugPickPlaneHit(newPick); - } - - var toCameraDistance = getDistanceToCamera(initialPosition); - var dimensionsMultiple = toCameraDistance * SCALE_DIMENSIONS_CAMERA_DISTANCE_MULTIPLE; - var changeInDimensions = Vec3.subtract(newPick, initialPick); - changeInDimensions = Vec3.multiplyQbyV(Quat.inverse(Camera.orientation), changeInDimensions); - changeInDimensions = grid.snapToSpacing(changeInDimensions); - changeInDimensions = Vec3.multiply(changeInDimensions, dimensionsMultiple); - - var averageDimensionChange = (changeInDimensions.x + changeInDimensions.y + changeInDimensions.z) / 3; - var averageInitialDimension = (initialDimensions.x + initialDimensions.y + initialDimensions.z) / 3; - percentChange = averageDimensionChange / averageInitialDimension; - percentChange += 1.0; - - var newDimensions = Vec3.multiply(percentChange, initialDimensions); - newDimensions.x = Math.abs(newDimensions.x); - newDimensions.y = Math.abs(newDimensions.y); - newDimensions.z = Math.abs(newDimensions.z); - - var minimumDimension = Entities.getPropertyInfo("dimensions").minimum; - if (newDimensions.x < minimumDimension) { - newDimensions.x = minimumDimension; - changeInDimensions.x = minimumDimension - initialDimensions.x; - } - if (newDimensions.y < minimumDimension) { - newDimensions.y = minimumDimension; - changeInDimensions.y = minimumDimension - initialDimensions.y; - } - if (newDimensions.z < minimumDimension) { - newDimensions.z = minimumDimension; - changeInDimensions.z = minimumDimension - initialDimensions.z; - } - - Entities.editEntity(SelectionManager.selections[0], { dimensions: newDimensions }); - - var wantDebug = false; - if (wantDebug) { - print(mode); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - } - - previousPickRay = pickRay; - - SelectionManager._update(false, this); - } - }); - } - - // FUNCTION: UPDATE ROTATION DEGREES OVERLAY - function updateRotationDegreesOverlay(angleFromZero, position) { - var toCameraDistance = getDistanceToCamera(position); - var overlayProps = { - position: position, - dimensions: { - x: toCameraDistance * ROTATE_DISPLAY_SIZE_X_MULTIPLIER, - y: toCameraDistance * ROTATE_DISPLAY_SIZE_Y_MULTIPLIER - }, - lineHeight: toCameraDistance * ROTATE_DISPLAY_LINE_HEIGHT_MULTIPLIER, - text: normalizeDegrees(-angleFromZero) + "°" - }; - Overlays.editOverlay(rotationDegreesDisplay, overlayProps); - } - - // FUNCTION DEF: updateSelectionsRotation - // Helper func used by rotation handle tools - function updateSelectionsRotation(rotationChange, initialPosition) { - if (!rotationChange) { - print("ERROR: entitySelectionTool.updateSelectionsRotation - Invalid arg specified!!"); - - // EARLY EXIT - return; - } - - // Entities should only reposition if we are rotating multiple selections around - // the selections center point. Otherwise, the rotation will be around the entities - // registration point which does not need repositioning. - var reposition = (SelectionManager.selections.length > 1); - - // editing a parent will cause all the children to automatically follow along, so don't - // edit any entity who has an ancestor in SelectionManager.selections - var toRotate = SelectionManager.selections.filter(function (selection) { - if (SelectionManager.selections.indexOf(SelectionManager.savedProperties[selection].parentID) >= 0) { - return false; // a parent is also being moved, so don't issue an edit for this entity - } else { - return true; - } - }); - - for (var i = 0; i < toRotate.length; i++) { - var entityID = toRotate[i]; - var initialProperties = SelectionManager.savedProperties[entityID]; - - var newProperties = { - rotation: Quat.multiply(rotationChange, initialProperties.rotation) - }; - - if (reposition) { - var dPos = Vec3.subtract(initialProperties.position, initialPosition); - dPos = Vec3.multiplyQbyV(rotationChange, dPos); - newProperties.position = Vec3.sum(initialPosition, dPos); - } - - Entities.editEntity(entityID, newProperties); - } - } - - // TOOL DEFINITION: HANDLE ROTATION TOOL - function addHandleRotateTool(overlay, mode, direction) { - var selectedHandle = null; - var worldRotation = null; - var initialRotation = null; - var rotationCenter = null; - var rotationNormal = null; - var rotationZero = null; - var rotationDegreesPosition = null; - addHandleTool(overlay, { - mode: mode, - onBegin: function(event, pickRay, pickResult) { - var wantDebug = false; - if (wantDebug) { - print("================== " + getMode() + "(addHandleRotateTool onBegin) -> ======================="); - } - - if (direction === ROTATE_DIRECTION.PITCH) { - rotationNormal = { x: 1, y: 0, z: 0 }; - worldRotation = worldRotationY; - selectedHandle = handleRotatePitchRing; - } else if (direction === ROTATE_DIRECTION.YAW) { - rotationNormal = { x: 0, y: 1, z: 0 }; - worldRotation = worldRotationZ; - selectedHandle = handleRotateYawRing; - } else if (direction === ROTATE_DIRECTION.ROLL) { - rotationNormal = { x: 0, y: 0, z: 1 }; - worldRotation = worldRotationX; - selectedHandle = handleRotateRollRing; - } - - initialRotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation; - rotationNormal = Vec3.multiplyQbyV(initialRotation, rotationNormal); - rotationCenter = SelectionManager.worldPosition; - - SelectionManager.saveProperties(); - that.resetPreviousHandleColor(); - - that.setHandleTranslateVisible(false); - that.setHandleRotatePitchVisible(direction === ROTATE_DIRECTION.PITCH); - that.setHandleRotateYawVisible(direction === ROTATE_DIRECTION.YAW); - that.setHandleRotateRollVisible(direction === ROTATE_DIRECTION.ROLL); - that.setHandleStretchVisible(false); - that.setHandleScaleVisible(false); - that.setHandleDuplicatorVisible(false); - - Overlays.editOverlay(selectedHandle, { - hasTickMarks: true, - solid: false, - innerRadius: ROTATE_RING_SELECTED_INNER_RADIUS - }); - - Overlays.editOverlay(rotationDegreesDisplay, { visible: true }); - Overlays.editOverlay(handleRotateCurrentRing, { - position: rotationCenter, - rotation: worldRotation, - startAt: 0, - endAt: 0, - visible: true, - ignorePickIntersection: false - }); - - // editOverlays may not have committed rotation changes. - // Compute zero position based on where the overlay will be eventually. - var initialPick = rayPlaneIntersection(pickRay, rotationCenter, rotationNormal); - // In case of a parallel ray, this will be null, which will cause early-out - // in the onMove helper. - rotationZero = initialPick; - - var rotationCenterToZero = Vec3.subtract(rotationZero, rotationCenter); - var rotationCenterToZeroLength = Vec3.length(rotationCenterToZero); - rotationDegreesPosition = Vec3.sum(rotationCenter, Vec3.multiply(Vec3.normalize(rotationCenterToZero), - rotationCenterToZeroLength * ROTATE_DISPLAY_DISTANCE_MULTIPLIER)); - updateRotationDegreesOverlay(0, rotationDegreesPosition); - - if (debugPickPlaneEnabled) { - that.showDebugPickPlane(rotationCenter, rotationNormal); - that.showDebugPickPlaneHit(initialPick); - } - - if (wantDebug) { - print("================== " + getMode() + "(addHandleRotateTool onBegin) <- ======================="); - } - }, - onEnd: function(event, reason) { - var wantDebug = false; - if (wantDebug) { - print("================== " + getMode() + "(addHandleRotateTool onEnd) -> ======================="); - } - Overlays.editOverlay(rotationDegreesDisplay, { visible: false, ignorePickIntersection: true }); - Overlays.editOverlay(selectedHandle, { - hasTickMarks: false, - solid: true, - innerRadius: ROTATE_RING_IDLE_INNER_RADIUS - }); - Overlays.editOverlay(handleRotateCurrentRing, { visible: false, ignorePickIntersection: true }); - pushCommandForSelections(); - if (wantDebug) { - print("================== " + getMode() + "(addHandleRotateTool onEnd) <- ======================="); - } - }, - onMove: function(event) { - if (!rotationZero) { - print("ERROR: entitySelectionTool.addHandleRotateTool.onMove - " + - "Invalid RotationZero Specified (missed rotation target plane?)"); - - // EARLY EXIT - return; - } - - var wantDebug = false; - if (wantDebug) { - print("================== "+ getMode() + "(addHandleRotateTool onMove) -> ======================="); - Vec3.print(" rotationZero: ", rotationZero); - } - - var pickRay = generalComputePickRay(event.x, event.y); - var result = rayPlaneIntersection(pickRay, rotationCenter, rotationNormal); - if (result) { - var centerToZero = Vec3.subtract(rotationZero, rotationCenter); - var centerToIntersect = Vec3.subtract(result, rotationCenter); - - if (wantDebug) { - Vec3.print(" RotationNormal: ", rotationNormal); - Vec3.print(" rotationZero: ", rotationZero); - Vec3.print(" rotationCenter: ", rotationCenter); - Vec3.print(" intersect: ", result); - Vec3.print(" centerToZero: ", centerToZero); - Vec3.print(" centerToIntersect: ", centerToIntersect); - } - - // Note: orientedAngle which wants normalized centerToZero and centerToIntersect - // handles that internally, so it's to pass unnormalized vectors here. - var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); - var snapAngle = ctrlPressed ? ROTATE_CTRL_SNAP_ANGLE : ROTATE_DEFAULT_SNAP_ANGLE; - angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; - var rotationChange = Quat.angleAxis(angleFromZero, rotationNormal); - updateSelectionsRotation(rotationChange, rotationCenter); - updateRotationDegreesOverlay(-angleFromZero, rotationDegreesPosition); - - if (direction === ROTATE_DIRECTION.YAW) { - angleFromZero *= -1; - } - - var startAtCurrent = 0; - var endAtCurrent = angleFromZero; - var maxDegrees = 360; - if (angleFromZero < 0) { - startAtCurrent = maxDegrees + angleFromZero; - endAtCurrent = maxDegrees; - } - Overlays.editOverlay(handleRotateCurrentRing, { - startAt: startAtCurrent, - endAt: endAtCurrent - }); - - if (debugPickPlaneEnabled) { - that.showDebugPickPlaneHit(result); - } - } - - if (wantDebug) { - print("================== "+ getMode() + "(addHandleRotateTool onMove) <- ======================="); - } - } - }); - } - - addHandleTranslateXZTool(selectionBox, "TRANSLATE_XZ", false); - addHandleTranslateXZTool(iconSelectionBox, "TRANSLATE_XZ", false); - addHandleTranslateXZTool(handleDuplicator, "DUPLICATE", true); - - addHandleTranslateTool(handleTranslateXCone, "TRANSLATE_X", TRANSLATE_DIRECTION.X); - addHandleTranslateTool(handleTranslateXCylinder, "TRANSLATE_X", TRANSLATE_DIRECTION.X); - addHandleTranslateTool(handleTranslateYCone, "TRANSLATE_Y", TRANSLATE_DIRECTION.Y); - addHandleTranslateTool(handleTranslateYCylinder, "TRANSLATE_Y", TRANSLATE_DIRECTION.Y); - addHandleTranslateTool(handleTranslateZCone, "TRANSLATE_Z", TRANSLATE_DIRECTION.Z); - addHandleTranslateTool(handleTranslateZCylinder, "TRANSLATE_Z", TRANSLATE_DIRECTION.Z); - - addHandleRotateTool(handleRotatePitchRing, "ROTATE_PITCH", ROTATE_DIRECTION.PITCH); - addHandleRotateTool(handleRotateYawRing, "ROTATE_YAW", ROTATE_DIRECTION.YAW); - addHandleRotateTool(handleRotateRollRing, "ROTATE_ROLL", ROTATE_DIRECTION.ROLL); - - addHandleStretchTool(handleStretchXCube, "STRETCH_X", STRETCH_DIRECTION.X); - addHandleStretchTool(handleStretchYCube, "STRETCH_Y", STRETCH_DIRECTION.Y); - addHandleStretchTool(handleStretchZCube, "STRETCH_Z", STRETCH_DIRECTION.Z); - - addHandleScaleTool(handleScaleCube, "SCALE"); - - return that; -}()); diff --git a/scripts/simplifiedUI/system/assets/images/hourglass.svg b/scripts/system/create/assets/images/hourglass.svg similarity index 100% rename from scripts/simplifiedUI/system/assets/images/hourglass.svg rename to scripts/system/create/assets/images/hourglass.svg diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index ae7cd43767..f50bc547e5 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -31,7 +31,7 @@ Script.include([ "../libraries/entityCameraTool.js", "../libraries/utils.js", "../libraries/entityIconOverlayManager.js", - "../libraries/gridTool/gridTool.js", + "../libraries/gridTool.js", "entityList/entityList.js", "entitySelectionTool/entitySelectionTool.js" ]); diff --git a/scripts/system/create/modules/entityShapeVisualizer.js b/scripts/system/create/modules/entityShapeVisualizer.js index da28369cdd..dbf09a1cb7 100644 --- a/scripts/system/create/modules/entityShapeVisualizer.js +++ b/scripts/system/create/modules/entityShapeVisualizer.js @@ -146,8 +146,8 @@ EntityShape.prototype = { parentID: this.entity, priority: 1, materialMappingMode: PROJECTED_MATERIALS ? "projected" : "uv", - materialURL: Script.resolvePath("../assets/images/materials/GridPattern.json"), - ignorePickIntersection: true, + materialURL: Script.resolvePath("../../assets/images/materials/GridPattern.json"), + ignorePickIntersection: true }, "local"); }, update: function() { diff --git a/scripts/system/create/qml/EditTabView.qml b/scripts/system/create/qml/EditTabView.qml index 4c780c3427..f90a962f7a 100644 --- a/scripts/system/create/qml/EditTabView.qml +++ b/scripts/system/create/qml/EditTabView.qml @@ -263,7 +263,7 @@ TabBar { property Component visualItem: Component { WebView { id: gridControlsWebView - url: Qt.resolvedURL("../../libraries/gridTool/html/gridControls.html") + url: Qt.resolvedURL("../../html/gridControls.html") enabled: true blurOnCtrlShift: false } diff --git a/scripts/system/create/qml/EditToolsTabView.qml b/scripts/system/create/qml/EditToolsTabView.qml index fdba4cdbc9..0ce8d8e8d4 100644 --- a/scripts/system/create/qml/EditToolsTabView.qml +++ b/scripts/system/create/qml/EditToolsTabView.qml @@ -253,7 +253,7 @@ TabBar { property Component visualItem: Component { WebView { id: gridControlsWebView - url: Qt.resolvedUrl("../../libraries/gridTool/html/gridControls.html") + url: Qt.resolvedUrl("../../html/gridControls.html") enabled: true blurOnCtrlShift: false } diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 5c7623066b..38287e3af3 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -17,7 +17,7 @@ var selectionDisplay = null; // for gridTool.js to ignore (function () { // BEGIN LOCAL_SCOPE var AppUi = Script.require('appUi'); -Script.include("/~/system/libraries/gridTool/gridTool.js"); +Script.include("/~/system/libraries/gridTool.js"); Script.include("/~/system/libraries/connectionUtils.js"); Script.include("/~/system/libraries/accountUtils.js"); From bd3fe8a0925b2ab204bf0213e1ffeb144148441e Mon Sep 17 00:00:00 2001 From: Preston Bezos Date: Wed, 26 Jun 2019 09:12:32 -0700 Subject: [PATCH 60/63] fixed conflict and spacing --- .../simplifiedUI/inputDeviceButton/InputDeviceButton.qml | 2 +- .../qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml index c46367d064..0ca9abf4a8 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml @@ -163,7 +163,7 @@ Rectangle { Item { width: parent.width - height: parent.height-parent.height*level + height: parent.height - parent.height * level anchors.top: parent.top anchors.left: parent.left clip:true diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index 44b639f70b..61d2fd6634 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -47,6 +47,12 @@ Rectangle { onSkeletonModelURLChanged: { root.updatePreviewUrl(); + + if ((MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) && + topBarInventoryModel.count > 0) { + Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true); + MyAvatar.skeletonModelURL = topBarInventoryModel.get(0).download_url; + } } } @@ -95,7 +101,8 @@ Rectangle { inventoryFullyReceived = true; // If we have an avatar in our inventory AND we haven't already auto-selected an avatar... - if (!Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatar", false) && topBarInventoryModel.count > 0) { + if ((!Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatar", false) || + MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) && topBarInventoryModel.count > 0) { Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true); MyAvatar.skeletonModelURL = topBarInventoryModel.get(0).download_url; } From 59505ab20f708cf8d0c44092f530f4b495f248b5 Mon Sep 17 00:00:00 2001 From: Anna Date: Wed, 26 Jun 2019 09:29:06 -0700 Subject: [PATCH 61/63] fixed color banding on rift --- .../src/display-plugins/hmd/HmdDisplayPlugin.cpp | 4 ++++ .../src/display-plugins/hmd/HmdDisplayPlugin.h | 2 ++ plugins/oculus/src/OculusDisplayPlugin.cpp | 11 +---------- plugins/oculus/src/OculusDisplayPlugin.h | 3 --- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 3952c2c90e..0c7d83cdd8 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -174,6 +174,10 @@ float HmdDisplayPlugin::getLeftCenterPixel() const { return leftCenterPixel; } +gpu::PipelinePointer HmdDisplayPlugin::getRenderTexturePipeline() { + return _SRGBToLinearPipeline; +} + void HmdDisplayPlugin::internalPresent() { PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)presentCount()) diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 9942222f48..1f34e1b52a 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -51,6 +51,8 @@ public: std::function getHUDOperator() override; virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::PAINT; } + virtual gpu::PipelinePointer getRenderTexturePipeline() override; + signals: void hmdMountedChanged(); void hmdVisibleChanged(bool visible); diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index f928ccb8a4..161266c4af 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -124,15 +124,6 @@ void OculusDisplayPlugin::uncustomizeContext() { Parent::uncustomizeContext(); } -gpu::PipelinePointer OculusDisplayPlugin::getRenderTexturePipeline() { - //return _SRGBToLinearPipeline; - return _drawTexturePipeline; -} - -gpu::PipelinePointer OculusDisplayPlugin::getCompositeScenePipeline() { - return _SRGBToLinearPipeline; -} - static const uint64_t FRAME_BUDGET = (11 * USECS_PER_MSEC); static const uint64_t FRAME_OVER_BUDGET = (15 * USECS_PER_MSEC); @@ -172,7 +163,7 @@ void OculusDisplayPlugin::hmdPresent() { batch.setStateScissorRect(ivec4(uvec2(), _outputFramebuffer->getSize())); batch.resetViewTransform(); batch.setProjectionTransform(mat4()); - batch.setPipeline(_drawTexturePipeline); + batch.setPipeline(_SRGBToLinearPipeline); batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0)); batch.draw(gpu::TRIANGLE_STRIP, 4); }); diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index a892d27534..9209fd373e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -24,9 +24,6 @@ public: virtual QJsonObject getHardwareStats() const; - virtual gpu::PipelinePointer getRenderTexturePipeline() override; - virtual gpu::PipelinePointer getCompositeScenePipeline() override; - protected: QThread::Priority getPresentPriority() override { return QThread::TimeCriticalPriority; } From f0dd28e71a146f949deecddb57ac984fc3605fc2 Mon Sep 17 00:00:00 2001 From: Preston Bezos Date: Wed, 26 Jun 2019 09:54:43 -0700 Subject: [PATCH 62/63] removed extra line --- .../hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml index 0ca9abf4a8..15f4c42d39 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml @@ -184,7 +184,6 @@ Rectangle { source: maskImage color: "#b2b2b2" } - } } } From 5937a219dddb7be7f9588203db48b248ce8ee024 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 26 Jun 2019 15:25:17 -0700 Subject: [PATCH 63/63] wait on thread pool threads --- interface/src/Application.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eba8664f72..1a0030bc12 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2712,6 +2712,7 @@ void Application::cleanupBeforeQuit() { // Clear any queued processing (I/O, FBX/OBJ/Texture parsing) QThreadPool::globalInstance()->clear(); + QThreadPool::globalInstance()->waitForDone(); DependencyManager::destroy();