From fc47e6799059af018053a71dd13cac172c5e7297 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 16 Feb 2018 13:56:59 -0800 Subject: [PATCH 01/74] Merging with master --- libraries/render-utils/src/AntialiasingEffect.cpp | 6 +++--- libraries/render-utils/src/VelocityBufferPass.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index 7bc5328100..eb1b98aa1f 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -202,7 +202,7 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { if (!_antialiasingPipeline) { auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); - auto ps = gpu::Shader::createPixel(std::string(taa_frag)); + auto ps = taa_frag::getShader(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; @@ -233,7 +233,7 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { const gpu::PipelinePointer& Antialiasing::getBlendPipeline() { if (!_blendPipeline) { auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); - auto ps = gpu::Shader::createPixel(std::string(fxaa_blend_frag)); + auto ps = fxaa_blend_frag::getShader(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; @@ -254,7 +254,7 @@ const gpu::PipelinePointer& Antialiasing::getBlendPipeline() { const gpu::PipelinePointer& Antialiasing::getDebugBlendPipeline() { if (!_debugBlendPipeline) { auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); - auto ps = gpu::Shader::createPixel(std::string(taa_blend_frag)); + auto ps = taa_blend_frag::getShader(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; diff --git a/libraries/render-utils/src/VelocityBufferPass.cpp b/libraries/render-utils/src/VelocityBufferPass.cpp index 26dc1c6848..4f25604798 100644 --- a/libraries/render-utils/src/VelocityBufferPass.cpp +++ b/libraries/render-utils/src/VelocityBufferPass.cpp @@ -147,7 +147,7 @@ void VelocityBufferPass::run(const render::RenderContextPointer& renderContext, const gpu::PipelinePointer& VelocityBufferPass::getCameraMotionPipeline() { if (!_cameraMotionPipeline) { auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); - auto ps = gpu::Shader::createPixel(std::string(velocityBuffer_cameraMotion_frag)); + auto ps = velocityBuffer_cameraMotion_frag::getShader(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; From 27ba9172b8e9d19f31caddbc935181f8f9072518 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 16 Feb 2018 17:20:20 -0800 Subject: [PATCH 02/74] identifying the bug with defered transform in hmd and trying to apply fix for taa --- libraries/render-utils/src/DeferredFrameTransform.cpp | 2 ++ libraries/render-utils/src/DeferredFrameTransform.h | 2 ++ libraries/render-utils/src/DeferredTransform.slh | 9 +++++++++ .../render-utils/src/velocityBuffer_cameraMotion.slf | 5 +++-- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/DeferredFrameTransform.cpp b/libraries/render-utils/src/DeferredFrameTransform.cpp index cee5786847..781161a8af 100644 --- a/libraries/render-utils/src/DeferredFrameTransform.cpp +++ b/libraries/render-utils/src/DeferredFrameTransform.cpp @@ -48,6 +48,7 @@ void DeferredFrameTransform::update(RenderArgs* args) { frameTransformBuffer.projection[0] = frameTransformBuffer.projectionMono; frameTransformBuffer.stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f); frameTransformBuffer.invpixelInfo = glm::vec4(1.0f / args->_viewport.z, 1.0f / args->_viewport.w, 0.0f, 0.0f); + frameTransformBuffer.invProjection[0] = glm::inverse(frameTransformBuffer.projection[0]); } else { mat4 projMats[2]; @@ -59,6 +60,7 @@ void DeferredFrameTransform::update(RenderArgs* args) { // Compose the mono Eye space to Stereo clip space Projection Matrix auto sideViewMat = projMats[i] * eyeViews[i]; frameTransformBuffer.projection[i] = sideViewMat; + frameTransformBuffer.invProjection[i] = glm::inverse(sideViewMat); } frameTransformBuffer.stereoInfo = glm::vec4(1.0f, (float)(args->_viewport.z >> 1), 0.0f, 1.0f); diff --git a/libraries/render-utils/src/DeferredFrameTransform.h b/libraries/render-utils/src/DeferredFrameTransform.h index a90effe053..0b5cb6a989 100644 --- a/libraries/render-utils/src/DeferredFrameTransform.h +++ b/libraries/render-utils/src/DeferredFrameTransform.h @@ -45,6 +45,8 @@ protected: glm::vec4 stereoInfo{ 0.0 }; // Mono proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space glm::mat4 projection[2]; + // Inverse proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space + glm::mat4 invProjection[2]; // THe mono projection for sure glm::mat4 projectionMono; // Inv View matrix from eye space (mono) to world space diff --git a/libraries/render-utils/src/DeferredTransform.slh b/libraries/render-utils/src/DeferredTransform.slh index 25d352387f..f1765978eb 100644 --- a/libraries/render-utils/src/DeferredTransform.slh +++ b/libraries/render-utils/src/DeferredTransform.slh @@ -31,6 +31,7 @@ struct DeferredFrameTransform { vec4 _depthInfo; vec4 _stereoInfo; mat4 _projection[2]; + mat4 _invProjection[2]; mat4 _projectionMono; mat4 _viewInverse; mat4 _view; @@ -128,6 +129,14 @@ vec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) { return vec3(Xe, Ye, Zeye); } +vec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) { + // compute the view space position using the depth + vec3 clipPos; + clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0; + vec4 eyePos = frameTransform._invProjection[side] * vec4(clipPos.xyz, 1.0); + return eyePos.xyz / eyePos.w; +} + ivec2 getPixelPosTexcoordPosAndSide(in vec2 glFragCoord, out ivec2 pixelPos, out vec2 texcoordPos, out ivec4 stereoSide) { ivec2 fragPos = ivec2(glFragCoord.xy); diff --git a/libraries/render-utils/src/velocityBuffer_cameraMotion.slf b/libraries/render-utils/src/velocityBuffer_cameraMotion.slf index 7488f42535..00d5cdfb3d 100644 --- a/libraries/render-utils/src/velocityBuffer_cameraMotion.slf +++ b/libraries/render-utils/src/velocityBuffer_cameraMotion.slf @@ -26,14 +26,15 @@ void main(void) { ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide); float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x; - float Zeye = evalZeyeFromZdb(Zdb); + // float Zeye = evalZeyeFromZdb(Zdb); /* if (Zeye <= -getPosLinearDepthFar()) { outFragColor = vec4(0.5, 0.5, 0.0, 0.0); return; }*/ // The position of the pixel fragment in Eye space then in world space - vec3 eyePos = evalEyePositionFromZeye(stereoSide.x, Zeye, texcoordPos); + //vec3 eyePos = evalEyePositionFromZeye(stereoSide.x, Zeye, texcoordPos); + vec3 eyePos = evalEyePositionFromZdb(stereoSide.x, Zdb, texcoordPos); vec3 worldPos = (frameTransform._viewInverse * cameraCorrection._correction * vec4(eyePos, 1.0)).xyz; vec3 prevEyePos = (cameraCorrection._prevCorrectionInverse * frameTransform._prevView * vec4(worldPos, 1.0)).xyz; From 6d02aa064a9b531c6d537f414d5fa9d425db5575 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 13 Mar 2018 10:53:21 -0700 Subject: [PATCH 03/74] REmove any change --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 14db81d01e..df91e0ca7b 100644 --- a/.gitignore +++ b/.gitignore @@ -78,10 +78,8 @@ TAGS node_modules npm-debug.log - # ignore qmlc files generated from qml as cache *.qmlc - # Android studio files *___jb_old___ From c237e34b7119467c17a0bea75228ecef45d0abe9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 28 Mar 2018 17:47:20 -0700 Subject: [PATCH 04/74] Adding script tools --- .../utilities/render/inspectEngine.js | 39 +++++++++++++++++++ .../utilities/render/inspectEngine.qml | 19 +++++++++ 2 files changed, 58 insertions(+) create mode 100644 scripts/developer/utilities/render/inspectEngine.js create mode 100644 scripts/developer/utilities/render/inspectEngine.qml diff --git a/scripts/developer/utilities/render/inspectEngine.js b/scripts/developer/utilities/render/inspectEngine.js new file mode 100644 index 0000000000..7abce8b477 --- /dev/null +++ b/scripts/developer/utilities/render/inspectEngine.js @@ -0,0 +1,39 @@ +(function() { // BEGIN LOCAL_SCOPE + +function traverse(root, functor, depth) { + var subs = root.findChildren(/.*/) + depth++; + for (var i = 0; i Date: Wed, 28 Mar 2018 18:27:21 -0700 Subject: [PATCH 05/74] i dont't know --- .../utilities/render/inspectEngine.js | 22 ++++++++++++++----- .../utilities/render/inspectEngine.qml | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/scripts/developer/utilities/render/inspectEngine.js b/scripts/developer/utilities/render/inspectEngine.js index 7abce8b477..82231b991e 100644 --- a/scripts/developer/utilities/render/inspectEngine.js +++ b/scripts/developer/utilities/render/inspectEngine.js @@ -1,17 +1,27 @@ (function() { // BEGIN LOCAL_SCOPE -function traverse(root, functor, depth) { +function task_traverse(root, functor, depth) { var subs = root.findChildren(/.*/) depth++; for (var i = 0; i Date: Wed, 28 Nov 2018 22:37:11 -0800 Subject: [PATCH 06/74] REmove cruft --- .../utilities/render/inspectEngine.js | 49 ------------------- .../utilities/render/inspectEngine.qml | 20 -------- 2 files changed, 69 deletions(-) delete mode 100644 scripts/developer/utilities/render/inspectEngine.js delete mode 100644 scripts/developer/utilities/render/inspectEngine.qml diff --git a/scripts/developer/utilities/render/inspectEngine.js b/scripts/developer/utilities/render/inspectEngine.js deleted file mode 100644 index 82231b991e..0000000000 --- a/scripts/developer/utilities/render/inspectEngine.js +++ /dev/null @@ -1,49 +0,0 @@ -(function() { // BEGIN LOCAL_SCOPE - -function task_traverse(root, functor, depth) { - var subs = root.findChildren(/.*/) - depth++; - for (var i = 0; i Date: Fri, 30 Nov 2018 00:42:49 -0800 Subject: [PATCH 07/74] exploring better stereo drawcall techniques --- .../hmd/DebugHmdDisplayPlugin.cpp | 5 +++ .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 8 +++- .../gpu-gl-common/src/gpu/gl/GLBackend.h | 10 ++++- .../src/gpu/gl/GLBackendTransform.cpp | 42 ++++++++++++++++++- libraries/gpu/src/gpu/Transform.slh | 9 +++- libraries/shaders/headers/450/header.glsl | 1 + tools/shadergen.py | 4 ++ 7 files changed, 73 insertions(+), 6 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp index 40063652c8..3de3e590b9 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp @@ -26,6 +26,8 @@ bool DebugHmdDisplayPlugin::isSupported() const { void DebugHmdDisplayPlugin::resetSensors() { _currentRenderFrameInfo.renderPose = glm::mat4(); // identity + _currentRenderFrameInfo.renderPose = glm::translate(glm::mat4(), glm::vec3(0.0f, 1.76f, 0.0f)); + } bool DebugHmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) { @@ -35,6 +37,8 @@ bool DebugHmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) { // FIXME simulate head movement //_currentRenderFrameInfo.renderPose = ; //_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose; + _currentRenderFrameInfo.renderPose = glm::translate(glm::mat4(), glm::vec3(0.0f, 1.76f, 0.0f)); + _currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose; withNonPresentThreadLock([&] { _frameInfos[frameIndex] = _currentRenderFrameInfo; @@ -71,6 +75,7 @@ bool DebugHmdDisplayPlugin::internalActivate() { _eyeOffsets[1][3] = vec4{ 0.0327499993, 0.0, -0.0149999997, 1.0 }; _renderTargetSize = { 3024, 1680 }; _cullingProjection = _eyeProjections[0]; + // This must come after the initialization, so that the values calculated // above are available during the customizeContext call (when not running // in threaded present mode) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index c1ce05c18b..00373eb196 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -410,20 +410,24 @@ void GLBackend::render(const Batch& batch) { renderPassTransfer(batch); } -#ifdef GPU_STEREO_DRAWCALL_INSTANCED +//#ifdef GPU_STEREO_DRAWCALL_INSTANCED +#ifdef GPU_STEREO_VIEWPORT_CLIPPED if (_stereo.isStereo()) { glEnable(GL_CLIP_DISTANCE0); } #endif +//#endif { PROFILE_RANGE(render_gpu_gl_detail, _stereo.isStereo() ? "Render Stereo" : "Render"); renderPassDraw(batch); } -#ifdef GPU_STEREO_DRAWCALL_INSTANCED +//#ifdef GPU_STEREO_DRAWCALL_INSTANCED +#ifdef GPU_STEREO_VIEWPORT_CLIPPED if (_stereo.isStereo()) { glDisable(GL_CLIP_DISTANCE0); } #endif +//#endif // Restore the saved stereo state for the next batch _stereo._enable = savedStereo; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 37dde5b08e..8a459c86ca 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -36,7 +36,8 @@ #define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE #else //#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER -#define GPU_STEREO_TECHNIQUE_INSTANCED +//#define GPU_STEREO_TECHNIQUE_INSTANCED +#define GPU_STEREO_TECHNIQUE_INSTANCED_MULTIVIEWPORT #endif // Let these be configured by the one define picked above @@ -51,6 +52,13 @@ #ifdef GPU_STEREO_TECHNIQUE_INSTANCED #define GPU_STEREO_DRAWCALL_INSTANCED +#define GPU_STEREO_VIEWPORT_CLIPPED +#define GPU_STEREO_CAMERA_BUFFER +#endif + +#ifdef GPU_STEREO_TECHNIQUE_INSTANCED_MULTIVIEWPORT +#define GPU_STEREO_DRAWCALL_INSTANCED +#define GPU_STEREO_MULTI_VIEWPORT #define GPU_STEREO_CAMERA_BUFFER #endif diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp index 2c2a4e254c..caa194764d 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp @@ -39,6 +39,45 @@ void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) #ifdef GPU_STEREO_DRAWCALL_INSTANCED { + #ifdef GPU_STEREO_MULTI_VIEWPORT + ivec4& vp = _transform._viewport; + auto sideWidth = vp.z / 2; + + vec4 leftRight[3]; + + // Mono + leftRight[0] = vp; + + // Left side + leftRight[1] = vp; + leftRight[1].x = 0; + leftRight[1].z = sideWidth; + + // right side + leftRight[2] = vp; + leftRight[2].x = sideWidth; + leftRight[2].z = sideWidth; + + glViewportArrayv(0, 3, (float*)leftRight); + + // Where we assign the GL viewport + if (_stereo.isStereo()) { + + // ivec4 leftRight[3]; + // leftRight[0] = vp; + vp.z /= 2; + /* leftRight[1] = vp; // left side + leftRight[2] = vp; // right side + leftRight[2].x += vp.z; + glViewportArrayv(0, 3, (float*) leftRight); +*/ + if (_stereo._pass) { + vp.x += vp.z; + } + } else { + // glViewport(vp.x, vp.y, vp.z, vp.w); + } + #else ivec4& vp = _transform._viewport; glViewport(vp.x, vp.y, vp.z, vp.w); @@ -49,6 +88,7 @@ void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) vp.x += vp.z; } } + #endif } #else if (!_inRenderTransferPass && !isStereo()) { @@ -123,7 +163,7 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo if (_invalidView || _invalidProj || _invalidViewport) { size_t offset = _cameraUboSize * _cameras.size(); - Vec2 finalJitter = _projectionJitter / Vec2(framebufferSize); + Vec2 finalJitter = _projectionJitter / Vec2(framebufferSize); _cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset)); if (stereo.isStereo()) { diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 43205ba4c2..998204ce92 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -168,10 +168,15 @@ TransformObject getTransformObject() { vec2 eyeOffsetScale = vec2(-0.5, +0.5); uint eyeIndex = uint(_stereoSide); #ifndef GPU_GLES +#ifdef GPU_GL450 + gl_ViewportIndex = _stereoSide + 1; + // gl_ViewportIndex = 2 - _stereoSide; +#else gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]); #endif - float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w; - <$clipPos$>.x = newClipPosX; +#endif + // float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w; + // <$clipPos$>.x = newClipPosX; #endif #else diff --git a/libraries/shaders/headers/450/header.glsl b/libraries/shaders/headers/450/header.glsl index 6ce61b4378..a33b7634b1 100644 --- a/libraries/shaders/headers/450/header.glsl +++ b/libraries/shaders/headers/450/header.glsl @@ -1,4 +1,5 @@ #version 450 core +#extension GL_ARB_shader_viewport_layer_array : require #define GPU_GL450 #define GPU_SSBO_TRANSFORM_OBJECT #define BITFIELD int diff --git a/tools/shadergen.py b/tools/shadergen.py index ffbe1662ec..120fcc6bb7 100644 --- a/tools/shadergen.py +++ b/tools/shadergen.py @@ -190,6 +190,10 @@ def processCommand(line): if (dialect == '310es'): spirvCrossDialect = '320es' spirvCrossArgs = [spirvCrossExec, '--output', glslFile, spirvFile, '--version', spirvCrossDialect] if (dialect == '410'): spirvCrossArgs.append('--no-420pack-extension') + if (dialect == '450'): + spirvCrossArgs.append('--extension') + spirvCrossArgs.append('GL_ARB_shader_viewport_layer_array') + executeSubprocess(spirvCrossArgs) else: # This logic is necessary because cmake will agressively keep re-executing the shadergen From 9125f4ff41f43c5a1aaa0911a701cd5083a87a19 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 1 Mar 2019 17:45:33 -0800 Subject: [PATCH 08/74] Trying to hack the stereo for layered --- libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp | 3 +++ libraries/gpu/src/gpu/Transform.slh | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp index 130932238d..698a70af5a 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp @@ -47,6 +47,9 @@ void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) // Mono leftRight[0] = vp; + // adding this here as im doing Layered, force the first viewport here to be half of it + leftRight[0].x = 0; + leftRight[0].z = sideWidth; // Left side leftRight[1] = vp; diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 9298ddcba4..484ad7ebd2 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -169,8 +169,10 @@ TransformObject getTransformObject() { uint eyeIndex = uint(_stereoSide); #if !defined(GPU_GLES) || (defined(HAVE_EXT_clip_cull_distance) && !defined(VULKAN)) #ifdef GPU_GL450 - gl_ViewportIndex = _stereoSide + 1; + /* gl_ViewportIndex = _stereoSide + 1; // gl_ViewportIndex = 2 - _stereoSide; + */// THIs is the layered version + gl_Layer = _stereoSide; #else gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]); #endif From fe23ef1485e4a152e339d6f40b53deab374bdb31 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 3 Mar 2019 23:35:40 -0800 Subject: [PATCH 09/74] Adding the prop library --- .../developer/utilities/lib/prop/Global.qml | 44 +++++++ .../utilities/lib/prop/PropColor.qml | 0 .../developer/utilities/lib/prop/PropEnum.qml | 110 ++++++++++++++++++ .../developer/utilities/lib/prop/PropItem.qml | 62 ++++++++++ .../utilities/lib/prop/PropLabel.qml | 25 ++++ .../utilities/lib/prop/PropScalar.qml | 71 +++++++++++ .../utilities/lib/prop/PropSplitter.qml | 21 ++++ .../developer/utilities/lib/prop/PropText.qml | 24 ++++ scripts/developer/utilities/lib/prop/qmldir | 8 ++ scripts/developer/utilities/render/luci.qml | 59 ++++++++++ scripts/developer/utilities/render/luci2.js | 13 +++ 11 files changed, 437 insertions(+) create mode 100644 scripts/developer/utilities/lib/prop/Global.qml create mode 100644 scripts/developer/utilities/lib/prop/PropColor.qml create mode 100644 scripts/developer/utilities/lib/prop/PropEnum.qml create mode 100644 scripts/developer/utilities/lib/prop/PropItem.qml create mode 100644 scripts/developer/utilities/lib/prop/PropLabel.qml create mode 100644 scripts/developer/utilities/lib/prop/PropScalar.qml create mode 100644 scripts/developer/utilities/lib/prop/PropSplitter.qml create mode 100644 scripts/developer/utilities/lib/prop/PropText.qml create mode 100644 scripts/developer/utilities/lib/prop/qmldir create mode 100644 scripts/developer/utilities/render/luci.qml create mode 100644 scripts/developer/utilities/render/luci2.js diff --git a/scripts/developer/utilities/lib/prop/Global.qml b/scripts/developer/utilities/lib/prop/Global.qml new file mode 100644 index 0000000000..be189e3c96 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/Global.qml @@ -0,0 +1,44 @@ +// +// Prop/Global.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +import stylesUit 1.0 +import controlsUit 1.0 as HifiControls + + +Item { + HifiConstants { id: hifi } + id: root + + property real lineHeight: 32 + property real slimHeight: 24 + + property var color: hifi.colors.baseGray + property var colorBackHighlight: hifi.colors.baseGrayHighlight + property var colorBorderLight: hifi.colors.lightGray + property var colorBorderHighight: hifi.colors.blueHighlight + + property real fontSize: 12 + property var fontFamily: "Raleway" + property var fontWeight: Font.DemiBold + property var fontColor: hifi.colors.faintGray + + property var splitterRightWidthScale: 0.44 + property real splitterWidth: 4 + + property var labelTextAlign: Text.AlignRight + property var labelTextElide: Text.ElideMiddle + + property var valueAreaWidthScale: 0.3 * (1.0 - splitterRightWidthScale) + property var valueTextAlign: Text.AlignHCenter + property real valueBorderWidth: 1 + property real valueBorderRadius: 2 +} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/prop/PropColor.qml b/scripts/developer/utilities/lib/prop/PropColor.qml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/developer/utilities/lib/prop/PropEnum.qml b/scripts/developer/utilities/lib/prop/PropEnum.qml new file mode 100644 index 0000000000..fe6200d971 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/PropEnum.qml @@ -0,0 +1,110 @@ +// +// PropEnum.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 +import QtQuick.Controls 2.2 + +PropItem { + Global { id: global } + id: root + + property alias valueVar : valueCombo.currentIndex + property alias enums : valueCombo.model + + ComboBox { + id: valueCombo + + flat: true + + anchors.left: root.splitter.right + anchors.right: parent.right + anchors.verticalCenter: root.verticalCenter + height: global.slimHeight + + currentIndex: root.valueVarGetter() + onCurrentIndexChanged: { root.valueVarSetter(currentIndex); } + + delegate: ItemDelegate { + width: valueCombo.width + height: valueCombo.height + contentItem: PropText { + text: modelData + horizontalAlignment: global.valueTextAlign + } + background: Rectangle { + color:highlighted?global.colorBackHighlight:global.color; + } + highlighted: valueCombo.highlightedIndex === index + } + + indicator: Canvas { + id: canvas + x: valueCombo.width - width - valueCombo.rightPadding + y: valueCombo.topPadding + (valueCombo.availableHeight - height) / 2 + width: 12 + height: 8 + contextType: "2d" + + Connections { + target: valueCombo + onPressedChanged: canvas.requestPaint() + } + + onPaint: { + context.reset(); + context.moveTo(0, 0); + context.lineTo(width, 0); + context.lineTo(width / 2, height); + context.closePath(); + context.fillStyle = (valueCombo.pressed) ? global.colorBorderHighight : global.colorBorderLight; + context.fill(); + } + } + + contentItem: PropText { + leftPadding: 0 + rightPadding: valueCombo.indicator.width + valueCombo.spacing + + text: valueCombo.displayText + horizontalAlignment: global.valueTextAlign + } + + background: Rectangle { + implicitWidth: 120 + implicitHeight: 40 + color: global.color + border.color: valueCombo.popup.visible ? global.colorBorderHighight : global.colorBorderLight + border.width: global.valueBorderWidth + radius: global.valueBorderRadius + } + + popup: Popup { + y: valueCombo.height - 1 + width: valueCombo.width + implicitHeight: contentItem.implicitHeight + 2 + padding: 1 + + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: valueCombo.popup.visible ? valueCombo.delegateModel : null + currentIndex: valueCombo.highlightedIndex + + ScrollIndicator.vertical: ScrollIndicator { } + } + + background: Rectangle { + color: global.color + border.color: global.colorBorderHighight + radius: global.valueBorderRadius + } + } + } +} diff --git a/scripts/developer/utilities/lib/prop/PropItem.qml b/scripts/developer/utilities/lib/prop/PropItem.qml new file mode 100644 index 0000000000..ee1e99a772 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/PropItem.qml @@ -0,0 +1,62 @@ +// +// PropItem.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +Item { + Global { id: global } + + id: root + + // Prop item is designed to author an object[property]: + property var object: NULL + property string property: "" + + // value is accessed through the "valueVarSetter" and "valueVarGetter" + // By default, these just go get or set the value from the object[property] + // + function defaultGet() { return root.object[root.property]; } + function defaultSet(value) { root.object[root.property] = value; } + property var valueVarSetter: defaultSet + property var valueVarGetter: defaultGet + + // PropItem is stretching horizontally accross its parent + // Fixed height + anchors.left: parent.left + anchors.right: parent.right + height: global.lineHeight + + + // LabelControl And SplitterControl are on the left side of the PropItem + property bool showLabel: true + property alias labelControl: labelControl + property alias label: labelControl.text + + property var labelAreaWidth: root.width * global.splitterRightWidthScale - global.splitterWidth + + PropText { + id: labelControl + text: root.label + enabled: root.showLabel + + anchors.left: root.left + anchors.verticalCenter: root.verticalCenter + width: labelAreaWidth + } + + property alias splitter: splitterControl + PropSplitter { + id: splitterControl + + anchors.left: labelControl.right + size: global.splitterWidth + } + +} diff --git a/scripts/developer/utilities/lib/prop/PropLabel.qml b/scripts/developer/utilities/lib/prop/PropLabel.qml new file mode 100644 index 0000000000..9dbeffe0ec --- /dev/null +++ b/scripts/developer/utilities/lib/prop/PropLabel.qml @@ -0,0 +1,25 @@ +// +// PropLabel.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 +import QtQuick.Controls 2.2 + +Label { + Global { id: global } + + color: global.fontColor + font.pixelSize: global.fontSize + font.family: global.fontFamily + font.weight: global.fontWeight + verticalAlignment: Text.AlignVCenter + horizontalAlignment: global.labelTextAlign + elide: global.labelTextElide +} + diff --git a/scripts/developer/utilities/lib/prop/PropScalar.qml b/scripts/developer/utilities/lib/prop/PropScalar.qml new file mode 100644 index 0000000000..29b42e2801 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/PropScalar.qml @@ -0,0 +1,71 @@ +// +// PropItem.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +import controlsUit 1.0 as HifiControls + +PropItem { + Global { id: global } + id: root + + // Scalar Prop + 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(); + } + + PropLabel { + id: valueLabel + enabled: root.showValue + + anchors.left: root.splitter.right + anchors.verticalCenter: root.verticalCenter + width: root.width * global.valueAreaWidthScale + horizontalAlignment: global.valueTextAlign + height: global.slimHeight + + text: sliderControl.value.toFixed(root.integral ? 0 : root.numDigits) + + background: Rectangle { + color: global.color + border.color: global.colorBorderLight + border.width: global.valueBorderWidth + radius: global.valueBorderRadius + } + } + + HifiControls.Slider { + id: sliderControl + stepSize: root.integral ? 1.0 : 0.0 + anchors.left: valueLabel.right + anchors.right: root.right + anchors.rightMargin: 0 + anchors.verticalCenter: root.verticalCenter + + onValueChanged: { root.valueVarSetter(value) } + } + + +} diff --git a/scripts/developer/utilities/lib/prop/PropSplitter.qml b/scripts/developer/utilities/lib/prop/PropSplitter.qml new file mode 100644 index 0000000000..25f668a6eb --- /dev/null +++ b/scripts/developer/utilities/lib/prop/PropSplitter.qml @@ -0,0 +1,21 @@ +// +// PropSplitter.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +Item { + id: root + property real size + + width: size // Must be non-zero + height: size + + anchors.verticalCenter: parent.verticalCenter +} diff --git a/scripts/developer/utilities/lib/prop/PropText.qml b/scripts/developer/utilities/lib/prop/PropText.qml new file mode 100644 index 0000000000..b1669f3836 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/PropText.qml @@ -0,0 +1,24 @@ +// +// Prop/Text.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +Text { + Global { id: global } + + color: global.fontColor + font.pixelSize: global.fontSize + font.family: global.fontFamily + font.weight: global.fontWeight + verticalAlignment: Text.AlignVCenter + horizontalAlignment: global.labelTextAlign + elide: global.labelTextElide +} + diff --git a/scripts/developer/utilities/lib/prop/qmldir b/scripts/developer/utilities/lib/prop/qmldir new file mode 100644 index 0000000000..44e4889ab6 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/qmldir @@ -0,0 +1,8 @@ +PropGlobal 1.0 PropGlobal.qml +PropText 1.0 PropText.qml +PropLabel 1.0 PropLabel.qml +PropSplitter 1.0 PropSplitter.qml +PropItem 1.0 PropItem.qml +PropScalar 1.0 PropScalar.qml +PropEnum 1.0 PropEnum.qml +PropColor 1.0 PropColor.qml diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml new file mode 100644 index 0000000000..959a24e9be --- /dev/null +++ b/scripts/developer/utilities/render/luci.qml @@ -0,0 +1,59 @@ +// +// luci.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import controlsUit 1.0 as HifiControls + +import "../lib/prop" as Prop + +Rectangle { + Prop.Global { id: prop;} + id: render; + anchors.fill: parent + color: prop.color; + + property var mainViewTask: Render.getConfig("RenderMainView") + + Column { + anchors.left: parent.left + anchors.right: parent.right + Repeater { + model: [ "Tone mapping exposure:ToneMapping:exposure:5.0:-5.0", + "Tone:ToneMapping:exposure:5.0:-5.0" + ] + Prop.PropScalar { + label: qsTr(modelData.split(":")[0]) + integral: false + object: render.mainViewTask.getConfig(modelData.split(":")[1]) + property: modelData.split(":")[2] + max: modelData.split(":")[3] + min: modelData.split(":")[4] + + anchors.left: parent.left + anchors.right: parent.right + } + } + Prop.PropEnum { + label: "Tone Curve" + object: render.mainViewTask.getConfig("ToneMapping") + property: "curve" + enums: [ + "RGB", + "SRGB", + "Reinhard", + "Filmic", + ] + anchors.left: parent.left + anchors.right: parent.right + } + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci2.js b/scripts/developer/utilities/render/luci2.js new file mode 100644 index 0000000000..4aea49a059 --- /dev/null +++ b/scripts/developer/utilities/render/luci2.js @@ -0,0 +1,13 @@ +function openEngineTaskView() { + // Set up the qml ui + var qml = Script.resolvePath('luci.qml'); + var window = new OverlayWindow({ + title: 'luci qml', + source: qml, + width: 300, + height: 400 + }); + window.setPosition(200, 50); + //window.closed.connect(function() { Script.stop(); }); + } + openEngineTaskView(); \ No newline at end of file From 3d2614498be2de804e86d73527be5e26e88d3b7b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 4 Mar 2019 18:07:02 -0800 Subject: [PATCH 10/74] ANd fuck --- .../developer/utilities/lib/prop/PropBool.qml | 35 +++++++ .../utilities/lib/prop/PropGroup.qml | 60 ++++++++++++ .../utilities/lib/prop/style/Global.qml | 44 +++++++++ .../utilities/lib/prop/style/PiComboBox.qml | 98 +++++++++++++++++++ .../utilities/lib/prop/style/PiLabel.qml | 25 +++++ .../utilities/lib/prop/style/PiSplitter.qml | 21 ++++ .../utilities/lib/prop/style/PiText.qml | 24 +++++ 7 files changed, 307 insertions(+) create mode 100644 scripts/developer/utilities/lib/prop/PropBool.qml create mode 100644 scripts/developer/utilities/lib/prop/PropGroup.qml create mode 100644 scripts/developer/utilities/lib/prop/style/Global.qml create mode 100644 scripts/developer/utilities/lib/prop/style/PiComboBox.qml create mode 100644 scripts/developer/utilities/lib/prop/style/PiLabel.qml create mode 100644 scripts/developer/utilities/lib/prop/style/PiSplitter.qml create mode 100644 scripts/developer/utilities/lib/prop/style/PiText.qml diff --git a/scripts/developer/utilities/lib/prop/PropBool.qml b/scripts/developer/utilities/lib/prop/PropBool.qml new file mode 100644 index 0000000000..e355398375 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/PropBool.qml @@ -0,0 +1,35 @@ +// +// PropBool.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 +import controlsUit 1.0 as HifiControls + +PropItem { + Global { id: global } + id: root + + property alias valueVar : checkboxControl.checked + + Component.onCompleted: { + valueVar = root.valueVarGetter(); + } + + HifiControls.CheckBox { + id: checkboxControl + + anchors.left: root.splitter.right + anchors.verticalCenter: root.verticalCenter + width: root.width * global.valueAreaWidthScale + height: global.slimHeight + + checked: root.valueVar + onCheckedChanged: { root.valueVarSetter(checked); } + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml new file mode 100644 index 0000000000..39294743b6 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -0,0 +1,60 @@ +// +// PropGroup.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +Item { + Global { id: global } + id: root + + // Prop Group is designed to author an array of ProItems, they are defined with an array of the tuplets describing each individual item: + // [ ..., PropItemInfo, ...] + // PropItemInfo { + // "type": "PropXXXX", "object": object, "property": "propName" + // } + // + property var propItems: [] + + + property var label: "group" + + Column { + id: column + anchors.left: parent.left + anchors.right: parent.right + + PropLabel { + anchors.left: parent.left + anchors.right: parent.right + text: root.label + } + + + Component.onCompleted: { + var component = Qt.createComponent("PropBool.qml"); + component.label = "Test"; + for (var i=0; i Date: Mon, 4 Mar 2019 23:44:14 -0800 Subject: [PATCH 11/74] Fixing the bins and exploring the REpeater --- .../developer/utilities/lib/prop/Global.qml | 44 ---------- .../developer/utilities/lib/prop/PropBool.qml | 1 - .../developer/utilities/lib/prop/PropEnum.qml | 83 ++----------------- .../utilities/lib/prop/PropGroup.qml | 42 ++++++---- .../developer/utilities/lib/prop/PropItem.qml | 3 +- .../utilities/lib/prop/PropLabel.qml | 25 ------ .../utilities/lib/prop/PropSplitter.qml | 21 ----- .../developer/utilities/lib/prop/PropText.qml | 24 ------ scripts/developer/utilities/lib/prop/qmldir | 11 ++- .../utilities/lib/prop/style/Global.qml | 2 + .../utilities/lib/prop/style/PiComboBox.qml | 2 +- scripts/developer/utilities/render/luci.qml | 17 ++++ 12 files changed, 58 insertions(+), 217 deletions(-) delete mode 100644 scripts/developer/utilities/lib/prop/Global.qml delete mode 100644 scripts/developer/utilities/lib/prop/PropLabel.qml delete mode 100644 scripts/developer/utilities/lib/prop/PropSplitter.qml delete mode 100644 scripts/developer/utilities/lib/prop/PropText.qml diff --git a/scripts/developer/utilities/lib/prop/Global.qml b/scripts/developer/utilities/lib/prop/Global.qml deleted file mode 100644 index be189e3c96..0000000000 --- a/scripts/developer/utilities/lib/prop/Global.qml +++ /dev/null @@ -1,44 +0,0 @@ -// -// Prop/Global.qml -// -// Created by Sam Gateau on 3/2/2019 -// Copyright 2019 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.7 - -import stylesUit 1.0 -import controlsUit 1.0 as HifiControls - - -Item { - HifiConstants { id: hifi } - id: root - - property real lineHeight: 32 - property real slimHeight: 24 - - property var color: hifi.colors.baseGray - property var colorBackHighlight: hifi.colors.baseGrayHighlight - property var colorBorderLight: hifi.colors.lightGray - property var colorBorderHighight: hifi.colors.blueHighlight - - property real fontSize: 12 - property var fontFamily: "Raleway" - property var fontWeight: Font.DemiBold - property var fontColor: hifi.colors.faintGray - - property var splitterRightWidthScale: 0.44 - property real splitterWidth: 4 - - property var labelTextAlign: Text.AlignRight - property var labelTextElide: Text.ElideMiddle - - property var valueAreaWidthScale: 0.3 * (1.0 - splitterRightWidthScale) - property var valueTextAlign: Text.AlignHCenter - property real valueBorderWidth: 1 - property real valueBorderRadius: 2 -} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/prop/PropBool.qml b/scripts/developer/utilities/lib/prop/PropBool.qml index e355398375..d8e4bad589 100644 --- a/scripts/developer/utilities/lib/prop/PropBool.qml +++ b/scripts/developer/utilities/lib/prop/PropBool.qml @@ -29,7 +29,6 @@ PropItem { width: root.width * global.valueAreaWidthScale height: global.slimHeight - checked: root.valueVar onCheckedChanged: { root.valueVarSetter(checked); } } } \ No newline at end of file diff --git a/scripts/developer/utilities/lib/prop/PropEnum.qml b/scripts/developer/utilities/lib/prop/PropEnum.qml index fe6200d971..9446a267b3 100644 --- a/scripts/developer/utilities/lib/prop/PropEnum.qml +++ b/scripts/developer/utilities/lib/prop/PropEnum.qml @@ -18,7 +18,11 @@ PropItem { property alias valueVar : valueCombo.currentIndex property alias enums : valueCombo.model - ComboBox { + Component.onCompleted: { + valueVar = root.valueVarGetter(); + } + + PropComboBox { id: valueCombo flat: true @@ -28,83 +32,6 @@ PropItem { anchors.verticalCenter: root.verticalCenter height: global.slimHeight - currentIndex: root.valueVarGetter() onCurrentIndexChanged: { root.valueVarSetter(currentIndex); } - - delegate: ItemDelegate { - width: valueCombo.width - height: valueCombo.height - contentItem: PropText { - text: modelData - horizontalAlignment: global.valueTextAlign - } - background: Rectangle { - color:highlighted?global.colorBackHighlight:global.color; - } - highlighted: valueCombo.highlightedIndex === index - } - - indicator: Canvas { - id: canvas - x: valueCombo.width - width - valueCombo.rightPadding - y: valueCombo.topPadding + (valueCombo.availableHeight - height) / 2 - width: 12 - height: 8 - contextType: "2d" - - Connections { - target: valueCombo - onPressedChanged: canvas.requestPaint() - } - - onPaint: { - context.reset(); - context.moveTo(0, 0); - context.lineTo(width, 0); - context.lineTo(width / 2, height); - context.closePath(); - context.fillStyle = (valueCombo.pressed) ? global.colorBorderHighight : global.colorBorderLight; - context.fill(); - } - } - - contentItem: PropText { - leftPadding: 0 - rightPadding: valueCombo.indicator.width + valueCombo.spacing - - text: valueCombo.displayText - horizontalAlignment: global.valueTextAlign - } - - background: Rectangle { - implicitWidth: 120 - implicitHeight: 40 - color: global.color - border.color: valueCombo.popup.visible ? global.colorBorderHighight : global.colorBorderLight - border.width: global.valueBorderWidth - radius: global.valueBorderRadius - } - - popup: Popup { - y: valueCombo.height - 1 - width: valueCombo.width - implicitHeight: contentItem.implicitHeight + 2 - padding: 1 - - contentItem: ListView { - clip: true - implicitHeight: contentHeight - model: valueCombo.popup.visible ? valueCombo.delegateModel : null - currentIndex: valueCombo.highlightedIndex - - ScrollIndicator.vertical: ScrollIndicator { } - } - - background: Rectangle { - color: global.color - border.color: global.colorBorderHighight - radius: global.valueBorderRadius - } - } } } diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 39294743b6..dd579af7eb 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -25,6 +25,19 @@ Item { property var label: "group" + /* Component.onCompleted: { + var component1 = Qt.createComponent("PropBool.qml"); + component1.label = "Test"; + for (var i=0; i Date: Tue, 5 Mar 2019 14:27:32 -0800 Subject: [PATCH 12/74] Dynamic creation of the propItem in the propGRoup! --- .../developer/utilities/lib/prop/PropEnum.qml | 3 +- .../utilities/lib/prop/PropGroup.qml | 62 ++++++++++++------- scripts/developer/utilities/render/luci.qml | 12 +++- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/scripts/developer/utilities/lib/prop/PropEnum.qml b/scripts/developer/utilities/lib/prop/PropEnum.qml index 9446a267b3..ff5dfd8161 100644 --- a/scripts/developer/utilities/lib/prop/PropEnum.qml +++ b/scripts/developer/utilities/lib/prop/PropEnum.qml @@ -19,7 +19,7 @@ PropItem { property alias enums : valueCombo.model Component.onCompleted: { - valueVar = root.valueVarGetter(); + // valueVar = root.valueVarGetter(); } PropComboBox { @@ -32,6 +32,7 @@ PropItem { anchors.verticalCenter: root.verticalCenter height: global.slimHeight + currentIndex: root.valueVarGetter() onCurrentIndexChanged: { root.valueVarSetter(currentIndex); } } } diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index dd579af7eb..1dfb957536 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -17,7 +17,7 @@ Item { // Prop Group is designed to author an array of ProItems, they are defined with an array of the tuplets describing each individual item: // [ ..., PropItemInfo, ...] // PropItemInfo { - // "type": "PropXXXX", "object": object, "property": "propName" + // type: "PropXXXX", object: JSobject, property: "propName" // } // property var propItems: [] @@ -25,18 +25,6 @@ Item { property var label: "group" - /* Component.onCompleted: { - var component1 = Qt.createComponent("PropBool.qml"); - component1.label = "Test"; - for (var i=0; i Date: Tue, 5 Mar 2019 20:22:19 -0800 Subject: [PATCH 13/74] This is working !!!! --- .../utilities/lib/jet/qml/TaskPropView.qml | 40 +++++++++++++++++++ .../developer/utilities/lib/jet/qml/qmldir | 1 + .../utilities/lib/prop/PropGroup.qml | 7 +++- scripts/developer/utilities/render/luci.qml | 11 ++++- 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 scripts/developer/utilities/lib/jet/qml/TaskPropView.qml diff --git a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml new file mode 100644 index 0000000000..350103021a --- /dev/null +++ b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml @@ -0,0 +1,40 @@ +// +// jet/TaskListView.qml +// +// Created by Sam Gateau, 2018/05/09 +// 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 +// + +import QtQuick 2.7 +import QtQuick.Controls 1.4 as Original +import QtQuick.Controls.Styles 1.4 + +import stylesUit 1.0 +import controlsUit 1.0 as HifiControls + +import "../../prop" as Prop + +import "../jet.js" as Jet + +Prop.PropGroup { + + id: root; + + property var rootConfig : Render + property var jobPath: "" + property alias jobName: root.label + + Component.onCompleted: { + var props = Jet.job_propKeys(rootConfig.getConfig(jobPath)); + //console.log(JSON.stringify(props)); + for (var p in props) { + root.propItems.push({"type": "PropBool", "object": rootConfig.getConfig(jobPath), "property":props[p] }) + } + root.updatePropItems(); + } + + +} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/jet/qml/qmldir b/scripts/developer/utilities/lib/jet/qml/qmldir index e16820914b..2914c27c23 100644 --- a/scripts/developer/utilities/lib/jet/qml/qmldir +++ b/scripts/developer/utilities/lib/jet/qml/qmldir @@ -1,3 +1,4 @@ TaskList 1.0 TaskList.qml TaskViewList 1.0 TaskViewList.qml TaskTimeFrameView 1.0 TaskTimeFrameView.qml +TaskPropView 1.0 TaskPropView.qml \ No newline at end of file diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 1dfb957536..6f5607def4 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -42,8 +42,8 @@ Item { } height: column.height - Component.onCompleted: { - for (var i = 0; i < root.propItems.length; i++) { + function updatePropItems() { + for (var i = 0; i < root.propItems.length; i++) { var proItem = root.propItems[i]; switch(proItem.type) { case 'PropBool': { @@ -77,4 +77,7 @@ Item { } } } + Component.onCompleted: { + updatePropItems(); + } } diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index d009d52f55..d5156c3cf7 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -14,6 +14,7 @@ import QtQuick.Layouts 1.3 import controlsUit 1.0 as HifiControls import "../lib/prop" as Prop +import "../lib/jet/qml" as Jet Rectangle { Prop.Global { id: prop;} @@ -62,7 +63,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right }*/ - Prop.PropGroup { + /* Prop.PropGroup { label: "My group" propItems: [ {"type": "PropBool", "object": render.mainViewTask.getConfig("LightingModel"), "property": "enableBackground"}, @@ -75,6 +76,14 @@ Rectangle { "Filmic", ]}, ] + anchors.left: parent.left + anchors.right: parent.right + }*/ + + Jet.TaskPropView { + jobPath: "RenderMainView.LightingModel" + label: "Le tone mapping Job" + anchors.left: parent.left anchors.right: parent.right } From f7896b64079b90bfed7a9474f8260307053a7f92 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 6 Mar 2019 22:24:43 -0800 Subject: [PATCH 14/74] Better propGroup --- .../utilities/lib/jet/qml/TaskPropView.qml | 6 +- .../utilities/lib/prop/PropGroup.qml | 126 ++++++++++++------ scripts/developer/utilities/render/luci.qml | 11 +- 3 files changed, 98 insertions(+), 45 deletions(-) diff --git a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml index 350103021a..2188df7cc0 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml @@ -25,13 +25,13 @@ Prop.PropGroup { property var rootConfig : Render property var jobPath: "" - property alias jobName: root.label + property alias label: root.label Component.onCompleted: { var props = Jet.job_propKeys(rootConfig.getConfig(jobPath)); - //console.log(JSON.stringify(props)); + console.log(JSON.stringify(props)); for (var p in props) { - root.propItems.push({"type": "PropBool", "object": rootConfig.getConfig(jobPath), "property":props[p] }) + root.propItems.push({"object": rootConfig.getConfig(jobPath), "property":props[p] }) } root.updatePropItems(); } diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 6f5607def4..7b901b079d 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -25,56 +25,102 @@ Item { property var label: "group" - - Column { - id: column - anchors.left: parent.left - anchors.right: parent.right + Item { + id: header + height: global.slimHeight + anchors.left: parent.left + anchors.right: parent.right PropLabel { - anchors.left: parent.left - anchors.right: parent.right + id: labelControl + anchors.left: header.left + width: 0.8 * header.width + anchors.verticalCenter: header.verticalCenter text: root.label horizontalAlignment: Text.AlignHCenter } - - + Rectangle { + id: headerRect + color: global.color + border.color: global.colorBorderLight + border.width: global.valueBorderWidth + radius: global.valueBorderRadius + + anchors.left: labelControl.right + anchors.right: header.right + anchors.verticalCenter: header.verticalCenter + height: parent.height + } } - height: column.height + + Column { + id: column + anchors.top: header.bottom + anchors.left: parent.left + anchors.right: parent.right + clip: true + + // Where the propItems are added + } + height: header.height + column.height function updatePropItems() { for (var i = 0; i < root.propItems.length; i++) { var proItem = root.propItems[i]; - switch(proItem.type) { - case 'PropBool': { - var component = Qt.createComponent("PropBool.qml"); - component.createObject(column, { - "label": proItem.property, - "object": proItem.object, - "property": proItem.property - }) - } break; - case 'PropScalar': { - var component = Qt.createComponent("PropScalar.qml"); - component.createObject(column, { - "label": proItem.property, - "object": proItem.object, - "property": proItem.property, - "min": (proItem["min"] !== undefined ? proItem.min : 0.0), - "max": (proItem["max"] !== undefined ? proItem.max : 1.0), - "integer": (proItem["integral"] !== undefined ? proItem.integral : false), - }) - } break; - case 'PropEnum': { - var component = Qt.createComponent("PropEnum.qml"); - component.createObject(column, { - "label": proItem.property, - "object": proItem.object, - "property": proItem.property, - "enums": (proItem["enums"] !== undefined ? proItem.enums : ["Undefined Enums !!!"]), - }) - } break; - } + // valid object + if (proItem['object'] !== undefined && proItem['object'] !== null ) { + // valid property + if (proItem['property'] !== undefined && proItem.object[proItem.property] !== undefined) { + // check type + if (proItem['type'] === undefined) { + proItem['type'] = typeof(proItem.object[proItem.property]) + } + switch(proItem.type) { + case 'boolean': + case 'PropBool': { + var component = Qt.createComponent("PropBool.qml"); + component.createObject(column, { + "label": proItem.property, + "object": proItem.object, + "property": proItem.property + }) + } break; + case 'number': + case 'PropScalar': { + var component = Qt.createComponent("PropScalar.qml"); + component.createObject(column, { + "label": proItem.property, + "object": proItem.object, + "property": proItem.property, + "min": (proItem["min"] !== undefined ? proItem.min : 0.0), + "max": (proItem["max"] !== undefined ? proItem.max : 1.0), + "integer": (proItem["integral"] !== undefined ? proItem.integral : false), + }) + } break; + case 'PropEnum': { + var component = Qt.createComponent("PropEnum.qml"); + component.createObject(column, { + "label": proItem.property, + "object": proItem.object, + "property": proItem.property, + "enums": (proItem["enums"] !== undefined ? proItem.enums : ["Undefined Enums !!!"]), + }) + } break; + case 'object': { + var component = Qt.createComponent("PropItem.qml"); + component.createObject(column, { + "label": proItem.property, + "object": proItem.object, + "property": proItem.property, + }) + } break; + } + } else { + console.log('Invalid property: ' + JSON.stringify(proItem)); + } + } else { + console.log('Invalid object: ' + JSON.stringify(proItem)); + } } } Component.onCompleted: { diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index d5156c3cf7..091a287e02 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -81,8 +81,15 @@ Rectangle { }*/ Jet.TaskPropView { - jobPath: "RenderMainView.LightingModel" - label: "Le tone mapping Job" + jobPath: "RenderMainView.ToneMapping" + label: "Le ToneMapping Job" + + anchors.left: parent.left + anchors.right: parent.right + } + Jet.TaskPropView { + jobPath: "RenderMainView.Antialiasing" + label: "Le Antialiasing Job" anchors.left: parent.left anchors.right: parent.right From 5b8116bec4046af2ed36e9b3a1749c0dbbd2a047 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 7 Mar 2019 17:52:11 -0800 Subject: [PATCH 15/74] make the group foldable --- scripts/developer/utilities/lib/prop/PropGroup.qml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 7b901b079d..0b8d5621f4 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -25,6 +25,8 @@ Item { property var label: "group" + property var isUnfold: false + Item { id: header height: global.slimHeight @@ -39,6 +41,7 @@ Item { text: root.label horizontalAlignment: Text.AlignHCenter } + Rectangle { id: headerRect color: global.color @@ -50,11 +53,20 @@ Item { anchors.right: header.right anchors.verticalCenter: header.verticalCenter height: parent.height + + MouseArea{ + id: mousearea + anchors.fill: parent + onDoubleClicked: { + root.isUnfold = !root.isUnfold + } + } } } Column { id: column + visible: root.isUnfold anchors.top: header.bottom anchors.left: parent.left anchors.right: parent.right @@ -62,7 +74,7 @@ Item { // Where the propItems are added } - height: header.height + column.height + height: header.height + isUnfold * column.height function updatePropItems() { for (var i = 0; i < root.propItems.length; i++) { From a303f803ebe1933805fac15e986dd5d23042e887 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 8 Mar 2019 18:14:38 -0800 Subject: [PATCH 16/74] BReaking group --- scripts/developer/utilities/lib/prop/PropGroup.qml | 4 ++-- scripts/developer/utilities/render/luci.qml | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 0b8d5621f4..eaba9d299f 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -36,7 +36,7 @@ Item { PropLabel { id: labelControl anchors.left: header.left - width: 0.8 * header.width + width: 0.9 * header.width anchors.verticalCenter: header.verticalCenter text: root.label horizontalAlignment: Text.AlignHCenter @@ -57,7 +57,7 @@ Item { MouseArea{ id: mousearea anchors.fill: parent - onDoubleClicked: { + onClicked: { root.isUnfold = !root.isUnfold } } diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index 091a287e02..3f6b5b5c01 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -16,14 +16,17 @@ import controlsUit 1.0 as HifiControls import "../lib/prop" as Prop import "../lib/jet/qml" as Jet -Rectangle { + Original.ScrollView { Prop.Global { id: prop;} id: render; - anchors.fill: parent - color: prop.color; + anchors.fill: parent + + // color: prop.color; + + property var mainViewTask: Render.getConfig("RenderMainView") - + Column { anchors.left: parent.left anchors.right: parent.right From 530b871eef09bc74257cbaf9772cf7e60dfee1ea Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 11 Mar 2019 00:08:31 -0700 Subject: [PATCH 17/74] Getting the group styled and scrollview working all together --- .../developer/utilities/lib/prop/PropEnum.qml | 2 +- .../utilities/lib/prop/PropGroup.qml | 93 +++++++++------ .../utilities/lib/prop/PropScalar.qml | 1 - scripts/developer/utilities/lib/prop/qmldir | 1 + .../utilities/lib/prop/style/Global.qml | 5 +- .../utilities/lib/prop/style/PiCanvasIcon.qml | 50 ++++++++ .../utilities/lib/prop/style/PiComboBox.qml | 22 +--- scripts/developer/utilities/render/luci.qml | 112 ++++++------------ 8 files changed, 159 insertions(+), 127 deletions(-) create mode 100644 scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml diff --git a/scripts/developer/utilities/lib/prop/PropEnum.qml b/scripts/developer/utilities/lib/prop/PropEnum.qml index ff5dfd8161..87c2845c90 100644 --- a/scripts/developer/utilities/lib/prop/PropEnum.qml +++ b/scripts/developer/utilities/lib/prop/PropEnum.qml @@ -28,7 +28,7 @@ PropItem { flat: true anchors.left: root.splitter.right - anchors.right: parent.right + anchors.right: root.right anchors.verticalCenter: root.verticalCenter height: global.slimHeight diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index eaba9d299f..4465ec420e 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -25,56 +25,83 @@ Item { property var label: "group" - property var isUnfold: false - + property alias isUnfold: headerRect.icon + Item { id: header height: global.slimHeight anchors.left: parent.left anchors.right: parent.right - + + Item { + id: folder + anchors.left: header.left + width: headerRect.width * 2 + anchors.verticalCenter: header.verticalCenter + height: parent.height + + PropCanvasIcon { + id: headerRect + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + + MouseArea{ + id: mousearea + anchors.fill: parent + onClicked: { + root.isUnfold = !root.isUnfold + } + } + } + } + PropLabel { id: labelControl - anchors.left: header.left - width: 0.9 * header.width + anchors.left: folder.right + anchors.right: header.right anchors.verticalCenter: header.verticalCenter text: root.label horizontalAlignment: Text.AlignHCenter } - Rectangle { - id: headerRect - color: global.color - border.color: global.colorBorderLight - border.width: global.valueBorderWidth - radius: global.valueBorderRadius - - anchors.left: labelControl.right - anchors.right: header.right - anchors.verticalCenter: header.verticalCenter - height: parent.height + /* Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + anchors.bottom: parent.bottom + color: global.colorBorderHighight + + visible: root.isUnfold + }*/ + } - MouseArea{ - id: mousearea - anchors.fill: parent - onClicked: { - root.isUnfold = !root.isUnfold - } - } + Rectangle { + visible: root.isUnfold + + color: "transparent" + border.color: global.colorBorderLight + border.width: global.valueBorderWidth + radius: global.valueBorderRadius + + anchors.left: parent.left + anchors.right: parent.right + anchors.top: header.bottom + anchors.bottom: root.bottom + + Column { + id: column + // anchors.top: header.bottom + anchors.left: parent.left + anchors.right: parent.right + clip: true + + // Where the propItems are added } } - - Column { - id: column - visible: root.isUnfold - anchors.top: header.bottom - anchors.left: parent.left - anchors.right: parent.right - clip: true - // Where the propItems are added - } height: header.height + isUnfold * column.height + anchors.leftMargin: global.horizontalMargin + anchors.rightMargin: global.horizontalMargin function updatePropItems() { for (var i = 0; i < root.propItems.length; i++) { diff --git a/scripts/developer/utilities/lib/prop/PropScalar.qml b/scripts/developer/utilities/lib/prop/PropScalar.qml index 29b42e2801..684dd4fed4 100644 --- a/scripts/developer/utilities/lib/prop/PropScalar.qml +++ b/scripts/developer/utilities/lib/prop/PropScalar.qml @@ -61,7 +61,6 @@ PropItem { stepSize: root.integral ? 1.0 : 0.0 anchors.left: valueLabel.right anchors.right: root.right - anchors.rightMargin: 0 anchors.verticalCenter: root.verticalCenter onValueChanged: { root.valueVarSetter(value) } diff --git a/scripts/developer/utilities/lib/prop/qmldir b/scripts/developer/utilities/lib/prop/qmldir index 3e52395dab..2cd06d58ac 100644 --- a/scripts/developer/utilities/lib/prop/qmldir +++ b/scripts/developer/utilities/lib/prop/qmldir @@ -4,6 +4,7 @@ PropText 1.0 style/PiText.qml PropLabel 1.0 style/PiLabel.qml PropSplitter 1.0 style/PiSplitter.qml PropComboBox 1.0 style/PiComboBox.qml +PropCanvasIcon 1.0 style/PiCanvasIcon.qml PropItem 1.0 PropItem.qml PropScalar 1.0 PropScalar.qml diff --git a/scripts/developer/utilities/lib/prop/style/Global.qml b/scripts/developer/utilities/lib/prop/style/Global.qml index e772477611..6066a4f99b 100644 --- a/scripts/developer/utilities/lib/prop/style/Global.qml +++ b/scripts/developer/utilities/lib/prop/style/Global.qml @@ -21,7 +21,7 @@ Item { property real lineHeight: 32 property real slimHeight: 24 - property real horizontalMargin: 2 + property real horizontalMargin: 4 property var color: hifi.colors.baseGray property var colorBackHighlight: hifi.colors.baseGrayHighlight @@ -35,6 +35,9 @@ Item { property var splitterRightWidthScale: 0.45 property real splitterWidth: 8 + + property real iconWidth: fontSize + property real iconHeight: fontSize property var labelTextAlign: Text.AlignRight property var labelTextElide: Text.ElideMiddle diff --git a/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml b/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml new file mode 100644 index 0000000000..6a805ea4c6 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml @@ -0,0 +1,50 @@ +// +// Prop/style/PiFoldCanvas.qml +// +// Created by Sam Gateau on 3/9/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + + import QtQuick 2.7 +import QtQuick.Controls 2.2 + +Canvas { + Global { id: global } + + width: global.iconWidth + height: global.iconHeight + + property var icon: 0 + onIconChanged: function () { requestPaint() } + property var fillColor: global.colorBorderHighight + + contextType: "2d" + onPaint: { + context.reset(); + switch (icon) { + case 0: + case 1: + case 2: + default: { + if ((icon % 3) == 0) { + context.moveTo(width * 0.25, 0); + context.lineTo(width * 0.25, height); + context.lineTo(width, height / 2); + } else if ((icon % 3) == 1) { + context.moveTo(0, height * 0.25); + context.lineTo(width, height * 0.25); + context.lineTo(width / 2, height); + } else { + context.moveTo(0, height * 0.75); + context.lineTo(width, height* 0.75); + context.lineTo(width / 2, 0); + } + context.closePath(); + context.fillStyle = fillColor; + context.fill(); + }} + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/prop/style/PiComboBox.qml b/scripts/developer/utilities/lib/prop/style/PiComboBox.qml index 9d002ed2b9..d9e029b702 100644 --- a/scripts/developer/utilities/lib/prop/style/PiComboBox.qml +++ b/scripts/developer/utilities/lib/prop/style/PiComboBox.qml @@ -33,28 +33,16 @@ ComboBox { highlighted: valueCombo.highlightedIndex === index } - indicator: Canvas { + indicator: PiCanvasIcon { id: canvas x: valueCombo.width - width - valueCombo.rightPadding y: valueCombo.topPadding + (valueCombo.availableHeight - height) / 2 - width: 12 - height: 8 - contextType: "2d" - Connections { + icon: 1 + /*Connections { target: valueCombo - onPressedChanged: canvas.requestPaint() - } - - onPaint: { - context.reset(); - context.moveTo(0, 0); - context.lineTo(width, 0); - context.lineTo(width / 2, height); - context.closePath(); - context.fillStyle = (valueCombo.pressed) ? global.colorBorderHighight : global.colorBorderLight; - context.fill(); - } + onPressedChanged: { canvas.icon = control.down + 1 } + }*/ } contentItem: PiText { diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index 3f6b5b5c01..89794b037e 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html // import QtQuick 2.7 -import QtQuick.Controls 1.4 +import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import controlsUit 1.0 as HifiControls @@ -16,86 +16,50 @@ import controlsUit 1.0 as HifiControls import "../lib/prop" as Prop import "../lib/jet/qml" as Jet - Original.ScrollView { - Prop.Global { id: prop;} - id: render; +Rectangle { anchors.fill: parent - - // color: prop.color; - - - + id: render; property var mainViewTask: Render.getConfig("RenderMainView") - Column { - anchors.left: parent.left - anchors.right: parent.right - /* Repeater { - model: [ "Tone mapping exposure:ToneMapping:exposure:5.0:-5.0", - "Tone:ToneMapping:exposure:5.0:-5.0" + Prop.Global { id: global;} + color: global.color + + ScrollView { + id: control + anchors.fill: parent + clip: true + + Column { + width: render.width + + Prop.PropEnum { + label: "Tone Curve" + object: render.mainViewTask.getConfig("ToneMapping") + property: "curve" + enums: [ + "RGB", + "SRGB", + "Reinhard", + "Filmic", ] - Prop.PropScalar { - label: qsTr(modelData.split(":")[0]) - integral: false - object: render.mainViewTask.getConfig(modelData.split(":")[1]) - property: modelData.split(":")[2] - max: modelData.split(":")[3] - min: modelData.split(":")[4] + anchors.left: parent.left + anchors.right: parent.right + } + + Jet.TaskPropView { + jobPath: "RenderMainView.ToneMapping" + label: "Le ToneMapping Job" - anchors.left: parent.left - anchors.right: parent.right + anchors.left: parent.left + anchors.right: parent.right } - } - Prop.PropEnum { - label: "Tone Curve" - object: render.mainViewTask.getConfig("ToneMapping") - property: "curve" - enums: [ - "RGB", - "SRGB", - "Reinhard", - "Filmic", - ] - anchors.left: parent.left - anchors.right: parent.right - } - Prop.PropBool { - label: "Background" - object: render.mainViewTask.getConfig("LightingModel") - property: "enableBackground" - anchors.left: parent.left - anchors.right: parent.right - }*/ - /* Prop.PropGroup { - label: "My group" - propItems: [ - {"type": "PropBool", "object": render.mainViewTask.getConfig("LightingModel"), "property": "enableBackground"}, - {"type": "PropScalar", "object": render.mainViewTask.getConfig("ToneMapping"), "property": "exposure"}, - {"type": "PropBool", "object": render.mainViewTask.getConfig("LightingModel"), "property": "enableEmissive"}, - {"type": "PropEnum", "object": render.mainViewTask.getConfig("ToneMapping"), "property": "curve", enums: [ - "RGB", - "SRGB", - "Reinhard", - "Filmic", - ]}, - ] - anchors.left: parent.left - anchors.right: parent.right - }*/ + Jet.TaskPropView { + jobPath: "RenderMainView.Antialiasing" + label: "Le Antialiasing Job" - Jet.TaskPropView { - jobPath: "RenderMainView.ToneMapping" - label: "Le ToneMapping Job" - - anchors.left: parent.left - anchors.right: parent.right - } - Jet.TaskPropView { - jobPath: "RenderMainView.Antialiasing" - label: "Le Antialiasing Job" - - anchors.left: parent.left - anchors.right: parent.right + anchors.left: parent.left + anchors.right: parent.right + } } } } \ No newline at end of file From f2fc9c010219dd97f62e6517bf48f9b60c05f019 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 12 Mar 2019 16:40:28 -0700 Subject: [PATCH 18/74] Multiple task view --- scripts/developer/utilities/lib/jet/jet.js | 10 +++- .../utilities/lib/jet/qml/TaskPropView.qml | 32 ++++++++++-- .../utilities/lib/prop/PropGroup.qml | 51 +++++++++++-------- .../developer/utilities/lib/prop/PropItem.qml | 2 +- scripts/developer/utilities/render/luci.qml | 18 +++++-- 5 files changed, 83 insertions(+), 30 deletions(-) diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index 40563e4b2c..52c13c5279 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -10,7 +10,12 @@ // "use strict"; - // traverse task tree + // traverse task tree recursively + // + // @param root: the root job config from where to traverse + // @param functor: the functor function() which is applied on every subjobs of root traversed + // if return true, then 'task_tree' is called recursively on that subjob + // @param depth: the depth of the recurse loop since the initial call. function task_traverse(root, functor, depth) { if (root.isTask()) { depth++; @@ -22,6 +27,9 @@ function task_traverse(root, functor, depth) { } } } + +// same function as 'task_traverse' with the depth being 0 +// and visisting the root job first. function task_traverseTree(root, functor) { if (functor(root, 0, 0)) { task_traverse(root, functor, 0) diff --git a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml index 2188df7cc0..af4cbb1c9a 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml @@ -1,5 +1,5 @@ // -// jet/TaskListView.qml +// jet/TaskPropView.qml // // Created by Sam Gateau, 2018/05/09 // Copyright 2018 High Fidelity, Inc. @@ -27,13 +27,37 @@ Prop.PropGroup { property var jobPath: "" property alias label: root.label - Component.onCompleted: { + function populatePropItems() { + var propsModel = [] var props = Jet.job_propKeys(rootConfig.getConfig(jobPath)); console.log(JSON.stringify(props)); for (var p in props) { - root.propItems.push({"object": rootConfig.getConfig(jobPath), "property":props[p] }) + propsModel.push({"object": rootConfig.getConfig(jobPath), "property":props[p] }) } - root.updatePropItems(); + root.updatePropItems(propsModel); + + + Jet.task_traverse(rootConfig.getConfig(jobPath), + function(job, depth, index) { + var component = Qt.createComponent("./TaskPropView.qml"); + component.createObject(root.propItemsPanel, { + "label": job.objectName, + "rootConfig": root.rootConfig, + "jobPath": root.jobPath + '.' + job.objectName + }) + /* var component = Qt.createComponent("../../prop/PropItem.qml"); + component.createObject(root.propItemsPanel, { + "label": root.jobPath + '.' + job.objectName + ' num=' + index, + })*/ + // propsModel.push({"type": "printLabel", "label": root.jobPath + '.' + job.objectName + ' num=' + index }) + + return (depth < 1); + }, 0) + + } + + Component.onCompleted: { + populatePropItems() } diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 4465ec420e..544a687f70 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -13,20 +13,12 @@ import QtQuick 2.7 Item { Global { id: global } id: root - - // Prop Group is designed to author an array of ProItems, they are defined with an array of the tuplets describing each individual item: - // [ ..., PropItemInfo, ...] - // PropItemInfo { - // type: "PropXXXX", object: JSobject, property: "propName" - // } - // - property var propItems: [] - property var label: "group" property alias isUnfold: headerRect.icon - + property alias propItemsPanel: propItemsContainer + Item { id: header height: global.slimHeight @@ -89,7 +81,7 @@ Item { anchors.bottom: root.bottom Column { - id: column + id: propItemsContainer // anchors.top: header.bottom anchors.left: parent.left anchors.right: parent.right @@ -99,13 +91,22 @@ Item { } } - height: header.height + isUnfold * column.height + height: header.height + isUnfold * propItemsContainer.height anchors.leftMargin: global.horizontalMargin anchors.rightMargin: global.horizontalMargin + anchors.left: parent.left + anchors.right: parent.right - function updatePropItems() { - for (var i = 0; i < root.propItems.length; i++) { - var proItem = root.propItems[i]; + + // Prop Group is designed to author an array of ProItems, they are defined with an array of the tuplets describing each individual item: + // [ ..., PropItemInfo, ...] + // PropItemInfo { + // type: "PropXXXX", object: JSobject, property: "propName" + // } + // + function updatePropItems(propItemsModel) { + for (var i = 0; i < propItemsModel.length; i++) { + var proItem = propItemsModel[i]; // valid object if (proItem['object'] !== undefined && proItem['object'] !== null ) { // valid property @@ -118,7 +119,7 @@ Item { case 'boolean': case 'PropBool': { var component = Qt.createComponent("PropBool.qml"); - component.createObject(column, { + component.createObject(propItemsContainer, { "label": proItem.property, "object": proItem.object, "property": proItem.property @@ -127,7 +128,7 @@ Item { case 'number': case 'PropScalar': { var component = Qt.createComponent("PropScalar.qml"); - component.createObject(column, { + component.createObject(propItemsContainer, { "label": proItem.property, "object": proItem.object, "property": proItem.property, @@ -138,7 +139,7 @@ Item { } break; case 'PropEnum': { var component = Qt.createComponent("PropEnum.qml"); - component.createObject(column, { + component.createObject(propItemsContainer, { "label": proItem.property, "object": proItem.object, "property": proItem.property, @@ -147,22 +148,32 @@ Item { } break; case 'object': { var component = Qt.createComponent("PropItem.qml"); - component.createObject(column, { + component.createObject(propItemsContainer, { "label": proItem.property, "object": proItem.object, "property": proItem.property, }) } break; + case 'printLabel': { + var component = Qt.createComponent("PropItem.qml"); + component.createObject(propItemsContainer, { + "label": proItem.property + }) + } break; } } else { console.log('Invalid property: ' + JSON.stringify(proItem)); } + } else if (proItem['type'] === 'printLabel') { + var component = Qt.createComponent("PropItem.qml"); + component.createObject(propItemsContainer, { + "label": proItem.label + }) } else { console.log('Invalid object: ' + JSON.stringify(proItem)); } } } Component.onCompleted: { - updatePropItems(); } } diff --git a/scripts/developer/utilities/lib/prop/PropItem.qml b/scripts/developer/utilities/lib/prop/PropItem.qml index 00314512f2..339ff10422 100644 --- a/scripts/developer/utilities/lib/prop/PropItem.qml +++ b/scripts/developer/utilities/lib/prop/PropItem.qml @@ -16,7 +16,7 @@ Item { id: root // Prop item is designed to author an object[property]: - property var object: NULL + property var object: {} property string property: "" // value is accessed through the "valueVarSetter" and "valueVarGetter" diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index 89794b037e..85ca69e998 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -32,7 +32,7 @@ Rectangle { Column { width: render.width - Prop.PropEnum { + /* Prop.PropEnum { label: "Tone Curve" object: render.mainViewTask.getConfig("ToneMapping") property: "curve" @@ -44,9 +44,16 @@ Rectangle { ] anchors.left: parent.left anchors.right: parent.right - } - + } */ Jet.TaskPropView { + id: "the" + jobPath: "RenderMainView.RenderDeferredTask" + label: "Le Render Deferred Job" + + anchors.left: parent.left + anchors.right: parent.right + } + /* Jet.TaskPropView { jobPath: "RenderMainView.ToneMapping" label: "Le ToneMapping Job" @@ -59,7 +66,10 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right - } + }*/ } } + + Component.onCompleted: { + } } \ No newline at end of file From 9581f5c958c17b830b617f87c0953ed7bb7b4e50 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 5 Apr 2019 08:44:49 -0700 Subject: [PATCH 19/74] separating the group header container --- .../utilities/lib/prop/PropGroup.qml | 43 +++++++++++-------- scripts/developer/utilities/render/luci.qml | 16 +++++++ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 544a687f70..f4b1ba02d6 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -16,24 +16,27 @@ Item { property var label: "group" - property alias isUnfold: headerRect.icon + property alias isUnfold: headerFolderIcon.icon property alias propItemsPanel: propItemsContainer + property alias headerContainer: headerContainer + // Header Item Item { id: header height: global.slimHeight anchors.left: parent.left anchors.right: parent.right + // First in the header, the folder button / indicator Item { - id: folder + id: headerFolder anchors.left: header.left - width: headerRect.width * 2 + width: headerFolderIcon.width * 2 anchors.verticalCenter: header.verticalCenter height: parent.height PropCanvasIcon { - id: headerRect + id: headerFolderIcon anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter @@ -47,26 +50,28 @@ Item { } } - PropLabel { - id: labelControl - anchors.left: folder.right + // Next the header container + // by default containing a Label showing the root.label + Item { + id: headerContainer + anchors.left: headerFolder.right anchors.right: header.right anchors.verticalCenter: header.verticalCenter - text: root.label - horizontalAlignment: Text.AlignHCenter - } + height: parent.height - /* Rectangle { - anchors.left: parent.left - anchors.right: parent.right - height: 1 - anchors.bottom: parent.bottom - color: global.colorBorderHighight - - visible: root.isUnfold - }*/ + PropLabel { + id: labelControl + anchors.left: headerContainer.left + anchors.right: headerContainer.right + anchors.verticalCenter: headerContainer.verticalCenter + text: root.label + horizontalAlignment: Text.AlignHCenter + } + + } } + // The Panel container Rectangle { visible: root.isUnfold diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index 85ca69e998..8c68d654a1 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -45,6 +45,22 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right } */ + Jet.TaskPropView { + id: "lightingModel" + jobPath: "RenderMainView.LightingModel" + label: "Le LightingModel" + + anchors.left: parent.left + anchors.right: parent.right + } + Jet.TaskPropView { + id: "theView" + jobPath: "RenderMainView" + label: "Le Render Main View" + + anchors.left: parent.left + anchors.right: parent.right + } Jet.TaskPropView { id: "the" jobPath: "RenderMainView.RenderDeferredTask" From c730e51d1e7d37271a6c7b948f6d62806de6a3a0 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 11 Apr 2019 13:22:51 -0700 Subject: [PATCH 20/74] wip redo stencil work --- cmake/externals/LibOVR/CMakeLists.txt | 4 +- interface/src/Application.cpp | 24 +++++-- interface/src/Application.h | 6 ++ interface/src/SecondaryCamera.cpp | 11 +-- interface/src/graphics/GraphicsEngine.cpp | 4 ++ interface/src/ui/SnapshotAnimated.cpp | 67 ++++++++++--------- .../display-plugins/OpenGLDisplayPlugin.cpp | 9 +++ .../display-plugins/hmd/HmdDisplayPlugin.h | 2 + libraries/gpu/src/gpu/Frame.h | 3 + libraries/plugins/src/plugins/DisplayPlugin.h | 5 ++ .../render-utils/src/StencilMaskPass.cpp | 42 +++++++----- libraries/render-utils/src/StencilMaskPass.h | 13 ++-- libraries/render/src/render/Args.h | 5 ++ libraries/shared/src/RegisteredMetaTypes.cpp | 11 +++ libraries/shared/src/RegisteredMetaTypes.h | 4 ++ libraries/shared/src/StencilMaskMode.h | 18 +++++ plugins/oculus/CMakeLists.txt | 2 +- .../oculus/src/OculusBaseDisplayPlugin.cpp | 63 +++++++++++++++++ plugins/oculus/src/OculusBaseDisplayPlugin.h | 8 +++ plugins/openvr/src/OpenVrDisplayPlugin.cpp | 45 +++++++++++++ plugins/openvr/src/OpenVrDisplayPlugin.h | 8 +++ 21 files changed, 288 insertions(+), 66 deletions(-) create mode 100644 libraries/shared/src/StencilMaskMode.h diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index ae4cf6320e..481753f7e0 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -17,8 +17,8 @@ if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://public.highfidelity.com/dependencies/ovr_sdk_win_1.26.0_public.zip - URL_MD5 06804ff9727b910dcd04a37c800053b5 + URL https://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.35.0.zip + URL_MD5 1e3e8b2101387af07ff9c841d0ea285e CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" /CMakeLists.txt LOG_DOWNLOAD 1 diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e809120a74..bc0feefb9a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6725,6 +6725,11 @@ void Application::updateRenderArgs(float deltaTime) { } } + appRenderArgs._renderArgs._stencilMaskMode = getActiveDisplayPlugin()->getStencilMaskMode(); + if (appRenderArgs._renderArgs._stencilMaskMode == StencilMaskMode::MESH) { + appRenderArgs._renderArgs._stencilMaskOperator = getActiveDisplayPlugin()->getStencilMaskMeshOperator(); + } + { QMutexLocker viewLocker(&_viewMutex); _myCamera.loadViewFrustum(_displayViewFrustum); @@ -8412,11 +8417,20 @@ void Application::loadAvatarBrowser() const { DependencyManager::get()->openTablet(); } +void Application::addSnapshotOperator(const SnapshotOperator& snapshotOperator) { + std::lock_guard lock(_snapshotMutex); + _snapshotOperators.push(snapshotOperator); +} + +bool Application::takeSnapshotOperators(std::queue& snapshotOperators) { + std::lock_guard lock(_snapshotMutex); + _snapshotOperators.swap(snapshotOperators); + return !snapshotOperators.empty(); +} + void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { - postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] { - // Get a screenshot and save it - QString path = DependencyManager::get()->saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename, - TestScriptingInterface::getInstance()->getTestResultsLocation()); + addSnapshotOperator({ [notify, includeAnimated, aspectRatio, filename](const QImage& snapshot) { + QString path = DependencyManager::get()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); // If we're not doing an animated snapshot as well... if (!includeAnimated) { @@ -8428,7 +8442,7 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa // Get an animated GIF snapshot and save it SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, qApp, DependencyManager::get()); } - }); + }, aspectRatio }); } void Application::takeSecondaryCameraSnapshot(const bool& notify, const QString& filename) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 99e57f1866..b2e59e97d4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -344,6 +344,10 @@ public: void toggleAwayMode(); #endif + using SnapshotOperator = std::pair, float>; + void addSnapshotOperator(const SnapshotOperator& snapshotOperator); + bool takeSnapshotOperators(std::queue& snapshotOperators); + signals: void svoImportRequested(const QString& url); @@ -788,6 +792,8 @@ private: AudioInjectorPointer _snapshotSoundInjector; SharedSoundPointer _snapshotSound; SharedSoundPointer _sampleSound; + std::mutex _snapshotMutex; + std::queue _snapshotOperators; DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin; QString _autoSwitchDisplayModeSupportedHMDPluginName; diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 12c9636746..da2874a3f4 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -152,10 +152,12 @@ public: _cachedArgsPointer->_viewport = args->_viewport; _cachedArgsPointer->_displayMode = args->_displayMode; _cachedArgsPointer->_renderMode = args->_renderMode; + _cachedArgsPointer->_stencilMaskMode = args->_stencilMaskMode; args->_blitFramebuffer = destFramebuffer; args->_viewport = glm::ivec4(0, 0, destFramebuffer->getWidth(), destFramebuffer->getHeight()); args->_displayMode = RenderArgs::MONO; args->_renderMode = RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE; + args->_stencilMaskMode = StencilMaskMode::NONE; gpu::doInBatch("SecondaryCameraJob::run", args->_context, [&](gpu::Batch& batch) { batch.disableContextStereo(); @@ -255,10 +257,11 @@ public: void run(const render::RenderContextPointer& renderContext, const RenderArgsPointer& cachedArgs) { auto args = renderContext->args; if (cachedArgs) { - args->_blitFramebuffer = cachedArgs->_blitFramebuffer; - args->_viewport = cachedArgs->_viewport; - args->_displayMode = cachedArgs->_displayMode; - args->_renderMode = cachedArgs->_renderMode; + args->_blitFramebuffer = cachedArgs->_blitFramebuffer; + args->_viewport = cachedArgs->_viewport; + args->_displayMode = cachedArgs->_displayMode; + args->_renderMode = cachedArgs->_renderMode; + args->_stencilMaskMode = cachedArgs->_stencilMaskMode; } args->popViewFrustum(); diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index c2137d3d97..1842c20e4e 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -244,6 +244,7 @@ void GraphicsEngine::render_performFrame() { finalFramebuffer = framebufferCache->getFramebuffer(); } + std::queue snapshotOperators; if (!_programsCompiled.load()) { gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { batch.setFramebuffer(finalFramebuffer); @@ -271,11 +272,13 @@ void GraphicsEngine::render_performFrame() { PROFILE_RANGE(render, "/runRenderFrame"); renderArgs._hudOperator = displayPlugin->getHUDOperator(); renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture(); + renderArgs._takingSnapshot = qApp->takeSnapshotOperators(snapshotOperators); renderArgs._blitFramebuffer = finalFramebuffer; render_runRenderFrame(&renderArgs); } } + qDebug() << "boop" << renderArgs._takingSnapshot << snapshotOperators.size(); auto frame = getGPUContext()->endFrame(); frame->frameIndex = _renderFrameCount; frame->framebuffer = finalFramebuffer; @@ -285,6 +288,7 @@ void GraphicsEngine::render_performFrame() { frameBufferCache->releaseFramebuffer(framebuffer); } }; + frame->snapshotOperators = snapshotOperators; // deliver final scene rendering commands to the display plugin { PROFILE_RANGE(render, "/pluginOutput"); diff --git a/interface/src/ui/SnapshotAnimated.cpp b/interface/src/ui/SnapshotAnimated.cpp index 9d58d89385..1c5a25b68f 100644 --- a/interface/src/ui/SnapshotAnimated.cpp +++ b/interface/src/ui/SnapshotAnimated.cpp @@ -62,44 +62,45 @@ void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio void SnapshotAnimated::captureFrames() { if (SnapshotAnimated::snapshotAnimatedTimerRunning) { - // Get a screenshot from the display, then scale the screenshot down, - // then convert it to the image format the GIF library needs, - // then save all that to the QImage named "frame" - QImage frame(SnapshotAnimated::app->getActiveDisplayPlugin()->getScreenshot(SnapshotAnimated::aspectRatio)); - frame = frame.scaledToWidth(SNAPSNOT_ANIMATED_WIDTH); - SnapshotAnimated::snapshotAnimatedFrameVector.append(frame); + SnapshotAnimated::app->addSnapshotOperator({ [](const QImage& snapshot) { + // Get a screenshot from the display, then scale the screenshot down, + // then convert it to the image format the GIF library needs, + // then save all that to the QImage named "frame" + QImage frame = snapshot.scaledToWidth(SNAPSNOT_ANIMATED_WIDTH); + SnapshotAnimated::snapshotAnimatedFrameVector.append(frame); - // If that was the first frame... - if (SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp == 0) { - // Record the current frame timestamp - SnapshotAnimated::snapshotAnimatedTimestamp = QDateTime::currentMSecsSinceEpoch(); - // Record the first frame timestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp = SnapshotAnimated::snapshotAnimatedTimestamp; - SnapshotAnimated::snapshotAnimatedFrameDelayVector.append(SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC / 10); - // If this is an intermediate or the final frame... - } else { - // Push the current frame delay onto the vector - SnapshotAnimated::snapshotAnimatedFrameDelayVector.append(round(((float)(QDateTime::currentMSecsSinceEpoch() - SnapshotAnimated::snapshotAnimatedTimestamp)) / 10)); - // Record the current frame timestamp - SnapshotAnimated::snapshotAnimatedTimestamp = QDateTime::currentMSecsSinceEpoch(); + // If that was the first frame... + if (SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp == 0) { + // Record the current frame timestamp + SnapshotAnimated::snapshotAnimatedTimestamp = QDateTime::currentMSecsSinceEpoch(); + // Record the first frame timestamp + SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp = SnapshotAnimated::snapshotAnimatedTimestamp; + SnapshotAnimated::snapshotAnimatedFrameDelayVector.append(SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC / 10); + // If this is an intermediate or the final frame... + } else { + // Push the current frame delay onto the vector + SnapshotAnimated::snapshotAnimatedFrameDelayVector.append(round(((float)(QDateTime::currentMSecsSinceEpoch() - SnapshotAnimated::snapshotAnimatedTimestamp)) / 10)); + // Record the current frame timestamp + SnapshotAnimated::snapshotAnimatedTimestamp = QDateTime::currentMSecsSinceEpoch(); - // If that was the last frame... - if ((SnapshotAnimated::snapshotAnimatedTimestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp) >= (SnapshotAnimated::snapshotAnimatedDuration.get() * MSECS_PER_SECOND)) { - SnapshotAnimated::snapshotAnimatedTimerRunning = false; + // If that was the last frame... + if ((SnapshotAnimated::snapshotAnimatedTimestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp) >= (SnapshotAnimated::snapshotAnimatedDuration.get() * MSECS_PER_SECOND)) { + SnapshotAnimated::snapshotAnimatedTimerRunning = false; - // Notify the user that we're processing the snapshot - // This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called. - emit SnapshotAnimated::snapshotAnimatedDM->processingGifStarted(SnapshotAnimated::snapshotStillPath); + // Notify the user that we're processing the snapshot + // This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called. + emit SnapshotAnimated::snapshotAnimatedDM->processingGifStarted(SnapshotAnimated::snapshotStillPath); - // Kick off the thread that'll pack the frames into the GIF - QtConcurrent::run(processFrames); - // Stop the snapshot QTimer. This action by itself DOES NOT GUARANTEE - // that the slot will not be called again in the future. - // See: http://lists.qt-project.org/pipermail/qt-interest-old/2009-October/013926.html - SnapshotAnimated::snapshotAnimatedTimer->stop(); - delete SnapshotAnimated::snapshotAnimatedTimer; + // Kick off the thread that'll pack the frames into the GIF + QtConcurrent::run(processFrames); + // Stop the snapshot QTimer. This action by itself DOES NOT GUARANTEE + // that the slot will not be called again in the future. + // See: http://lists.qt-project.org/pipermail/qt-interest-old/2009-October/013926.html + SnapshotAnimated::snapshotAnimatedTimer->stop(); + delete SnapshotAnimated::snapshotAnimatedTimer; + } } - } + }, SnapshotAnimated::aspectRatio }); } } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index c536e6b6e2..1700ca9d54 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -723,6 +723,15 @@ void OpenGLDisplayPlugin::present() { compositeLayers(); } + { // 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(); + snapshotOperator.first(getScreenshot(snapshotOperator.second)); + _currentFrame->snapshotOperators.pop(); + } + } + // Take the composite framebuffer and send it to the output device { PROFILE_RANGE_EX(render, "internalPresent", 0xff00ffff, frameId) diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index d8c0ce8e1d..e952b1e8db 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -48,6 +48,8 @@ public: void pluginUpdate() override {}; + virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::PAINT; } + signals: void hmdMountedChanged(); void hmdVisibleChanged(bool visible); diff --git a/libraries/gpu/src/gpu/Frame.h b/libraries/gpu/src/gpu/Frame.h index 3787ebfacd..94c0919fdb 100644 --- a/libraries/gpu/src/gpu/Frame.h +++ b/libraries/gpu/src/gpu/Frame.h @@ -9,6 +9,7 @@ #define hifi_gpu_Frame_h #include +#include #include "Forward.h" #include "Batch.h" @@ -41,6 +42,8 @@ namespace gpu { /// How to process the framebuffer when the frame dies. MUST BE THREAD SAFE FramebufferRecycler framebufferRecycler; + std::queue, float>> snapshotOperators; + protected: friend class Deserializer; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index aa52e57c3f..9db8fc995c 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -27,6 +27,7 @@ #include #include #include "Plugin.h" +#include "StencilMaskMode.h" class QOpenGLFramebufferObject; @@ -221,6 +222,10 @@ public: // for updating plugin-related commands. Mimics the input plugin. virtual void pluginUpdate() = 0; + virtual StencilMaskMode getStencilMaskMode() const { return StencilMaskMode::NONE; } + using StencilMaskMeshOperator = std::function; + virtual StencilMaskMeshOperator getStencilMaskMeshOperator() { return nullptr; } + signals: void recommendedFramebufferSizeChanged(const QSize& size); void resetSensorsRequested(); diff --git a/libraries/render-utils/src/StencilMaskPass.cpp b/libraries/render-utils/src/StencilMaskPass.cpp index 7217a3e5eb..7c89e6b601 100644 --- a/libraries/render-utils/src/StencilMaskPass.cpp +++ b/libraries/render-utils/src/StencilMaskPass.cpp @@ -19,7 +19,6 @@ using namespace render; void PrepareStencil::configure(const Config& config) { _maskMode = config.maskMode; - _forceDraw = config.forceDraw; } graphics::MeshPointer PrepareStencil::getMesh() { @@ -43,6 +42,7 @@ gpu::PipelinePointer PrepareStencil::getMeshStencilPipeline() { auto state = std::make_shared(); drawMask(*state); state->setColorWriteMask(gpu::State::WRITE_NONE); + state->setCullMode(gpu::State::CullMode::CULL_NONE); _meshStencilPipeline = gpu::Pipeline::create(program, state); } @@ -64,8 +64,28 @@ gpu::PipelinePointer PrepareStencil::getPaintStencilPipeline() { void PrepareStencil::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) { RenderArgs* args = renderContext->args; - // Only draw the stencil mask if in HMD mode or not forced. - if (!_forceDraw && (args->_displayMode != RenderArgs::STEREO_HMD)) { + if (args->_takingSnapshot) { + return; + } + + StencilMaskMode maskMode = _maskMode; + std::function maskOperator = [this](gpu::Batch& batch) { + auto mesh = getMesh(); + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputFormat((mesh->getVertexFormat())); + batch.setInputStream(0, mesh->getVertexStream()); + + // Draw + auto part = mesh->getPartBuffer().get(0); + batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex); + }; + + if (maskMode == StencilMaskMode::NONE) { + maskMode = args->_stencilMaskMode; + maskOperator = args->_stencilMaskOperator; + } + + if (maskMode == StencilMaskMode::NONE || (maskMode == StencilMaskMode::MESH && !maskOperator)) { return; } @@ -74,20 +94,12 @@ void PrepareStencil::run(const RenderContextPointer& renderContext, const gpu::F batch.setViewportTransform(args->_viewport); - if (_maskMode < 0) { - batch.setPipeline(getMeshStencilPipeline()); - - auto mesh = getMesh(); - batch.setIndexBuffer(mesh->getIndexBuffer()); - batch.setInputFormat((mesh->getVertexFormat())); - batch.setInputStream(0, mesh->getVertexStream()); - - // Draw - auto part = mesh->getPartBuffer().get(0); - batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex); - } else { + if (maskMode == StencilMaskMode::PAINT) { batch.setPipeline(getPaintStencilPipeline()); batch.draw(gpu::TRIANGLE_STRIP, 4); + } else if (maskMode == StencilMaskMode::MESH) { + batch.setPipeline(getMeshStencilPipeline()); + maskOperator(batch); } }); } diff --git a/libraries/render-utils/src/StencilMaskPass.h b/libraries/render-utils/src/StencilMaskPass.h index a8e4d1e1f2..bca2ef17a5 100644 --- a/libraries/render-utils/src/StencilMaskPass.h +++ b/libraries/render-utils/src/StencilMaskPass.h @@ -15,17 +15,19 @@ #include #include #include +#include class PrepareStencilConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int maskMode MEMBER maskMode NOTIFY dirty) - Q_PROPERTY(bool forceDraw MEMBER forceDraw NOTIFY dirty) + Q_PROPERTY(StencilMaskMode maskMode MEMBER maskMode NOTIFY dirty) public: PrepareStencilConfig(bool enabled = true) : JobConfig(enabled) {} - int maskMode { 0 }; - bool forceDraw { false }; + // -1 -> don't force drawing (fallback to render args mode) + // 0 -> force draw without mesh + // 1 -> force draw with mesh + StencilMaskMode maskMode { StencilMaskMode::NONE }; signals: void dirty(); @@ -66,8 +68,7 @@ private: graphics::MeshPointer _mesh; graphics::MeshPointer getMesh(); - int _maskMode { 0 }; - bool _forceDraw { false }; + StencilMaskMode _maskMode { StencilMaskMode::NONE }; }; diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index b5c98e3428..c4b823256e 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -16,6 +16,7 @@ #include #include +#include #include #include "Forward.h" @@ -133,6 +134,10 @@ namespace render { std::function _hudOperator; gpu::TexturePointer _hudTexture; + + bool _takingSnapshot { false }; + StencilMaskMode _stencilMaskMode { StencilMaskMode::NONE }; + std::function _stencilMaskOperator; }; } diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 597e537d8d..9a35796db8 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -40,6 +40,7 @@ int qMapURLStringMetaTypeId = qRegisterMetaType>(); int socketErrorMetaTypeId = qRegisterMetaType(); int voidLambdaType = qRegisterMetaType>(); int variantLambdaType = qRegisterMetaType>(); +int stencilModeMetaTypeId = qRegisterMetaType(); void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, vec2ToScriptValue, vec2FromScriptValue); @@ -64,6 +65,8 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue); qScriptRegisterMetaType(engine, quuidToScriptValue, quuidFromScriptValue); qScriptRegisterMetaType(engine, aaCubeToScriptValue, aaCubeFromScriptValue); + + qScriptRegisterMetaType(engine, stencilMaskModeToScriptValue, stencilMaskModeFromScriptValue); } QScriptValue vec2ToScriptValue(QScriptEngine* engine, const glm::vec2& vec2) { @@ -1283,4 +1286,12 @@ QVariantMap parseTexturesToMap(QString newTextures, const QVariantMap& defaultTe } return toReturn; +} + +QScriptValue stencilMaskModeToScriptValue(QScriptEngine* engine, const StencilMaskMode& stencilMode) { + return engine->newVariant((int)stencilMode); +} + +void stencilMaskModeFromScriptValue(const QScriptValue& object, StencilMaskMode& stencilMode) { + stencilMode = StencilMaskMode(object.toVariant().toInt()); } \ No newline at end of file diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index ea2c5b8354..e663a9d90f 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -25,6 +25,7 @@ #include "shared/Bilateral.h" #include "Transform.h" #include "PhysicsCollisionGroups.h" +#include "StencilMaskMode.h" class QColor; class QUrl; @@ -729,5 +730,8 @@ void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextures); +Q_DECLARE_METATYPE(StencilMaskMode) +QScriptValue stencilMaskModeToScriptValue(QScriptEngine* engine, const StencilMaskMode& stencilMode); +void stencilMaskModeFromScriptValue(const QScriptValue& object, StencilMaskMode& stencilMode); #endif // hifi_RegisteredMetaTypes_h diff --git a/libraries/shared/src/StencilMaskMode.h b/libraries/shared/src/StencilMaskMode.h new file mode 100644 index 0000000000..98372890ec --- /dev/null +++ b/libraries/shared/src/StencilMaskMode.h @@ -0,0 +1,18 @@ +// +// Created by Sam Gondelman on 3/26/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_StencilMaskMode_h +#define hifi_StencilMaskMode_h + +enum class StencilMaskMode { + NONE = -1, // for legacy reasons, this is -1 + PAINT = 0, + MESH = 1 +}; + +#endif // hifi_StencilMaskMode_h \ No newline at end of file diff --git a/plugins/oculus/CMakeLists.txt b/plugins/oculus/CMakeLists.txt index abce753b4d..6ddc75e1e5 100644 --- a/plugins/oculus/CMakeLists.txt +++ b/plugins/oculus/CMakeLists.txt @@ -18,7 +18,7 @@ if (WIN32 AND (NOT USE_GLES)) link_hifi_libraries( shared task gl shaders gpu ${PLATFORM_GL_BACKEND} controllers ui qml plugins ui-plugins display-plugins input-plugins - audio-client networking render-utils + audio-client networking render-utils graphics ${PLATFORM_GL_BACKEND} ) include_hifi_library_headers(octree) diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index a67e3127e5..db26537a19 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -227,3 +227,66 @@ QVector OculusBaseDisplayPlugin::getSensorPositions() { return result; } + +DisplayPlugin::StencilMaskMeshOperator OculusBaseDisplayPlugin::getStencilMaskMeshOperator() { + if (_session) { + if (!_stencilMeshesInitialized) { + _stencilMeshesInitialized = true; + ovr::for_each_eye([&](ovrEyeType eye) { + ovrFovStencilDesc stencilDesc = { + ovrFovStencil_HiddenArea, 0, eye, + _eyeRenderDescs[eye].Fov, _eyeRenderDescs[eye].HmdToEyePose.Orientation + }; + // First we get the size of the buffer we need + ovrFovStencilMeshBuffer buffer = { 0, 0, nullptr, 0, 0, nullptr }; + ovrResult result = ovr_GetFovStencil(_session, &stencilDesc, &buffer); + if (!OVR_SUCCESS(result)) { + _stencilMeshesInitialized = false; + return; + } + + std::vector ovrVertices(buffer.UsedVertexCount); + std::vector ovrIndices(buffer.UsedIndexCount); + + // Now we populate the actual buffer + buffer = { (int)ovrVertices.size(), 0, ovrVertices.data(), (int)ovrIndices.size(), 0, ovrIndices.data() }; + result = ovr_GetFovStencil(_session, &stencilDesc, &buffer); + + if (!OVR_SUCCESS(result)) { + _stencilMeshesInitialized = false; + return; + } + + std::vector vertices; + vertices.reserve(ovrVertices.size()); + for (auto& ovrVertex : ovrVertices) { + // We need the vertices in clip space + vertices.emplace_back(ovrVertex.x - (1.0f - (float)eye), 2.0f * ovrVertex.y - 1.0f, 0.0f); + } + + std::vector indices; + indices.reserve(ovrIndices.size()); + for (auto& ovrIndex : ovrIndices) { + indices.push_back(ovrIndex); + } + + _stencilMeshes[eye] = graphics::Mesh::createIndexedTriangles_P3F((uint32_t)vertices.size(), (uint32_t)indices.size(), vertices.data(), indices.data()); + }); + } + + if (_stencilMeshesInitialized) { + return [&](gpu::Batch& batch) { + for (auto& mesh : _stencilMeshes) { + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputFormat((mesh->getVertexFormat())); + batch.setInputStream(0, mesh->getVertexStream()); + + // Draw + auto part = mesh->getPartBuffer().get(0); + batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex); + } + }; + } + } + return nullptr; +} \ No newline at end of file diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 1abb7cdad7..d442c365ae 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -16,6 +16,8 @@ #define OVRPL_DISABLED #include +#include + class OculusBaseDisplayPlugin : public HmdDisplayPlugin { using Parent = HmdDisplayPlugin; public: @@ -34,6 +36,9 @@ public: QRectF getPlayAreaRect() override; QVector getSensorPositions() override; + virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::MESH; } + virtual StencilMaskMeshOperator getStencilMaskMeshOperator() override; + protected: void customizeContext() override; void uncustomizeContext() override; @@ -52,4 +57,7 @@ protected: // ovrLayerEyeFovDepth _depthLayer; bool _hmdMounted { false }; bool _visible { true }; + + std::array _stencilMeshes; + bool _stencilMeshesInitialized { false }; }; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 11d941dcd0..cd318dd9b4 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -784,3 +784,48 @@ QRectF OpenVrDisplayPlugin::getPlayAreaRect() { return QRectF(center.x, center.y, dimensions.x, dimensions.y); } + +DisplayPlugin::StencilMaskMeshOperator OpenVrDisplayPlugin::getStencilMaskMeshOperator() { + if (_system) { + if (!_stencilMeshesInitialized) { + _stencilMeshesInitialized = true; + for (auto eye : VR_EYES) { + vr::HiddenAreaMesh_t stencilMesh = _system->GetHiddenAreaMesh(eye); + if (stencilMesh.pVertexData && stencilMesh.unTriangleCount > 0) { + std::vector vertices; + std::vector indices; + + const int NUM_INDICES_PER_TRIANGLE = 3; + int numIndices = stencilMesh.unTriangleCount * NUM_INDICES_PER_TRIANGLE; + vertices.reserve(numIndices); + indices.reserve(numIndices); + for (int i = 0; i < numIndices; i++) { + vr::HmdVector2_t vertex2D = stencilMesh.pVertexData[i]; + // We need the vertices in clip space + vertices.emplace_back(vertex2D.v[0] - (1.0f - (float)eye), 2.0f * vertex2D.v[1] - 1.0f, 0.0f); + indices.push_back(i); + } + + _stencilMeshes[eye] = graphics::Mesh::createIndexedTriangles_P3F((uint32_t)vertices.size(), (uint32_t)indices.size(), vertices.data(), indices.data()); + } else { + _stencilMeshesInitialized = false; + } + } + } + + if (_stencilMeshesInitialized) { + return [&](gpu::Batch& batch) { + for (auto& mesh : _stencilMeshes) { + batch.setIndexBuffer(mesh->getIndexBuffer()); + batch.setInputFormat((mesh->getVertexFormat())); + batch.setInputStream(0, mesh->getVertexStream()); + + // Draw + auto part = mesh->getPartBuffer().get(0); + batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex); + } + }; + } + } + return nullptr; +} \ No newline at end of file diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 265f328920..4b042a700d 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -13,6 +13,8 @@ #include +#include + const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. namespace gl { @@ -67,6 +69,9 @@ public: QRectF getPlayAreaRect() override; + virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::MESH; } + virtual StencilMaskMeshOperator getStencilMaskMeshOperator() override; + protected: bool internalActivate() override; void internalDeactivate() override; @@ -94,4 +99,7 @@ private: bool _asyncReprojectionActive { false }; bool _hmdMounted { false }; + + std::array _stencilMeshes; + bool _stencilMeshesInitialized { false }; }; From feda884c71d9be5ded70ed4dd13a8d4c5bdf92ea Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 12 Apr 2019 09:21:48 -0700 Subject: [PATCH 21/74] remove view/Independent-Mode and view/Entity-Mode menu items and related code. Leave the modes available for scripts. --- interface/src/Application.cpp | 23 ------------------- interface/src/Menu.cpp | 14 ----------- interface/src/Menu.h | 2 -- interface/src/ModelSelector.cpp | 3 --- scripts/system/hmd.js | 6 ----- .../AppDataHighFidelity/Interface.json | 2 -- 6 files changed, 50 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d1add60647..099a2ec483 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1861,12 +1861,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) { getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); // So that camera doesn't auto-switch to third person. - } else if (Menu::getInstance()->isOptionChecked(MenuOption::IndependentMode)) { - Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true); - cameraMenuChanged(); - } else if (Menu::getInstance()->isOptionChecked(MenuOption::CameraEntityMode)) { - Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true); - cameraMenuChanged(); } { @@ -5757,9 +5751,6 @@ void Application::cycleCamera() { menu->setIsOptionChecked(MenuOption::ThirdPerson, false); menu->setIsOptionChecked(MenuOption::FullscreenMirror, true); - } else if (menu->isOptionChecked(MenuOption::IndependentMode) || menu->isOptionChecked(MenuOption::CameraEntityMode)) { - // do nothing if in independent or camera entity modes - return; } cameraMenuChanged(); // handle the menu change } @@ -5775,12 +5766,6 @@ void Application::cameraModeChanged() { case CAMERA_MODE_MIRROR: Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); break; - case CAMERA_MODE_INDEPENDENT: - Menu::getInstance()->setIsOptionChecked(MenuOption::IndependentMode, true); - break; - case CAMERA_MODE_ENTITY: - Menu::getInstance()->setIsOptionChecked(MenuOption::CameraEntityMode, true); - break; default: break; } @@ -5824,14 +5809,6 @@ void Application::cameraMenuChanged() { getMyAvatar()->setBoomLength(MyAvatar::ZOOM_DEFAULT); } } - } else if (menu->isOptionChecked(MenuOption::IndependentMode)) { - if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT) { - _myCamera.setMode(CAMERA_MODE_INDEPENDENT); - } - } else if (menu->isOptionChecked(MenuOption::CameraEntityMode)) { - if (_myCamera.getMode() != CAMERA_MODE_ENTITY) { - _myCamera.setMode(CAMERA_MODE_ENTITY); - } } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e9aadea2b6..5b6774b9bc 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -194,20 +194,6 @@ Menu::Menu() { viewMirrorAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); - // View > Independent - auto viewIndependentAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::IndependentMode, 0, - false, qApp, SLOT(cameraMenuChanged()))); - - viewIndependentAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); - - // View > Entity Camera - auto viewEntityCameraAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::CameraEntityMode, 0, - false, qApp, SLOT(cameraMenuChanged()))); - - viewEntityCameraAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); - viewMenu->addSeparator(); // View > Center Player In View diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3611faaf8f..550913bb21 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -53,7 +53,6 @@ namespace MenuOption { const QString BookmarkAvatarEntities = "Bookmark Avatar Entities"; const QString BookmarkLocation = "Bookmark Location"; const QString CalibrateCamera = "Calibrate Camera"; - const QString CameraEntityMode = "Entity Mode"; const QString CenterPlayerInView = "Center Player In View"; const QString Chat = "Chat..."; const QString ClearDiskCache = "Clear Disk Cache"; @@ -120,7 +119,6 @@ namespace MenuOption { const QString Help = "Help..."; const QString HomeLocation = "Home "; const QString IncreaseAvatarSize = "Increase Avatar Size"; - const QString IndependentMode = "Independent Mode"; const QString ActionMotorControl = "Enable Default Motor Control"; const QString LastLocation = "Last Location"; const QString LoadScript = "Open and Run Script File..."; diff --git a/interface/src/ModelSelector.cpp b/interface/src/ModelSelector.cpp index 3223e3ab9c..6da9327cac 100644 --- a/interface/src/ModelSelector.cpp +++ b/interface/src/ModelSelector.cpp @@ -18,9 +18,6 @@ #include #include -static const QString AVATAR_HEAD_AND_BODY_STRING = "Avatar Body with Head"; -static const QString ENTITY_MODEL_STRING = "Entity Model"; - ModelSelector::ModelSelector() { QFormLayout* form = new QFormLayout(this); diff --git a/scripts/system/hmd.js b/scripts/system/hmd.js index 2d4a2d3e97..858b93ef1e 100644 --- a/scripts/system/hmd.js +++ b/scripts/system/hmd.js @@ -40,9 +40,6 @@ function updateControllerDisplay() { var button; var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); -// Independent and Entity mode make people sick; disable them in hmd. -var desktopOnlyViews = ['Independent Mode', 'Entity Mode']; - var switchToVR = "ENTER VR"; var switchToDesktop = "EXIT VR"; @@ -59,9 +56,6 @@ function onHmdChanged(isHmd) { text: switchToVR }); } - desktopOnlyViews.forEach(function (view) { - Menu.setMenuEnabled("View>" + view, !isHmd); - }); updateControllerDisplay(); } diff --git a/tools/nitpick/AppDataHighFidelity/Interface.json b/tools/nitpick/AppDataHighFidelity/Interface.json index ca91a092c8..7a8a15e002 100644 --- a/tools/nitpick/AppDataHighFidelity/Interface.json +++ b/tools/nitpick/AppDataHighFidelity/Interface.json @@ -253,9 +253,7 @@ "UserActivityLoggerDisabled": false, "View/Center Player In View": true, "View/Enter First Person Mode in HMD": true, - "View/Entity Mode": false, "View/First Person": true, - "View/Independent Mode": false, "View/Mirror": false, "View/Third Person": false, "WindowGeometry": "@Rect(0 0 1920 1080)", From e7e9715e106949a7a2a7bd0c91b0d92d0f4fe633 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 15 Apr 2019 09:16:59 -0700 Subject: [PATCH 22/74] merging up --- .../utilities/lib/jet/qml/TaskPropView.qml | 47 +++++++++++-------- .../utilities/lib/prop/PropGroup.qml | 18 ++++--- .../utilities/lib/prop/style/Global.qml | 46 +++++++++--------- .../utilities/lib/prop/style/PiCanvasIcon.qml | 10 +++- scripts/developer/utilities/render/luci2.js | 21 ++++----- 5 files changed, 81 insertions(+), 61 deletions(-) diff --git a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml index af4cbb1c9a..be3cda66b3 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml @@ -27,33 +27,40 @@ Prop.PropGroup { property var jobPath: "" property alias label: root.label + property var showProps: true + property var showSubs: true + function populatePropItems() { var propsModel = [] var props = Jet.job_propKeys(rootConfig.getConfig(jobPath)); console.log(JSON.stringify(props)); - for (var p in props) { - propsModel.push({"object": rootConfig.getConfig(jobPath), "property":props[p] }) + if (showProps) { + for (var p in props) { + propsModel.push({"object": rootConfig.getConfig(jobPath), "property":props[p] }) + } + root.updatePropItems(propsModel); } - root.updatePropItems(propsModel); - - Jet.task_traverse(rootConfig.getConfig(jobPath), - function(job, depth, index) { - var component = Qt.createComponent("./TaskPropView.qml"); - component.createObject(root.propItemsPanel, { - "label": job.objectName, - "rootConfig": root.rootConfig, - "jobPath": root.jobPath + '.' + job.objectName - }) - /* var component = Qt.createComponent("../../prop/PropItem.qml"); - component.createObject(root.propItemsPanel, { - "label": root.jobPath + '.' + job.objectName + ' num=' + index, - })*/ - // propsModel.push({"type": "printLabel", "label": root.jobPath + '.' + job.objectName + ' num=' + index }) - - return (depth < 1); - }, 0) + if (showSubs) { + Jet.task_traverse(rootConfig.getConfig(jobPath), + function(job, depth, index) { + var component = Qt.createComponent("./TaskPropView.qml"); + component.createObject(root.propItemsPanel, { + "label": job.objectName, + "rootConfig": root.rootConfig, + "jobPath": root.jobPath + '.' + job.objectName, + "showProps": root.showProps, + "showSubs": root.showSubs + }) + /* var component = Qt.createComponent("../../prop/PropItem.qml"); + component.createObject(root.propItemsPanel, { + "label": root.jobPath + '.' + job.objectName + ' num=' + index, + })*/ + // propsModel.push({"type": "printLabel", "label": root.jobPath + '.' + job.objectName + ' num=' + index }) + return (depth < 1); + }, 0) + } } Component.onCompleted: { diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index f4b1ba02d6..4c37eecc80 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -18,7 +18,7 @@ Item { property alias isUnfold: headerFolderIcon.icon property alias propItemsPanel: propItemsContainer - property alias headerContainer: headerContainer + default property alias extHeader: headerContainer.data // Header Item Item { @@ -39,7 +39,9 @@ Item { id: headerFolderIcon anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter - + fillColor: global.colorOrangeAccent + filled: root.propItemsPanel.height > 4 + MouseArea{ id: mousearea anchors.fill: parent @@ -80,6 +82,7 @@ Item { border.width: global.valueBorderWidth radius: global.valueBorderRadius + anchors.margins: 0 anchors.left: parent.left anchors.right: parent.right anchors.top: header.bottom @@ -87,9 +90,11 @@ Item { Column { id: propItemsContainer - // anchors.top: header.bottom anchors.left: parent.left - anchors.right: parent.right + anchors.right: parent.right + anchors.leftMargin: 0 + anchors.rightMargin: 0 + clip: true // Where the propItems are added @@ -97,8 +102,9 @@ Item { } height: header.height + isUnfold * propItemsContainer.height - anchors.leftMargin: global.horizontalMargin - anchors.rightMargin: global.horizontalMargin +// anchors.leftMargin: global.horizontalMargin +// anchors.rightMargin: global.horizontalMargin + anchors.margins: 0 anchors.left: parent.left anchors.right: parent.right diff --git a/scripts/developer/utilities/lib/prop/style/Global.qml b/scripts/developer/utilities/lib/prop/style/Global.qml index 6066a4f99b..e348338df1 100644 --- a/scripts/developer/utilities/lib/prop/style/Global.qml +++ b/scripts/developer/utilities/lib/prop/style/Global.qml @@ -18,32 +18,36 @@ Item { HifiConstants { id: hifi } id: root - property real lineHeight: 32 - property real slimHeight: 24 + readonly property real lineHeight: 32 + readonly property real slimHeight: 24 - property real horizontalMargin: 4 + readonly property real horizontalMargin: 4 - property var color: hifi.colors.baseGray - property var colorBackHighlight: hifi.colors.baseGrayHighlight - property var colorBorderLight: hifi.colors.lightGray - property var colorBorderHighight: hifi.colors.blueHighlight + readonly property color color: hifi.colors.baseGray + readonly property color colorBackHighlight: hifi.colors.baseGrayHighlight + readonly property color colorBorderLight: hifi.colors.lightGray + readonly property color colorBorderHighight: hifi.colors.blueHighlight - property real fontSize: 12 - property var fontFamily: "Raleway" - property var fontWeight: Font.DemiBold - property var fontColor: hifi.colors.faintGray + readonly property color colorOrangeAccent: "#FF6309" + readonly property color colorRedAccent: "#C62147" + readonly property color colorGreenHighlight: "#1ac567" - property var splitterRightWidthScale: 0.45 - property real splitterWidth: 8 + readonly property real fontSize: 12 + readonly property var fontFamily: "Raleway" + readonly property var fontWeight: Font.DemiBold + readonly property color fontColor: hifi.colors.faintGray - property real iconWidth: fontSize - property real iconHeight: fontSize + readonly property var splitterRightWidthScale: 0.45 + readonly property real splitterWidth: 8 + + readonly property real iconWidth: fontSize + readonly property real iconHeight: fontSize - property var labelTextAlign: Text.AlignRight - property var labelTextElide: Text.ElideMiddle + readonly property var labelTextAlign: Text.AlignRight + readonly property var labelTextElide: Text.ElideMiddle - property var valueAreaWidthScale: 0.3 * (1.0 - splitterRightWidthScale) - property var valueTextAlign: Text.AlignHCenter - property real valueBorderWidth: 1 - property real valueBorderRadius: 2 + readonly property var valueAreaWidthScale: 0.3 * (1.0 - splitterRightWidthScale) + readonly property var valueTextAlign: Text.AlignHCenter + readonly property real valueBorderWidth: 1 + readonly property real valueBorderRadius: 2 } \ No newline at end of file diff --git a/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml b/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml index 6a805ea4c6..b8e80f1c3b 100644 --- a/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml +++ b/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml @@ -18,6 +18,7 @@ Canvas { height: global.iconHeight property var icon: 0 + property var filled: true onIconChanged: function () { requestPaint() } property var fillColor: global.colorBorderHighight @@ -43,8 +44,13 @@ Canvas { context.lineTo(width / 2, 0); } context.closePath(); - context.fillStyle = fillColor; - context.fill(); + if (filled) { + context.fillStyle = fillColor; + context.fill(); + } else { + context.strokeStyle = fillColor; + context.stroke(); + } }} } } \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci2.js b/scripts/developer/utilities/render/luci2.js index 4aea49a059..d6bb005795 100644 --- a/scripts/developer/utilities/render/luci2.js +++ b/scripts/developer/utilities/render/luci2.js @@ -1,13 +1,10 @@ -function openEngineTaskView() { +function openView() { // Set up the qml ui - var qml = Script.resolvePath('luci.qml'); - var window = new OverlayWindow({ - title: 'luci qml', - source: qml, - width: 300, - height: 400 - }); - window.setPosition(200, 50); - //window.closed.connect(function() { Script.stop(); }); - } - openEngineTaskView(); \ No newline at end of file + var window = Desktop.createWindow(Script.resolvePath('luci.qml'), { + title: this.title, + presentationMode: Desktop.PresentationMode.NATIVE, + size: {x: 300, y: 400} + }); + //window.closed.connect(function() { Script.stop(); }); +} +openView(); \ No newline at end of file From 249df3dce49117dbf3b41f1a78f1d13a7ef54312 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Apr 2019 07:53:55 +1200 Subject: [PATCH 23/74] Update Record app per Marketplace certification requirements --- .../marketplace/record/assets}/avatar-record-a.svg | 0 .../marketplace/record/assets}/avatar-record-i.svg | 0 unpublishedScripts/marketplace/record/record.app.json | 4 ++++ unpublishedScripts/marketplace/record/record.js | 4 ++-- 4 files changed, 6 insertions(+), 2 deletions(-) rename {interface/resources/icons/tablet-icons => unpublishedScripts/marketplace/record/assets}/avatar-record-a.svg (100%) rename {interface/resources/icons/tablet-icons => unpublishedScripts/marketplace/record/assets}/avatar-record-i.svg (100%) create mode 100644 unpublishedScripts/marketplace/record/record.app.json diff --git a/interface/resources/icons/tablet-icons/avatar-record-a.svg b/unpublishedScripts/marketplace/record/assets/avatar-record-a.svg similarity index 100% rename from interface/resources/icons/tablet-icons/avatar-record-a.svg rename to unpublishedScripts/marketplace/record/assets/avatar-record-a.svg diff --git a/interface/resources/icons/tablet-icons/avatar-record-i.svg b/unpublishedScripts/marketplace/record/assets/avatar-record-i.svg similarity index 100% rename from interface/resources/icons/tablet-icons/avatar-record-i.svg rename to unpublishedScripts/marketplace/record/assets/avatar-record-i.svg diff --git a/unpublishedScripts/marketplace/record/record.app.json b/unpublishedScripts/marketplace/record/record.app.json new file mode 100644 index 0000000000..3b2860db01 --- /dev/null +++ b/unpublishedScripts/marketplace/record/record.app.json @@ -0,0 +1,4 @@ +{ + "scriptURL": "http://mpassets.highfidelity.com/b3da90d4-390f-4f2c-ac78-6c8e074c93d7-v1/record.js", + "homeURL": "http://mpassets.highfidelity.com/b3da90d4-390f-4f2c-ac78-6c8e074c93d7-v1/html/record.html" +} diff --git a/unpublishedScripts/marketplace/record/record.js b/unpublishedScripts/marketplace/record/record.js index 4786356fee..18bcfbf5a1 100644 --- a/unpublishedScripts/marketplace/record/record.js +++ b/unpublishedScripts/marketplace/record/record.js @@ -13,8 +13,8 @@ (function () { var APP_NAME = "RECORD", - APP_ICON_INACTIVE = "icons/tablet-icons/avatar-record-i.svg", - APP_ICON_ACTIVE = "icons/tablet-icons/avatar-record-a.svg", + APP_ICON_INACTIVE = Script.resolvePath("assets/avatar-record-i.svg"), + APP_ICON_ACTIVE = Script.resolvePath("assets/avatar-record-a.svg"), APP_URL = Script.resolvePath("html/record.html"), isDialogDisplayed = false, tablet, From f2b747a68da13937ff85af386fc6c130f95890db Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 16 Apr 2019 18:15:00 -0700 Subject: [PATCH 24/74] Adding indentation of the folder in the header and refining background color --- .../utilities/lib/jet/qml/TaskPropView.qml | 6 ++++-- .../utilities/lib/prop/PropGroup.qml | 19 ++++++++++++++++--- .../utilities/lib/prop/style/Global.qml | 1 + 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml index be3cda66b3..9f64f12291 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml @@ -26,6 +26,7 @@ Prop.PropGroup { property var rootConfig : Render property var jobPath: "" property alias label: root.label + property alias indentDepth: root.indentDepth property var showProps: true property var showSubs: true @@ -33,7 +34,7 @@ Prop.PropGroup { function populatePropItems() { var propsModel = [] var props = Jet.job_propKeys(rootConfig.getConfig(jobPath)); - console.log(JSON.stringify(props)); + // console.log(JSON.stringify(props)); if (showProps) { for (var p in props) { propsModel.push({"object": rootConfig.getConfig(jobPath), "property":props[p] }) @@ -50,7 +51,8 @@ Prop.PropGroup { "rootConfig": root.rootConfig, "jobPath": root.jobPath + '.' + job.objectName, "showProps": root.showProps, - "showSubs": root.showSubs + "showSubs": root.showSubs, + "indentDepth": root.indentDepth + 1, }) /* var component = Qt.createComponent("../../prop/PropItem.qml"); component.createObject(root.propItemsPanel, { diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 4c37eecc80..a4e192308d 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -17,20 +17,33 @@ Item { property var label: "group" property alias isUnfold: headerFolderIcon.icon + property var indentDepth: 0 + property alias propItemsPanel: propItemsContainer default property alias extHeader: headerContainer.data // Header Item - Item { + Rectangle { id: header height: global.slimHeight anchors.left: parent.left anchors.right: parent.right - // First in the header, the folder button / indicator + color: global.colorBackShadow // header of group is darker + + // First in the header, some indentation spacer + Item { + id: indentSpacer + width: (headerFolderIcon.width * root.indentDepth) + global.horizontalMargin // Must be non-zero + height: parent.height + + anchors.verticalCenter: parent.verticalCenter + } + + // Second, the folder button / indicator Item { id: headerFolder - anchors.left: header.left + anchors.left: indentSpacer.right width: headerFolderIcon.width * 2 anchors.verticalCenter: header.verticalCenter height: parent.height diff --git a/scripts/developer/utilities/lib/prop/style/Global.qml b/scripts/developer/utilities/lib/prop/style/Global.qml index e348338df1..4cdee70244 100644 --- a/scripts/developer/utilities/lib/prop/style/Global.qml +++ b/scripts/developer/utilities/lib/prop/style/Global.qml @@ -24,6 +24,7 @@ Item { readonly property real horizontalMargin: 4 readonly property color color: hifi.colors.baseGray + readonly property color colorBackShadow: hifi.colors.baseGrayShadow readonly property color colorBackHighlight: hifi.colors.baseGrayHighlight readonly property color colorBorderLight: hifi.colors.lightGray readonly property color colorBorderHighight: hifi.colors.blueHighlight From 4ce7d75720ee92015037f6fd0b10edb2d0ea5a61 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 16 Apr 2019 23:38:40 -0700 Subject: [PATCH 25/74] FInding a path --- .../utilities/lib/jet/qml/TaskPropView.qml | 30 +++++++++++++++++++ .../utilities/lib/prop/PropGroup.qml | 27 ++++++++--------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml index 9f64f12291..2f7ee71a5f 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml @@ -30,6 +30,36 @@ Prop.PropGroup { property var showProps: true property var showSubs: true + property var jobEnabled: true + + // Panel Header Data Component + panelHeaderData: Component { + Item { + id: header + Prop.PropLabel { + text: root.label + horizontalAlignment: Text.AlignHCenter + anchors.left: parent.left + anchors.right: enabledIcon.left + anchors.verticalCenter: parent.verticalCenter + } + Prop.PropCanvasIcon { + id: enabledIcon + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + fillColor: global.colorOrangeAccent + filled: jobEnabled + + MouseArea{ + id: mousearea + anchors.fill: parent + onClicked: { + root.jobEnabled = !root.jobEnabled + } + } + } + } + } function populatePropItems() { var propsModel = [] diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index a4e192308d..6836e85e25 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -20,7 +20,16 @@ Item { property var indentDepth: 0 property alias propItemsPanel: propItemsContainer - default property alias extHeader: headerContainer.data + + // Panel Header Data Component + property Component panelHeaderData: defaultPanelHeaderData + Component { // default is a Label + id: defaultPanelHeaderData + PropLabel { + text: root.label + horizontalAlignment: Text.AlignHCenter + } + } // Header Item Rectangle { @@ -67,22 +76,12 @@ Item { // Next the header container // by default containing a Label showing the root.label - Item { - id: headerContainer + Loader { + sourceComponent: panelHeaderData anchors.left: headerFolder.right anchors.right: header.right anchors.verticalCenter: header.verticalCenter height: parent.height - - PropLabel { - id: labelControl - anchors.left: headerContainer.left - anchors.right: headerContainer.right - anchors.verticalCenter: headerContainer.verticalCenter - text: root.label - horizontalAlignment: Text.AlignHCenter - } - } } @@ -115,8 +114,6 @@ Item { } height: header.height + isUnfold * propItemsContainer.height -// anchors.leftMargin: global.horizontalMargin -// anchors.rightMargin: global.horizontalMargin anchors.margins: 0 anchors.left: parent.left anchors.right: parent.right From ae20a5d439379e771acdec2b484d43a11ae6f3bc Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 17 Apr 2019 09:47:33 +0200 Subject: [PATCH 26/74] Fixed crash in debugShadow.js --- libraries/render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render-utils/src/RenderShadowTask.h | 3 ++- libraries/task/src/task/Task.h | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ea2b05a6fa..aae3237784 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -364,7 +364,7 @@ void RenderDeferredTaskDebug::build(JobModel& task, const render::Varying& input sprintf(jobName, "DrawShadowFrustum%d", i); task.addJob(jobName, shadowFrustum, glm::vec3(0.0f, tint, 1.0f)); if (!renderShadowTaskOut.isNull()) { - const auto& shadowCascadeSceneBBoxes = renderShadowTaskOut; + const auto& shadowCascadeSceneBBoxes = renderShadowTaskOut.get(); const auto shadowBBox = shadowCascadeSceneBBoxes[ExtractFrustums::SHADOW_CASCADE0_FRUSTUM + i]; sprintf(jobName, "DrawShadowBBox%d", i); task.addJob(jobName, shadowBBox, glm::vec3(1.0f, tint, 0.0f)); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index a261deefb8..8e6efeab9f 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -90,7 +90,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende #endif }; - render::VaryingArray cascadeSceneBBoxes; + CascadeBoxes cascadeSceneBBoxes; for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { char jobName[64]; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 4dc6f3073f..82b3ebac4f 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -52,8 +52,9 @@ class RenderShadowTask { public: // There is one AABox per shadow cascade + using CascadeBoxes = render::VaryingArray; using Input = render::VaryingSet2; - using Output = render::VaryingSet2, LightStage::ShadowFramePointer>; + using Output = render::VaryingSet2; using Config = RenderShadowTaskConfig; using JobModel = render::Task::ModelIO; diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 632e8a222e..b74986235e 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -152,6 +152,7 @@ public: template static std::shared_ptr create(const std::string& name, const Varying& input, A&&... args) { + assert(input.canCast()); return std::make_shared(name, input, std::make_shared(), std::forward(args)...); } From 5d7b149a9ec51fc750b5f4271e449105f42fc440 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 17 Apr 2019 11:12:59 +0200 Subject: [PATCH 27/74] Switched to clamped tangent for shadow slope bias --- libraries/render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render-utils/src/RenderShadowTask.h | 4 ++-- libraries/render-utils/src/Shadow.slh | 15 ++++++++------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 8e6efeab9f..bf564c1c10 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -336,7 +336,7 @@ void RenderShadowSetup::setConstantBias(int cascadeIndex, float value) { } void RenderShadowSetup::setSlopeBias(int cascadeIndex, float value) { - _bias[cascadeIndex]._slope = value * value * value * 0.01f; + _bias[cascadeIndex]._slope = value * value * value * 0.001f; } void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 82b3ebac4f..1cfa786e43 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -95,8 +95,8 @@ public: float constantBias3{ 0.2f }; float slopeBias0{ 0.6f }; float slopeBias1{ 0.6f }; - float slopeBias2{ 0.7f }; - float slopeBias3{ 0.82f }; + float slopeBias2{ 0.65f }; + float slopeBias3{ 0.7f }; signals: void dirty(); diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index b503844554..94bec86b34 100644 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -90,8 +90,8 @@ float evalShadowAttenuationPCF(int cascadeIndex, ShadowSampleOffsets offsets, ve return shadowAttenuation; } -float evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float oneMinusNdotL) { - float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * oneMinusNdotL; +float evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float slopeNdotL) { + float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * slopeNdotL; return evalShadowAttenuationPCF(cascadeIndex, offsets, shadowTexcoord, bias); } @@ -104,7 +104,8 @@ float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDe vec3 cascadeMix; bvec4 isPixelOnCascade; int cascadeIndex; - float oneMinusNdotL = 1.0 - clamp(dot(worldLightDir, worldNormal), 0.0, 1.0); + float NdotL = clamp(dot(worldLightDir, worldNormal), 0.0, 1.0); + float slopeNdotL = min(2.0, sqrt(1.0-NdotL*NdotL) / NdotL); for (cascadeIndex=0 ; cascadeIndex Date: Wed, 17 Apr 2019 12:35:24 +0200 Subject: [PATCH 28/74] Added opacity mask to shadow casters --- .../src/graphics/MaterialTextures.slh | 6 ++++ .../render-utils/src/MeshPartPayload.cpp | 5 +++ .../render-utils/src/RenderPipelines.cpp | 35 ++++++++++++++++++- libraries/render-utils/src/RenderPipelines.h | 1 + .../src/deformed_model_shadow.slv | 15 ++++++++ .../src/deformed_model_shadow_dq.slv | 15 ++++++++ .../render-utils/src/model_normal_map.slf | 2 +- libraries/render-utils/src/model_shadow.slf | 18 ++++++++++ libraries/render-utils/src/model_shadow.slv | 13 +++++++ 9 files changed, 108 insertions(+), 2 deletions(-) diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index c725aae9bb..16c7f0e211 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -149,6 +149,12 @@ float fetchScatteringMap(vec2 uv) { <@endfunc@> +<@func fetchMaterialAlbedoTextureCoord0(matKey, texcoord0, albedo)@> + if (getTexMapArray()._materialParams.y != 1.0 && clamp(<$texcoord0$>, vec2(0.0), vec2(1.0)) != <$texcoord0$>) { + discard; + } + vec4 <$albedo$> = fetchAlbedoMap(<$texcoord0$>); +<@endfunc@> <@func fetchMaterialTexturesCoord0(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, scattering)@> if (getTexMapArray()._materialParams.y != 1.0 && clamp(<$texcoord0$>, vec2(0.0), vec2(1.0)) != <$texcoord0$>) { diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2634784f3a..9470f11d59 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -437,6 +437,11 @@ void ModelMeshPartPayload::render(RenderArgs* args) { if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) { RenderPipelines::bindMaterials(_drawMaterials, batch, args->_enableTexturing); args->_details._materialSwitches++; + } else { + // We might have an opacity mask so we need to bind the albedo texture and material which might hold + // the alpha mask channel + RenderPipelines::bindMaterialsOpacityMask(_drawMaterials, batch, args->_enableTexturing); + args->_details._materialSwitches++; } // Draw! diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index c4a7368f39..ba0a079c7f 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -730,6 +730,8 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial multiMaterial.setInitialized(); } +static gpu::TextureTablePointer defaultMaterialTextures = std::make_shared(); + void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures) { if (multiMaterial.shouldUpdate()) { updateMultiMaterial(multiMaterial); @@ -737,7 +739,6 @@ void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu: auto textureCache = DependencyManager::get(); - static gpu::TextureTablePointer defaultMaterialTextures = std::make_shared(); static std::once_flag once; std::call_once(once, [textureCache] { defaultMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture()); @@ -763,3 +764,35 @@ void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu: batch.setResourceTextureTable(defaultMaterialTextures); } } + +static gpu::BufferView defaultMaterialSchema; + +void RenderPipelines::bindMaterialsOpacityMask(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures) { + if (multiMaterial.shouldUpdate()) { + updateMultiMaterial(multiMaterial); + } + + if (multiMaterial.getMaterialKey().isOpacityMaskMap()) { + auto textureCache = DependencyManager::get(); + + static std::once_flag once; + std::call_once(once, [textureCache] { + defaultMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture()); + }); + + auto& schemaBuffer = multiMaterial.getSchemaBuffer(); + batch.setUniformBuffer(gr::Buffer::Material, schemaBuffer); + + if (enableTextures) { + batch.setResourceTextureTable(multiMaterial.getTextureTable()); + } else { + batch.setResourceTextureTable(defaultMaterialTextures); + } + } else { + if (defaultMaterialSchema._buffer == nullptr) { + graphics::MultiMaterial::Schema schema; + defaultMaterialSchema = gpu::BufferView(std::make_shared(sizeof(schema), (const gpu::Byte*) &schema, sizeof(schema))); + } + batch.setUniformBuffer(gr::Buffer::Material, defaultMaterialSchema); + } +} diff --git a/libraries/render-utils/src/RenderPipelines.h b/libraries/render-utils/src/RenderPipelines.h index 0f3d1160ef..4a99b21e74 100644 --- a/libraries/render-utils/src/RenderPipelines.h +++ b/libraries/render-utils/src/RenderPipelines.h @@ -18,6 +18,7 @@ public: static void bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, bool enableTextures); static void updateMultiMaterial(graphics::MultiMaterial& multiMaterial); static void bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures); + static void bindMaterialsOpacityMask(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures); }; diff --git a/libraries/render-utils/src/deformed_model_shadow.slv b/libraries/render-utils/src/deformed_model_shadow.slv index cc6fb42f98..827fc69b32 100644 --- a/libraries/render-utils/src/deformed_model_shadow.slv +++ b/libraries/render-utils/src/deformed_model_shadow.slv @@ -18,9 +18,15 @@ <$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> <$declareMeshDeformerActivation(1, 1)$> +<@include graphics/Material.slh@> +<@include graphics/MaterialTextures.slh@> + +<$declareMaterialTexMapArrayBuffer()$> + <@include render-utils/ShaderConstants.h@> layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main(void) { vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); @@ -33,5 +39,14 @@ void main(void) { TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, deformedPosition, gl_Position)$> <$transformModelToWorldPos(obj, deformedPosition, _positionWS)$> + + Material mat = getMaterial(); + BITFIELD matKey = getMaterialKey(mat); + _texCoord01 = vec4(0.0, 0.0, 0.0, 0.0); + // If we have an opacity mask than we need the first tex coord + if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + } } diff --git a/libraries/render-utils/src/deformed_model_shadow_dq.slv b/libraries/render-utils/src/deformed_model_shadow_dq.slv index 84b5dfb33b..646fc12ce9 100644 --- a/libraries/render-utils/src/deformed_model_shadow_dq.slv +++ b/libraries/render-utils/src/deformed_model_shadow_dq.slv @@ -18,9 +18,15 @@ <$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, 1, 1)$> <$declareMeshDeformerActivation(1, 1)$> +<@include graphics/Material.slh@> +<@include graphics/MaterialTextures.slh@> + +<$declareMaterialTexMapArrayBuffer()$> + <@include render-utils/ShaderConstants.h@> layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main(void) { vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); @@ -33,4 +39,13 @@ void main(void) { TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, deformedPosition, gl_Position)$> <$transformModelToWorldPos(obj, deformedPosition, _positionWS)$> + + Material mat = getMaterial(); + BITFIELD matKey = getMaterialKey(mat); + _texCoord01 = vec4(0.0, 0.0, 0.0, 0.0); + // If we have an opacity mask than we need the first tex coord + if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + } } diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index 5fbc81e35b..695fadbca8 100644 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -32,7 +32,7 @@ void main(void) { <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); diff --git a/libraries/render-utils/src/model_shadow.slf b/libraries/render-utils/src/model_shadow.slf index 862fcd0cf6..956ece4923 100644 --- a/libraries/render-utils/src/model_shadow.slf +++ b/libraries/render-utils/src/model_shadow.slf @@ -9,10 +9,28 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include graphics/Material.slh@> +<@include graphics/MaterialTextures.slh@> +<@include render-utils/ShaderConstants.h@> + +<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; +#define _texCoord0 _texCoord01.xy layout(location=0) out vec4 _fragColor; void main(void) { + Material mat = getMaterial(); + BITFIELD matKey = getMaterialKey(mat); + + if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { + float opacity = 1.0; + <$fetchMaterialAlbedoTextureCoord0(matKey, _texCoord0, albedoTex)$> + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + } + // pass-through to set z-buffer _fragColor = vec4(1.0, 1.0, 1.0, 0.0); } diff --git a/libraries/render-utils/src/model_shadow.slv b/libraries/render-utils/src/model_shadow.slv index 8de77d7b1d..d455ea4ade 100644 --- a/libraries/render-utils/src/model_shadow.slv +++ b/libraries/render-utils/src/model_shadow.slv @@ -13,12 +13,16 @@ <@include gpu/Inputs.slh@> <@include gpu/Transform.slh@> +<@include graphics/Material.slh@> +<@include graphics/MaterialTextures.slh@> <$declareStandardTransform()$> +<$declareMaterialTexMapArrayBuffer()$> <@include render-utils/ShaderConstants.h@> layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main(void) { // standard transform @@ -26,4 +30,13 @@ void main(void) { TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> <$transformModelToWorldPos(obj, inPosition, _positionWS)$> + + Material mat = getMaterial(); + BITFIELD matKey = getMaterialKey(mat); + _texCoord01 = vec4(0.0, 0.0, 0.0, 0.0); + // If we have an opacity mask than we need the first tex coord + if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + } } From 54d7bde91a5524217bbebaa9ea0644ad3b544cdc Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 17 Apr 2019 10:56:55 -0700 Subject: [PATCH 29/74] grid ignorePickIntersection --- scripts/system/libraries/gridTool.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 1fd3cbfbaa..233ae3a3e4 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -25,7 +25,8 @@ Grid = function() { color: gridColor, alpha: gridAlpha, minorGridEvery: minorGridEvery, - majorGridEvery: majorGridEvery + majorGridEvery: majorGridEvery, + ignorePickIntersection: true }); that.visible = false; From e7d12dc4f88accac9da92bd3bec6fd1cc38fce7d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 17 Apr 2019 15:43:05 -0700 Subject: [PATCH 30/74] fix snapshots and preview --- interface/src/Application.cpp | 22 ++++-- interface/src/Application.h | 4 + interface/src/graphics/GraphicsEngine.cpp | 4 +- interface/src/ui/Snapshot.cpp | 74 ++++++++++--------- interface/src/ui/Snapshot.h | 2 + interface/src/ui/SnapshotAnimated.cpp | 30 ++++---- interface/src/ui/SnapshotAnimated.h | 3 +- .../src/display-plugins/NullDisplayPlugin.cpp | 10 +-- .../src/display-plugins/NullDisplayPlugin.h | 2 - .../display-plugins/OpenGLDisplayPlugin.cpp | 23 +++--- .../src/display-plugins/OpenGLDisplayPlugin.h | 5 +- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 2 +- libraries/gpu/src/gpu/Frame.h | 1 + libraries/plugins/src/plugins/DisplayPlugin.h | 4 - 14 files changed, 101 insertions(+), 85 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bc0feefb9a..7ad077151e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -8428,6 +8428,17 @@ bool Application::takeSnapshotOperators(std::queue& snapshotOp return !snapshotOperators.empty(); } +void Application::addSecondarySnapshotOperator(const SecondarySnapshotOperator& snapshotOperator) { + std::lock_guard lock(_snapshotMutex); + _secondarySnapshotOperators.push(snapshotOperator); +} + +bool Application::takeSecondarySnapshotOperators(std::queue& snapshotOperators) { + std::lock_guard lock(_snapshotMutex); + _secondarySnapshotOperators.swap(snapshotOperators); + return !snapshotOperators.empty(); +} + void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { addSnapshotOperator({ [notify, includeAnimated, aspectRatio, filename](const QImage& snapshot) { QString path = DependencyManager::get()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); @@ -8439,16 +8450,17 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa emit DependencyManager::get()->stillSnapshotTaken(path, notify); } } else if (!SnapshotAnimated::isAlreadyTakingSnapshotAnimated()) { - // Get an animated GIF snapshot and save it - SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, qApp, DependencyManager::get()); + qApp->postLambdaEvent([path, aspectRatio] { + // Get an animated GIF snapshot and save it + SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, DependencyManager::get()); + }); } }, aspectRatio }); } void Application::takeSecondaryCameraSnapshot(const bool& notify, const QString& filename) { - postLambdaEvent([notify, filename, this] { - QString snapshotPath = DependencyManager::get()->saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename, - TestScriptingInterface::getInstance()->getTestResultsLocation()); + addSecondarySnapshotOperator([notify, filename](const QImage& snapshot) { + QString snapshotPath = DependencyManager::get()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); emit DependencyManager::get()->stillSnapshotTaken(snapshotPath, notify); }); diff --git a/interface/src/Application.h b/interface/src/Application.h index b2e59e97d4..0004add3b1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -345,8 +345,11 @@ public: #endif using SnapshotOperator = std::pair, float>; + using SecondarySnapshotOperator = std::function; void addSnapshotOperator(const SnapshotOperator& snapshotOperator); bool takeSnapshotOperators(std::queue& snapshotOperators); + void addSecondarySnapshotOperator(const SecondarySnapshotOperator& snapshotOperator); + bool takeSecondarySnapshotOperators(std::queue& snapshotOperators); signals: void svoImportRequested(const QString& url); @@ -794,6 +797,7 @@ private: SharedSoundPointer _sampleSound; std::mutex _snapshotMutex; std::queue _snapshotOperators; + std::queue _secondarySnapshotOperators; DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin; QString _autoSwitchDisplayModeSupportedHMDPluginName; diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 1842c20e4e..09471a9570 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -245,6 +245,7 @@ void GraphicsEngine::render_performFrame() { } std::queue snapshotOperators; + std::queue secondarySnapshotOperators; if (!_programsCompiled.load()) { gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { batch.setFramebuffer(finalFramebuffer); @@ -273,12 +274,12 @@ void GraphicsEngine::render_performFrame() { renderArgs._hudOperator = displayPlugin->getHUDOperator(); renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture(); renderArgs._takingSnapshot = qApp->takeSnapshotOperators(snapshotOperators); + qApp->takeSecondarySnapshotOperators(secondarySnapshotOperators); renderArgs._blitFramebuffer = finalFramebuffer; render_runRenderFrame(&renderArgs); } } - qDebug() << "boop" << renderArgs._takingSnapshot << snapshotOperators.size(); auto frame = getGPUContext()->endFrame(); frame->frameIndex = _renderFrameCount; frame->framebuffer = finalFramebuffer; @@ -289,6 +290,7 @@ void GraphicsEngine::render_performFrame() { } }; frame->snapshotOperators = snapshotOperators; + frame->secondarySnapshotOperators = secondarySnapshotOperators; // deliver final scene rendering commands to the display plugin { PROFILE_RANGE(render, "/pluginOutput"); diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 60c039ce1f..94523fa6dd 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -159,47 +159,57 @@ void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, secondaryCameraRenderConfig->setOrientation(CAMERA_ORIENTATION_DOWN); _snapshotIndex = 0; + _taking360Snapshot = true; _snapshotTimer.start(SNAPSHOT_360_TIMER_INTERVAL); } void Snapshot::takeNextSnapshot() { - SecondaryCameraJobConfig* config = - static_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera")); + if (_taking360Snapshot) { + if (!_waitingOnSnapshot) { + _waitingOnSnapshot = true; + qApp->addSecondarySnapshotOperator([this](const QImage& snapshot) { + // Order is: + // 0. Down + // 1. Front + // 2. Left + // 3. Back + // 4. Right + // 5. Up + if (_snapshotIndex < 6) { + _imageArray[_snapshotIndex] = snapshot; + } - // Order is: - // 0. Down - // 1. Front - // 2. Left - // 3. Back - // 4. Right - // 5. Up - if (_snapshotIndex < 6) { - _imageArray[_snapshotIndex] = qApp->getActiveDisplayPlugin()->getSecondaryCameraScreenshot(); - } + SecondaryCameraJobConfig* config = static_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera")); + if (_snapshotIndex == 0) { + // Setup for Front Image capture + config->setOrientation(CAMERA_ORIENTATION_FRONT); + } else if (_snapshotIndex == 1) { + // Setup for Left Image capture + config->setOrientation(CAMERA_ORIENTATION_LEFT); + } else if (_snapshotIndex == 2) { + // Setup for Back Image capture + config->setOrientation(CAMERA_ORIENTATION_BACK); + } else if (_snapshotIndex == 3) { + // Setup for Right Image capture + config->setOrientation(CAMERA_ORIENTATION_RIGHT); + } else if (_snapshotIndex == 4) { + // Setup for Up Image capture + config->setOrientation(CAMERA_ORIENTATION_UP); + } else if (_snapshotIndex == 5) { + _taking360Snapshot = false; + } - if (_snapshotIndex == 0) { - // Setup for Front Image capture - config->setOrientation(CAMERA_ORIENTATION_FRONT); - } else if (_snapshotIndex == 1) { - // Setup for Left Image capture - config->setOrientation(CAMERA_ORIENTATION_LEFT); - } else if (_snapshotIndex == 2) { - // Setup for Back Image capture - config->setOrientation(CAMERA_ORIENTATION_BACK); - } else if (_snapshotIndex == 3) { - // Setup for Right Image capture - config->setOrientation(CAMERA_ORIENTATION_RIGHT); - } else if (_snapshotIndex == 4) { - // Setup for Up Image capture - config->setOrientation(CAMERA_ORIENTATION_UP); - } else if (_snapshotIndex > 5) { + _waitingOnSnapshot = false; + _snapshotIndex++; + }); + } + } else { _snapshotTimer.stop(); // Reset secondary camera render config - static_cast( - qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping")) - ->setCurve(1); + SecondaryCameraJobConfig* config = static_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera")); + static_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping"))->setCurve(1); config->resetSizeSpectatorCamera(qApp->getWindow()->geometry().width(), qApp->getWindow()->geometry().height()); config->setProperty("attachedEntityId", _oldAttachedEntityId); config->setProperty("vFoV", _oldvFoV); @@ -217,8 +227,6 @@ void Snapshot::takeNextSnapshot() { QtConcurrent::run([this]() { convertToEquirectangular(); }); } } - - _snapshotIndex++; } void Snapshot::convertToCubemap() { diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 77bdfd4ac1..f13f4cd587 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -97,6 +97,8 @@ private: bool _cubemapOutputFormat; QTimer _snapshotTimer; qint16 _snapshotIndex; + bool _waitingOnSnapshot { false }; + bool _taking360Snapshot { false }; bool _oldEnabled; QVariant _oldAttachedEntityId; QVariant _oldOrientation; diff --git a/interface/src/ui/SnapshotAnimated.cpp b/interface/src/ui/SnapshotAnimated.cpp index 1c5a25b68f..03ec86e342 100644 --- a/interface/src/ui/SnapshotAnimated.cpp +++ b/interface/src/ui/SnapshotAnimated.cpp @@ -27,7 +27,6 @@ QString SnapshotAnimated::snapshotAnimatedPath; QString SnapshotAnimated::snapshotStillPath; QVector SnapshotAnimated::snapshotAnimatedFrameVector; QVector SnapshotAnimated::snapshotAnimatedFrameDelayVector; -Application* SnapshotAnimated::app; float SnapshotAnimated::aspectRatio; QSharedPointer SnapshotAnimated::snapshotAnimatedDM; GifWriter SnapshotAnimated::snapshotAnimatedGifWriter; @@ -36,12 +35,11 @@ GifWriter SnapshotAnimated::snapshotAnimatedGifWriter; Setting::Handle SnapshotAnimated::alsoTakeAnimatedSnapshot("alsoTakeAnimatedSnapshot", true); Setting::Handle SnapshotAnimated::snapshotAnimatedDuration("snapshotAnimatedDuration", SNAPSNOT_ANIMATED_DURATION_SECS); -void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio, Application* app, QSharedPointer dm) { +void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio, QSharedPointer dm) { // If we're not in the middle of capturing an animated snapshot... if (SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp == 0) { SnapshotAnimated::snapshotAnimatedTimer = new QTimer(); SnapshotAnimated::aspectRatio = aspectRatio; - SnapshotAnimated::app = app; SnapshotAnimated::snapshotAnimatedDM = dm; // Define the output location of the still and animated snapshots. SnapshotAnimated::snapshotStillPath = pathStill; @@ -62,7 +60,7 @@ void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio void SnapshotAnimated::captureFrames() { if (SnapshotAnimated::snapshotAnimatedTimerRunning) { - SnapshotAnimated::app->addSnapshotOperator({ [](const QImage& snapshot) { + qApp->addSnapshotOperator({ [](const QImage& snapshot) { // Get a screenshot from the display, then scale the screenshot down, // then convert it to the image format the GIF library needs, // then save all that to the QImage named "frame" @@ -86,21 +84,21 @@ void SnapshotAnimated::captureFrames() { // If that was the last frame... if ((SnapshotAnimated::snapshotAnimatedTimestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp) >= (SnapshotAnimated::snapshotAnimatedDuration.get() * MSECS_PER_SECOND)) { SnapshotAnimated::snapshotAnimatedTimerRunning = false; - - // Notify the user that we're processing the snapshot - // This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called. - emit SnapshotAnimated::snapshotAnimatedDM->processingGifStarted(SnapshotAnimated::snapshotStillPath); - - // Kick off the thread that'll pack the frames into the GIF - QtConcurrent::run(processFrames); - // Stop the snapshot QTimer. This action by itself DOES NOT GUARANTEE - // that the slot will not be called again in the future. - // See: http://lists.qt-project.org/pipermail/qt-interest-old/2009-October/013926.html - SnapshotAnimated::snapshotAnimatedTimer->stop(); - delete SnapshotAnimated::snapshotAnimatedTimer; } } }, SnapshotAnimated::aspectRatio }); + } else { + // Notify the user that we're processing the snapshot + // This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called. + emit SnapshotAnimated::snapshotAnimatedDM->processingGifStarted(SnapshotAnimated::snapshotStillPath); + + // Kick off the thread that'll pack the frames into the GIF + QtConcurrent::run(processFrames); + // Stop the snapshot QTimer. This action by itself DOES NOT GUARANTEE + // that the slot will not be called again in the future. + // See: http://lists.qt-project.org/pipermail/qt-interest-old/2009-October/013926.html + SnapshotAnimated::snapshotAnimatedTimer->stop(); + delete SnapshotAnimated::snapshotAnimatedTimer; } } diff --git a/interface/src/ui/SnapshotAnimated.h b/interface/src/ui/SnapshotAnimated.h index 87ce533fc3..15734f57c8 100644 --- a/interface/src/ui/SnapshotAnimated.h +++ b/interface/src/ui/SnapshotAnimated.h @@ -42,7 +42,6 @@ private: static QVector snapshotAnimatedFrameVector; static QVector snapshotAnimatedFrameDelayVector; static QSharedPointer snapshotAnimatedDM; - static Application* app; static float aspectRatio; static GifWriter snapshotAnimatedGifWriter; @@ -51,7 +50,7 @@ private: static void processFrames(); static void clearTempVariables(); public: - static void saveSnapshotAnimated(QString pathStill, float aspectRatio, Application* app, QSharedPointer dm); + static void saveSnapshotAnimated(QString pathStill, float aspectRatio, QSharedPointer dm); static bool isAlreadyTakingSnapshotAnimated() { return snapshotAnimatedFirstFrameTimestamp != 0; }; static Setting::Handle alsoTakeAnimatedSnapshot; static Setting::Handle snapshotAnimatedDuration; diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index 47a213cf71..fcd695bed8 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -25,12 +25,4 @@ void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) { if (frame) { _gpuContext->consumeFrameUpdates(frame); } -} - -QImage NullDisplayPlugin::getScreenshot(float aspectRatio) const { - return QImage(); -} - -QImage NullDisplayPlugin::getSecondaryCameraScreenshot() const { - return QImage(); -} +} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index e4ff1b8b37..7aa763bab9 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -17,8 +17,6 @@ public: glm::uvec2 getRecommendedRenderSize() const override; void submitFrame(const gpu::FramePointer& newFrame) override; - QImage getScreenshot(float aspectRatio = 0.0f) const override; - QImage getSecondaryCameraScreenshot() const override; void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override {}; void pluginUpdate() override {}; private: diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 1700ca9d54..f9b6deb846 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -732,6 +732,15 @@ void OpenGLDisplayPlugin::present() { } } + { // If we have any secondary camera snapshots this frame, handle them + PROFILE_RANGE_EX(render, "secondarySnapshotOperators", 0x00ff00ff, frameId) + while (!_currentFrame->secondarySnapshotOperators.empty()) { + auto& snapshotOperator = _currentFrame->secondarySnapshotOperators.front(); + snapshotOperator(getSecondaryCameraScreenshot()); + _currentFrame->secondarySnapshotOperators.pop(); + } + } + // Take the composite framebuffer and send it to the output device { PROFILE_RANGE_EX(render, "internalPresent", 0xff00ffff, frameId) @@ -796,7 +805,7 @@ bool OpenGLDisplayPlugin::setDisplayTexture(const QString& name) { return !!_displayTexture; } -QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const { +QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) { auto size = _compositeFramebuffer->getSize(); if (isHmd()) { size.x /= 2; @@ -812,24 +821,18 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const { corner.x = round((size.x - bestSize.x) / 2.0f); corner.y = round((size.y - bestSize.y) / 2.0f); } - auto glBackend = const_cast(*this).getGLBackend(); QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32); - withOtherThreadContext([&] { - glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot); - }); + getGLBackend()->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot); return screenshot.mirrored(false, true); } -QImage OpenGLDisplayPlugin::getSecondaryCameraScreenshot() const { +QImage OpenGLDisplayPlugin::getSecondaryCameraScreenshot() { auto textureCache = DependencyManager::get(); auto secondaryCameraFramebuffer = textureCache->getSpectatorCameraFramebuffer(); gpu::Vec4i region(0, 0, secondaryCameraFramebuffer->getWidth(), secondaryCameraFramebuffer->getHeight()); - auto glBackend = const_cast(*this).getGLBackend(); QImage screenshot(region.z, region.w, QImage::Format_ARGB32); - withOtherThreadContext([&] { - glBackend->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot); - }); + getGLBackend()->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot); return screenshot.mirrored(false, true); } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 49a38ecb4c..e56804c151 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -60,8 +60,6 @@ public: virtual bool setDisplayTexture(const QString& name) override; virtual bool onDisplayTextureReset() { return false; }; - QImage getScreenshot(float aspectRatio = 0.0f) const override; - QImage getSecondaryCameraScreenshot() const override; float presentRate() const override; @@ -185,5 +183,8 @@ protected: // be serialized through this mutex mutable Mutex _presentMutex; float _hudAlpha{ 1.0f }; + + QImage getScreenshot(float aspectRatio); + QImage getSecondaryCameraScreenshot(); }; diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 321bcc3fd2..874454b391 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -199,7 +199,7 @@ void HmdDisplayPlugin::internalPresent() { float newWidth = sourceSize.x - shiftLeftBy; // Experimentally adjusted the region presented in preview to avoid seeing the masked pixels and recenter the center... - static float SCALE_WIDTH = 0.9f; + static float SCALE_WIDTH = 0.8f; static float SCALE_OFFSET = 2.0f; newWidth *= SCALE_WIDTH; shiftLeftBy *= SCALE_OFFSET; diff --git a/libraries/gpu/src/gpu/Frame.h b/libraries/gpu/src/gpu/Frame.h index 94c0919fdb..541b9393d3 100644 --- a/libraries/gpu/src/gpu/Frame.h +++ b/libraries/gpu/src/gpu/Frame.h @@ -43,6 +43,7 @@ namespace gpu { FramebufferRecycler framebufferRecycler; std::queue, float>> snapshotOperators; + std::queue> secondarySnapshotOperators; protected: friend class Deserializer; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 9db8fc995c..c88d76e661 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -173,10 +173,6 @@ public: return QRect(0, 0, recommendedSize.x, recommendedSize.y); } - // Fetch the most recently displayed image as a QImage - virtual QImage getScreenshot(float aspectRatio = 0.0f) const = 0; - virtual QImage getSecondaryCameraScreenshot() const = 0; - // will query the underlying hmd api to compute the most recent head pose virtual bool beginFrameRender(uint32_t frameIndex) { return true; } From 9873c10353486c861dd1c484e9a4b6e63655cc4b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 17 Apr 2019 17:58:48 -0700 Subject: [PATCH 31/74] Better canvas ICon qml and activation of the jobs --- .../utilities/lib/jet/qml/TaskPropView.qml | 33 +++++--- .../utilities/lib/prop/PropGroup.qml | 9 +-- .../utilities/lib/prop/style/PiCanvasIcon.qml | 80 +++++++++++++++---- 3 files changed, 85 insertions(+), 37 deletions(-) diff --git a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml index 2f7ee71a5f..e53932a9f9 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml @@ -32,31 +32,40 @@ Prop.PropGroup { property var showSubs: true property var jobEnabled: true + property var toggleJobActivation: function() { + console.log("the button has been pressed and jobEnabled is " + jobEnabled ) + jobEnabled = !jobEnabled; + rootConfig.getConfig(jobPath).enabled = jobEnabled; + } + // Panel Header Data Component panelHeaderData: Component { Item { id: header Prop.PropLabel { text: root.label - horizontalAlignment: Text.AlignHCenter + //horizontalAlignment: Text.AlignHCenter anchors.left: parent.left anchors.right: enabledIcon.left anchors.verticalCenter: parent.verticalCenter - } + } Prop.PropCanvasIcon { id: enabledIcon + anchors.right: enabledIcon2.left + anchors.verticalCenter: parent.verticalCenter + filled: root.jobEnabled + fillColor: (root.jobEnabled ? global.colorGreenHighlight : global.colorOrangeAccent) + icon: 5 + iconMouseArea.onClicked: { toggleJobActivation() } + } + Prop.PropCanvasIcon { + id: enabledIcon2 anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - fillColor: global.colorOrangeAccent - filled: jobEnabled - - MouseArea{ - id: mousearea - anchors.fill: parent - onClicked: { - root.jobEnabled = !root.jobEnabled - } - } + filled: root.jobEnabled + fillColor: (root.jobEnabled ? global.colorGreenHighlight : global.colorOrangeAccent) + icon: 7 + iconMouseArea.onClicked: { toggleJobActivation() } } } } diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 6836e85e25..38f19389aa 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -63,14 +63,7 @@ Item { anchors.verticalCenter: parent.verticalCenter fillColor: global.colorOrangeAccent filled: root.propItemsPanel.height > 4 - - MouseArea{ - id: mousearea - anchors.fill: parent - onClicked: { - root.isUnfold = !root.isUnfold - } - } + iconMouseArea.onClicked: { root.isUnfold = !root.isUnfold } } } diff --git a/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml b/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml index b8e80f1c3b..3feed342b8 100644 --- a/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml +++ b/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml @@ -18,39 +18,85 @@ Canvas { height: global.iconHeight property var icon: 0 + + onIconChanged: function () { //console.log("Icon changed to: " + icon ); + requestPaint() + } + property var filled: true - onIconChanged: function () { requestPaint() } + onFilledChanged: function () { //console.log("Filled changed to: " + filled ); + requestPaint() + } + property var fillColor: global.colorBorderHighight + onFillColorChanged: function () { //console.log("fillColor changed to: " + filled ); + requestPaint() + } + + property alias iconMouseArea: mousearea contextType: "2d" onPaint: { context.reset(); switch (icon) { - case 0: - case 1: - case 2: - default: { - if ((icon % 3) == 0) { + case false: + case 0:{ // Right Arrow context.moveTo(width * 0.25, 0); context.lineTo(width * 0.25, height); context.lineTo(width, height / 2); - } else if ((icon % 3) == 1) { + context.closePath(); + } break; + case true: + case 1:{ // Up Arrow context.moveTo(0, height * 0.25); context.lineTo(width, height * 0.25); context.lineTo(width / 2, height); - } else { + context.closePath(); + } break; + case 2:{ // Down Arrow context.moveTo(0, height * 0.75); context.lineTo(width, height* 0.75); context.lineTo(width / 2, 0); + context.closePath(); + } break; + case 3:{ // Left Arrow + context.moveTo(width * 0.75, 0); + context.lineTo(width * 0.75, height); + context.lineTo(0, height / 2); + context.closePath(); + } break; + case 4:{ // Square + context.moveTo(0,0); + context.lineTo(0, height); + context.lineTo(width, height); + context.lineTo(width, 0); + context.closePath(); + } break; + case 5:{ // Small Square + context.moveTo(width * 0.25, height * 0.25); + context.lineTo(width * 0.25, height * 0.75); + context.lineTo(width * 0.75, height * 0.75); + context.lineTo(width * 0.75, height * 0.25); + context.closePath(); + } break; + default: {// Down Arrow + /* context.moveTo(0, height * 0.25); + context.lineTo(width, height * 0.25); + context.lineTo(width / 2, height); + context.closePath();*/ } - context.closePath(); - if (filled) { - context.fillStyle = fillColor; - context.fill(); - } else { - context.strokeStyle = fillColor; - context.stroke(); - } - }} + } + if (filled) { + context.fillStyle = fillColor; + context.fill(); + } else { + context.strokeStyle = fillColor; + context.stroke(); + } + } + + MouseArea{ + id: mousearea + anchors.fill: parent } } \ No newline at end of file From 3b1751f2c98072c4de2dfd50b3b9ef4c194149b5 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 17 Apr 2019 20:18:17 -0700 Subject: [PATCH 32/74] adding proper logic for shield icon behavior --- interface/resources/qml/BubbleIcon.qml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/BubbleIcon.qml b/interface/resources/qml/BubbleIcon.qml index f4e99f136c..b5a7ddb2d8 100644 --- a/interface/resources/qml/BubbleIcon.qml +++ b/interface/resources/qml/BubbleIcon.qml @@ -23,15 +23,15 @@ Rectangle { property bool ignoreRadiusEnabled: AvatarInputs.ignoreRadiusEnabled; function updateOpacity() { - if (ignoreRadiusEnabled) { - bubbleRect.opacity = 1.0; - } else { - bubbleRect.opacity = 0.7; - } + var rectOpacity = ignoreRadiusEnabled ? 1.0 : (mouseArea.containsMouse ? 1.0 : 0.7); + bubbleRect.opacity = rectOpacity; } Component.onCompleted: { updateOpacity(); + AvatarInputs.ignoreRadiusEnabledChanged.connect(function() { + ignoreRadiusEnabled = AvatarInputs.ignoreRadiusEnabled; + }); } onIgnoreRadiusEnabledChanged: { @@ -74,10 +74,10 @@ Rectangle { } drag.target: dragTarget; onContainsMouseChanged: { - var rectOpacity = (ignoreRadiusEnabled && containsMouse) ? 1.0 : (containsMouse ? 1.0 : 0.7); if (containsMouse) { Tablet.playSound(TabletEnums.ButtonHover); } + var rectOpacity = ignoreRadiusEnabled ? 1.0 : (mouseArea.containsMouse ? 1.0 : 0.7); bubbleRect.opacity = rectOpacity; } } From 3d78592bb84ddc417bfde7f8acb83e98dd32eaed Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 18 Apr 2019 00:19:19 -0700 Subject: [PATCH 33/74] Adding more style widgets andbringing luci1 into the panels of luci2 --- .../developer/utilities/lib/prop/PropBool.qml | 4 +- .../utilities/lib/prop/PropGroup.qml | 30 +++- scripts/developer/utilities/lib/prop/qmldir | 2 + .../utilities/lib/prop/style/PiCheckBox.qml | 25 ++++ .../lib/prop/style/PiFolderPanel.qml | 133 ++++++++++++++++++ .../utilities/render/deferredLighting.qml | 71 +--------- scripts/developer/utilities/render/luci.qml | 32 ++--- .../utilities/render/luci/ShadingModel.qml | 105 ++++++++++++++ .../developer/utilities/render/luci/qmldir | 2 + 9 files changed, 306 insertions(+), 98 deletions(-) create mode 100644 scripts/developer/utilities/lib/prop/style/PiCheckBox.qml create mode 100644 scripts/developer/utilities/lib/prop/style/PiFolderPanel.qml create mode 100644 scripts/developer/utilities/render/luci/ShadingModel.qml create mode 100644 scripts/developer/utilities/render/luci/qmldir diff --git a/scripts/developer/utilities/lib/prop/PropBool.qml b/scripts/developer/utilities/lib/prop/PropBool.qml index d8e4bad589..1d50ec7dd3 100644 --- a/scripts/developer/utilities/lib/prop/PropBool.qml +++ b/scripts/developer/utilities/lib/prop/PropBool.qml @@ -9,7 +9,6 @@ // import QtQuick 2.7 -import controlsUit 1.0 as HifiControls PropItem { Global { id: global } @@ -21,13 +20,12 @@ PropItem { valueVar = root.valueVarGetter(); } - HifiControls.CheckBox { + PropCheckBox { id: checkboxControl anchors.left: root.splitter.right anchors.verticalCenter: root.verticalCenter width: root.width * global.valueAreaWidthScale - height: global.slimHeight onCheckedChanged: { root.valueVarSetter(checked); } } diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 38f19389aa..2f15e60a0c 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -10,19 +10,35 @@ import QtQuick 2.7 -Item { +//Item { +PropFolderPanel { Global { id: global } id: root - property var label: "group" + // property var label: "group" - property alias isUnfold: headerFolderIcon.icon - property var indentDepth: 0 + // property alias isUnfold: headerFolderIcon.icon + // property var indentDepth: 0 - property alias propItemsPanel: propItemsContainer + //property alias propItemsPanel: _panelFrameData + // property alias propItemsPanel: propItemsContainer + //property var propItemsPanel: propItemsContainer + + panelFrameData: Component { // default is a column + id: groupPanelFrameData + Column { + id: propItemsContainer + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: 0 + anchors.rightMargin: 0 + + clip: true + } + } // Panel Header Data Component - property Component panelHeaderData: defaultPanelHeaderData +/* property Component panelHeaderData: defaultPanelHeaderData Component { // default is a Label id: defaultPanelHeaderData PropLabel { @@ -110,7 +126,7 @@ Item { anchors.margins: 0 anchors.left: parent.left anchors.right: parent.right - +*/ // Prop Group is designed to author an array of ProItems, they are defined with an array of the tuplets describing each individual item: // [ ..., PropItemInfo, ...] diff --git a/scripts/developer/utilities/lib/prop/qmldir b/scripts/developer/utilities/lib/prop/qmldir index 2cd06d58ac..c67ab6a41a 100644 --- a/scripts/developer/utilities/lib/prop/qmldir +++ b/scripts/developer/utilities/lib/prop/qmldir @@ -5,6 +5,8 @@ PropLabel 1.0 style/PiLabel.qml PropSplitter 1.0 style/PiSplitter.qml PropComboBox 1.0 style/PiComboBox.qml PropCanvasIcon 1.0 style/PiCanvasIcon.qml +PropCheckBox 1.0 style/PiCheckBox.qml +PropFolderPanel 1.0 style/PiFolderPanel.qml PropItem 1.0 PropItem.qml PropScalar 1.0 PropScalar.qml diff --git a/scripts/developer/utilities/lib/prop/style/PiCheckBox.qml b/scripts/developer/utilities/lib/prop/style/PiCheckBox.qml new file mode 100644 index 0000000000..108a763be3 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/style/PiCheckBox.qml @@ -0,0 +1,25 @@ +// +// Prop/style/PiCheckBox.qml +// +// Created by Sam Gateau on 3/2/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 +import controlsUit 1.0 as HifiControls + +HifiControls.CheckBox { + Global { id: global } + + color: global.fontColor + + //anchors.left: root.splitter.right + //anchors.verticalCenter: root.verticalCenter + //width: root.width * global.valueAreaWidthScale + height: global.slimHeight + + onCheckedChanged: { root.valueVarSetter(checked); } +} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/prop/style/PiFolderPanel.qml b/scripts/developer/utilities/lib/prop/style/PiFolderPanel.qml new file mode 100644 index 0000000000..b80ab47fc6 --- /dev/null +++ b/scripts/developer/utilities/lib/prop/style/PiFolderPanel.qml @@ -0,0 +1,133 @@ +// +// Prop/style/PiFoldedPanel.qml +// +// Created by Sam Gateau on 4/17/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +Item { + Global { id: global } + id: root + + property var label: "panel" + + property alias isUnfold: headerFolderIcon.icon + property var indentDepth: 0 + + // Panel Header Data Component + property Component panelHeaderData: defaultPanelHeaderData + Component { // default is a Label + id: defaultPanelHeaderData + PiLabel { + text: root.label + horizontalAlignment: Text.AlignHCenter + } + } + + // Panel Frame Data Component + property Component panelFrameData: defaultPanelFrameData + Component { // default is a column + id: defaultPanelFrameData + Column { + } + } + + //property alias panelFrameContent: frame._panelFrameData.data + + // Header Item + Rectangle { + id: header + height: global.slimHeight + anchors.left: parent.left + anchors.right: parent.right + + color: global.colorBackShadow // header of group is darker + + // First in the header, some indentation spacer + Item { + id: indentSpacer + width: (headerFolderIcon.width * root.indentDepth) + global.horizontalMargin // Must be non-zero + height: parent.height + + anchors.verticalCenter: parent.verticalCenter + } + + // Second, the folder button / indicator + Item { + id: headerFolder + anchors.left: indentSpacer.right + width: headerFolderIcon.width * 2 + anchors.verticalCenter: header.verticalCenter + height: parent.height + + PiCanvasIcon { + id: headerFolderIcon + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + fillColor: global.colorOrangeAccent + filled: root.frame.height > 4 + iconMouseArea.onClicked: { root.isUnfold = !root.isUnfold } + } + } + + // Next the header container + // by default containing a Label showing the root.label + Loader { + sourceComponent: panelHeaderData + anchors.left: headerFolder.right + anchors.right: header.right + anchors.verticalCenter: header.verticalCenter + height: parent.height + } + } + + // The Panel container + Rectangle { + id: frame + visible: root.isUnfold + + color: "transparent" + border.color: global.colorBorderLight + border.width: global.valueBorderWidth + radius: global.valueBorderRadius + + anchors.margins: 0 + anchors.left: parent.left + anchors.right: parent.right + anchors.top: header.bottom + anchors.bottom: root.bottom + + // Next the panel frame data + Loader { + sourceComponent: panelFrameData + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: 0 + anchors.rightMargin: 0 + id: _panelFrameData + clip: true + } + + /* Column { + id: propItemsContainer + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: 0 + anchors.rightMargin: 0 + + clip: true + + // Where the propItems are added + }*/ + } + + height: header.height + isUnfold * _panelFrameData.height + anchors.margins: 0 + anchors.left: parent.left + anchors.right: parent.right +} \ No newline at end of file diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index d147585212..63c2af1b0f 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -14,6 +14,7 @@ import QtQuick.Layouts 1.3 import stylesUit 1.0 import controlsUit 1.0 as HifiControls import "configSlider" +import "luci" Rectangle { HifiConstants { id: hifi;} @@ -32,76 +33,8 @@ Rectangle { HifiControls.Label { text: "Shading" } - Row { - anchors.left: parent.left - anchors.right: parent.right - - spacing: 5 - Column { - spacing: 5 - // padding: 10 - Repeater { - model: [ - "Unlit:LightingModel:enableUnlit", - "Emissive:LightingModel:enableEmissive", - "Lightmap:LightingModel:enableLightmap", - "Background:LightingModel:enableBackground", - "Haze:LightingModel:enableHaze", - "AO:LightingModel:enableAmbientOcclusion", - "Textures:LightingModel:enableMaterialTexturing" - ] - HifiControls.CheckBox { - boxSize: 20 - text: modelData.split(":")[0] - checked: render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] - onCheckedChanged: { render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } - } - } - } + ShadingModel { - - Column { - spacing: 5 - Repeater { - model: [ - "Obscurance:LightingModel:enableObscurance", - "Scattering:LightingModel:enableScattering", - "Diffuse:LightingModel:enableDiffuse", - "Specular:LightingModel:enableSpecular", - "Albedo:LightingModel:enableAlbedo", - "Wireframe:LightingModel:enableWireframe", - "Skinning:LightingModel:enableSkinning", - "Blendshape:LightingModel:enableBlendshape" - ] - HifiControls.CheckBox { - boxSize: 20 - text: modelData.split(":")[0] - checked: render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] - onCheckedChanged: { render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } - } - } - } - - Column { - spacing: 5 - Repeater { - model: [ - "Ambient:LightingModel:enableAmbientLight", - "Directional:LightingModel:enableDirectionalLight", - "Point:LightingModel:enablePointLight", - "Spot:LightingModel:enableSpotLight", - "Light Contour:LightingModel:showLightContour", - "Zone Stack:DrawZoneStack:enabled", - "Shadow:LightingModel:enableShadow" - ] - HifiControls.CheckBox { - boxSize: 20 - text: modelData.split(":")[0] - checked: render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] - onCheckedChanged: { render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } - } - } - } } Separator {} Column { diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index 8c68d654a1..7bce087fda 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -15,6 +15,7 @@ import controlsUit 1.0 as HifiControls import "../lib/prop" as Prop import "../lib/jet/qml" as Jet +import "luci" Rectangle { anchors.fill: parent @@ -31,7 +32,14 @@ Rectangle { Column { width: render.width - + Prop.PropFolderPanel { + id: "shadingModel" + label: "Shading Model" + panelFrameData: Component { + ShadingModel { + } + } + } /* Prop.PropEnum { label: "Tone Curve" object: render.mainViewTask.getConfig("ToneMapping") @@ -45,14 +53,6 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right } */ - Jet.TaskPropView { - id: "lightingModel" - jobPath: "RenderMainView.LightingModel" - label: "Le LightingModel" - - anchors.left: parent.left - anchors.right: parent.right - } Jet.TaskPropView { id: "theView" jobPath: "RenderMainView" @@ -69,20 +69,14 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right } - /* Jet.TaskPropView { - jobPath: "RenderMainView.ToneMapping" - label: "Le ToneMapping Job" + Jet.TaskPropView { + id: "le" + jobPath: "" + label: "Le Render Engine" anchors.left: parent.left anchors.right: parent.right } - Jet.TaskPropView { - jobPath: "RenderMainView.Antialiasing" - label: "Le Antialiasing Job" - - anchors.left: parent.left - anchors.right: parent.right - }*/ } } diff --git a/scripts/developer/utilities/render/luci/ShadingModel.qml b/scripts/developer/utilities/render/luci/ShadingModel.qml new file mode 100644 index 0000000000..2c16492e80 --- /dev/null +++ b/scripts/developer/utilities/render/luci/ShadingModel.qml @@ -0,0 +1,105 @@ +// +// ShadingModel.qml +// +// Created by Sam Gateau on 4/17/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +import stylesUit 1.0 +import controlsUit 1.0 as HifiControls + +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import stylesUit 1.0 +import controlsUit 1.0 as HifiControls + +import "../../lib/prop" as Prop + + +Column { + + id: shadingModel; + + property var mainViewTask: Render.getConfig("RenderMainView") + + spacing: 5 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x + HifiControls.Label { + text: "Shading" + } + Row { + anchors.left: parent.left + anchors.right: parent.right + + spacing: 5 + Column { + spacing: 5 + Repeater { + model: [ + "Unlit:LightingModel:enableUnlit", + "Emissive:LightingModel:enableEmissive", + "Lightmap:LightingModel:enableLightmap", + "Background:LightingModel:enableBackground", + "Haze:LightingModel:enableHaze", + "AO:LightingModel:enableAmbientOcclusion", + "Textures:LightingModel:enableMaterialTexturing" + ] + Prop.PropCheckBox { + text: modelData.split(":")[0] + checked: render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] + onCheckedChanged: { render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } + } + } + } + + + Column { + spacing: 5 + Repeater { + model: [ + "Obscurance:LightingModel:enableObscurance", + "Scattering:LightingModel:enableScattering", + "Diffuse:LightingModel:enableDiffuse", + "Specular:LightingModel:enableSpecular", + "Albedo:LightingModel:enableAlbedo", + "Wireframe:LightingModel:enableWireframe", + "Skinning:LightingModel:enableSkinning", + "Blendshape:LightingModel:enableBlendshape" + ] + Prop.PropCheckBox { + text: modelData.split(":")[0] + checked: render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] + onCheckedChanged: { render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } + } + } + } + + Column { + spacing: 5 + Repeater { + model: [ + "Ambient:LightingModel:enableAmbientLight", + "Directional:LightingModel:enableDirectionalLight", + "Point:LightingModel:enablePointLight", + "Spot:LightingModel:enableSpotLight", + "Light Contour:LightingModel:showLightContour", + "Zone Stack:DrawZoneStack:enabled", + "Shadow:LightingModel:enableShadow" + ] + Prop.PropCheckBox { + text: modelData.split(":")[0] + checked: render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] + onCheckedChanged: { render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } + } + } + } + } +} diff --git a/scripts/developer/utilities/render/luci/qmldir b/scripts/developer/utilities/render/luci/qmldir new file mode 100644 index 0000000000..cf63b1c2b7 --- /dev/null +++ b/scripts/developer/utilities/render/luci/qmldir @@ -0,0 +1,2 @@ + +ShadingModel 1.0 ShadingModel.qml \ No newline at end of file From 3cb9c518eae445a44c9b5e49f6bd3e7cba38753a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 18 Apr 2019 11:06:12 +0200 Subject: [PATCH 34/74] Exposed max shadow distance and a shadow bias scale parameter in graphics::Light --- libraries/graphics/src/graphics/Light.cpp | 16 +++ libraries/graphics/src/graphics/Light.h | 11 +- libraries/render-utils/src/LightStage.cpp | 105 ++++++++++-------- libraries/render-utils/src/LightStage.h | 6 +- .../render-utils/src/RenderShadowTask.cpp | 8 +- 5 files changed, 87 insertions(+), 59 deletions(-) diff --git a/libraries/graphics/src/graphics/Light.cpp b/libraries/graphics/src/graphics/Light.cpp index 76d8a6030a..8a7281880e 100755 --- a/libraries/graphics/src/graphics/Light.cpp +++ b/libraries/graphics/src/graphics/Light.cpp @@ -73,6 +73,22 @@ bool Light::getCastShadows() const { return _castShadows; } +void Light::setShadowsMaxDistance(const float maxDistance) { + _shadowsMaxDistance = std::max(0.0f, maxDistance); +} + +float Light::getShadowsMaxDistance() const { + return _shadowsMaxDistance; +} + +void Light::setShadowsBiasScale(const float scale) { + _shadowsBiasScale = std::max(0.0f, scale); +} + +float Light::getShadowsBiasScale() const { + return _shadowsBiasScale; +} + void Light::setColor(const Color& color) { _lightSchemaBuffer.edit().irradiance.color = color; updateLightRadius(); diff --git a/libraries/graphics/src/graphics/Light.h b/libraries/graphics/src/graphics/Light.h index bb9fb3e5b9..824a9138c0 100755 --- a/libraries/graphics/src/graphics/Light.h +++ b/libraries/graphics/src/graphics/Light.h @@ -106,6 +106,12 @@ public: void setCastShadows(const bool castShadows); bool getCastShadows() const; + void setShadowsMaxDistance(const float maxDistance); + float getShadowsMaxDistance() const; + + void setShadowsBiasScale(const float scale); + float getShadowsBiasScale() const; + void setOrientation(const Quat& orientation); const glm::quat& getOrientation() const { return _transform.getRotation(); } @@ -192,10 +198,11 @@ protected: Type _type { SUN }; float _spotCos { -1.0f }; // stored here to be able to reset the spot angle when turning the type spot on/off - void updateLightRadius(); - + float _shadowsMaxDistance{ 40.0f }; + float _shadowsBiasScale{ 1.0f }; bool _castShadows{ false }; + void updateLightRadius(); }; typedef std::shared_ptr< Light > LightPointer; diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 6913949286..d35bc21526 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -120,7 +120,7 @@ float LightStage::Shadow::Cascade::computeFarDistance(const ViewFrustum& viewFru return far; } -LightStage::Shadow::Shadow(graphics::LightPointer light, float maxDistance, unsigned int cascadeCount) : +LightStage::Shadow::Shadow(graphics::LightPointer light, unsigned int cascadeCount) : _light{ light } { cascadeCount = std::min(cascadeCount, (unsigned int)SHADOW_CASCADE_MAX_COUNT); Schema schema; @@ -149,70 +149,77 @@ LightStage::Shadow::Shadow(graphics::LightPointer light, float maxDistance, unsi cascade.framebuffer->setDepthBuffer(map, depthFormat, cascadeIndex); } - setMaxDistance(maxDistance); + if (light) { + setMaxDistance(light->getShadowsMaxDistance()); + } } void LightStage::Shadow::setLight(graphics::LightPointer light) { _light = light; + if (light) { + setMaxDistance(light->getShadowsMaxDistance()); + } } - void LightStage::Shadow::setMaxDistance(float value) { - // This overlaping factor isn't really used directly for blending of shadow cascades. It - // just there to be sure the cascades do overlap. The blending width used is relative - // to the UV space and is set in the Schema with invCascadeBlendWidth. - static const auto OVERLAP_FACTOR = 1.0f / 5.0f; + value = std::max(1e-3f, value); + if (value != _maxDistance) { + // This overlaping factor isn't really used directly for blending of shadow cascades. It's + // just there to be sure the cascades do overlap. The blending width used is relative + // to the UV space and is set in the Schema with invCascadeBlendWidth. + static const auto OVERLAP_FACTOR = 1.0f / 5.0f; - _maxDistance = std::max(0.0f, value); + _maxDistance = value; - if (_cascades.size() == 1) { - _cascades.front().setMinDistance(0.0f); - _cascades.front().setMaxDistance(_maxDistance); - } else { - // Distribute the cascades along that distance - // TODO : these parameters should be exposed to the user as part of the light entity parameters, no? - static const auto LOW_MAX_DISTANCE = 2.0f; - static const auto MAX_RESOLUTION_LOSS = 0.6f; // Between 0 and 1, 0 giving tighter distributions + if (_cascades.size() == 1) { + _cascades.front().setMinDistance(0.0f); + _cascades.front().setMaxDistance(_maxDistance); + } else { + // Distribute the cascades along that distance + // TODO : these parameters should be exposed to the user as part of the light entity parameters, no? + static const auto LOW_MAX_DISTANCE = 2.0f; + static const auto MAX_RESOLUTION_LOSS = 0.6f; // Between 0 and 1, 0 giving tighter distributions - // The max cascade distance is computed by multiplying the previous cascade's max distance by a certain - // factor. There is a "user" factor that is computed from a desired max resolution loss in the shadow - // and an optimal one based on the global min and max shadow distance, all cascades considered. The final - // distance is a gradual blend between the two - const auto userDistanceScale = 1.0f / (1.0f - MAX_RESOLUTION_LOSS); - const auto optimalDistanceScale = powf(_maxDistance / LOW_MAX_DISTANCE, 1.0f / (_cascades.size() - 1)); + // The max cascade distance is computed by multiplying the previous cascade's max distance by a certain + // factor. There is a "user" factor that is computed from a desired max resolution loss in the shadow + // and an optimal one based on the global min and max shadow distance, all cascades considered. The final + // distance is a gradual blend between the two + const auto userDistanceScale = 1.0f / (1.0f - MAX_RESOLUTION_LOSS); + const auto optimalDistanceScale = powf(_maxDistance / LOW_MAX_DISTANCE, 1.0f / (_cascades.size() - 1)); - float maxCascadeUserDistance = LOW_MAX_DISTANCE; - float maxCascadeOptimalDistance = LOW_MAX_DISTANCE; - float minCascadeDistance = 0.0f; + float maxCascadeUserDistance = LOW_MAX_DISTANCE; + float maxCascadeOptimalDistance = LOW_MAX_DISTANCE; + float minCascadeDistance = 0.0f; - for (size_t cascadeIndex = 0; cascadeIndex < _cascades.size(); ++cascadeIndex) { - float blendFactor = cascadeIndex / float(_cascades.size() - 1); - float maxCascadeDistance; + for (size_t cascadeIndex = 0; cascadeIndex < _cascades.size(); ++cascadeIndex) { + float blendFactor = cascadeIndex / float(_cascades.size() - 1); + float maxCascadeDistance; - if (cascadeIndex == size_t(_cascades.size() - 1)) { - maxCascadeDistance = _maxDistance; - } else { - maxCascadeDistance = maxCascadeUserDistance + (maxCascadeOptimalDistance - maxCascadeUserDistance)*blendFactor*blendFactor; + if (cascadeIndex == size_t(_cascades.size() - 1)) { + maxCascadeDistance = _maxDistance; + } else { + maxCascadeDistance = maxCascadeUserDistance + (maxCascadeOptimalDistance - maxCascadeUserDistance)*blendFactor*blendFactor; + } + + float shadowOverlapDistance = maxCascadeDistance * OVERLAP_FACTOR; + + _cascades[cascadeIndex].setMinDistance(minCascadeDistance); + _cascades[cascadeIndex].setMaxDistance(maxCascadeDistance + shadowOverlapDistance); + + // Compute distances for next cascade + minCascadeDistance = maxCascadeDistance; + maxCascadeUserDistance = maxCascadeUserDistance * userDistanceScale; + maxCascadeOptimalDistance = maxCascadeOptimalDistance * optimalDistanceScale; + maxCascadeUserDistance = std::min(maxCascadeUserDistance, _maxDistance); } - - float shadowOverlapDistance = maxCascadeDistance * OVERLAP_FACTOR; - - _cascades[cascadeIndex].setMinDistance(minCascadeDistance); - _cascades[cascadeIndex].setMaxDistance(maxCascadeDistance + shadowOverlapDistance); - - // Compute distances for next cascade - minCascadeDistance = maxCascadeDistance; - maxCascadeUserDistance = maxCascadeUserDistance * userDistanceScale; - maxCascadeOptimalDistance = maxCascadeOptimalDistance * optimalDistanceScale; - maxCascadeUserDistance = std::min(maxCascadeUserDistance, _maxDistance); } - } - // Update the buffer - const auto& lastCascade = _cascades.back(); - auto& schema = _schemaBuffer.edit(); - schema.maxDistance = _maxDistance; - schema.invFalloffDistance = 1.0f / (OVERLAP_FACTOR*lastCascade.getMaxDistance()); + // Update the buffer + const auto& lastCascade = _cascades.back(); + auto& schema = _schemaBuffer.edit(); + schema.maxDistance = _maxDistance; + schema.invFalloffDistance = 1.0f / (OVERLAP_FACTOR*lastCascade.getMaxDistance()); + } } void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 1fb1754862..4da66843cc 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -74,7 +74,7 @@ public: float left, float right, float bottom, float top, float viewMaxShadowDistance) const; }; - Shadow(graphics::LightPointer light, float maxDistance, unsigned int cascadeCount = 1); + Shadow(graphics::LightPointer light, unsigned int cascadeCount = 1); void setLight(graphics::LightPointer light); @@ -104,16 +104,14 @@ public: }; protected: - using Cascades = std::vector; static const glm::mat4 _biasMatrix; graphics::LightPointer _light; - float _maxDistance; + float _maxDistance{ 0.0f }; Cascades _cascades; - UniformBufferView _schemaBuffer = nullptr; }; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index bf564c1c10..5de89a11b5 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -34,7 +34,6 @@ #define SHADOW_FRUSTUM_NEAR 1.0f #define SHADOW_FRUSTUM_FAR 500.0f static const unsigned int SHADOW_CASCADE_COUNT{ 4 }; -static const float SHADOW_MAX_DISTANCE{ 40.0f }; using namespace render; @@ -367,7 +366,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c output.edit2() = _cameraFrustum; if (!_globalShadowObject) { - _globalShadowObject = std::make_shared(graphics::LightPointer(), SHADOW_MAX_DISTANCE, SHADOW_CASCADE_COUNT); + _globalShadowObject = std::make_shared(currentKeyLight, SHADOW_CASCADE_COUNT); } _globalShadowObject->setLight(currentKeyLight); @@ -378,11 +377,12 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c unsigned int cascadeIndex; // Adjust each cascade frustum + const auto biasScale = currentKeyLight->getShadowsBiasScale(); for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { auto& bias = _bias[cascadeIndex]; _globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), - SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR, - bias._constant, bias._slope); + SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR, + bias._constant, bias._slope * biasScale); } _shadowFrameCache->pushShadow(_globalShadowObject); From 5baf2f21d84d5d3a481242e5800ad97ac2b1afad Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Thu, 18 Apr 2019 07:48:59 -0700 Subject: [PATCH 35/74] adding settingsLoaded bool check --- interface/src/scripting/Audio.cpp | 5 +++-- interface/src/scripting/Audio.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index caae946116..0a29152c7c 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -174,7 +174,7 @@ void Audio::setPTTDesktop(bool enabled) { _pttDesktop = enabled; } }); - if (!enabled) { + if (!enabled && _settingsLoaded) { // Set to default behavior (unmuted for Desktop) on Push-To-Talk disable. setMutedDesktop(true); } else { @@ -202,7 +202,7 @@ void Audio::setPTTHMD(bool enabled) { _pttHMD = enabled; } }); - if (!enabled) { + if (!enabled && _settingsLoaded) { // Set to default behavior (unmuted for HMD) on Push-To-Talk disable. setMutedHMD(false); } else { @@ -231,6 +231,7 @@ void Audio::loadData() { auto client = DependencyManager::get().data(); QMetaObject::invokeMethod(client, "setMuted", Q_ARG(bool, isMuted()), Q_ARG(bool, false)); + _settingsLoaded = true; } bool Audio::getPTTHMD() const { diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index 00da566b30..f7116ced3a 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -409,6 +409,7 @@ protected: private: + bool _settingsLoaded { false }; float _inputVolume { 1.0f }; float _inputLevel { 0.0f }; float _localInjectorGain { 0.0f }; // in dB From 0d914a695b0bc538bd5ac749a5cac6c4902eee93 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 18 Apr 2019 09:06:02 -0700 Subject: [PATCH 36/74] wip --- libraries/baking/src/ModelBaker.cpp | 1 + libraries/baking/src/ModelBaker.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libraries/baking/src/ModelBaker.cpp b/libraries/baking/src/ModelBaker.cpp index e58ec00afa..d5739c5e34 100644 --- a/libraries/baking/src/ModelBaker.cpp +++ b/libraries/baking/src/ModelBaker.cpp @@ -245,6 +245,7 @@ void ModelBaker::bakeSourceCopy() { baker.run(); _hfmModel = baker.getHFMModel(); + _materialMapping = baker.getMaterialMapping(); dracoMeshes = baker.getDracoMeshes(); dracoMaterialLists = baker.getDracoMaterialLists(); } diff --git a/libraries/baking/src/ModelBaker.h b/libraries/baking/src/ModelBaker.h index d612a0a43a..37909fb6b4 100644 --- a/libraries/baking/src/ModelBaker.h +++ b/libraries/baking/src/ModelBaker.h @@ -87,6 +87,7 @@ private: bool _hasBeenBaked { false }; hfm::Model::Pointer _hfmModel; + MaterialMapping _materialMapping; QSharedPointer _materialBaker; }; From 39d03ce87a54bdc9579656efe2d814453de81fd6 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 18 Apr 2019 19:19:38 +0200 Subject: [PATCH 37/74] Removed magic number --- libraries/render-utils/src/LightStage.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index d35bc21526..524deaaad2 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -162,7 +162,9 @@ void LightStage::Shadow::setLight(graphics::LightPointer light) { } void LightStage::Shadow::setMaxDistance(float value) { - value = std::max(1e-3f, value); + static const auto MINIMUM_MAXDISTANCE = 1e-3f; + + value = std::max(MINIMUM_MAXDISTANCE, value); if (value != _maxDistance) { // This overlaping factor isn't really used directly for blending of shadow cascades. It's // just there to be sure the cascades do overlap. The blending width used is relative From da8f8e0873e9371212e36694798b87bdd9a529fe Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Thu, 18 Apr 2019 14:46:08 -0700 Subject: [PATCH 38/74] real fix --- interface/src/scripting/Audio.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index 0a29152c7c..ce340f2665 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -174,9 +174,11 @@ void Audio::setPTTDesktop(bool enabled) { _pttDesktop = enabled; } }); - if (!enabled && _settingsLoaded) { - // Set to default behavior (unmuted for Desktop) on Push-To-Talk disable. - setMutedDesktop(true); + if (!enabled) { + if (_settingsLoaded) { + // Set to default behavior (unmuted for Desktop) on Push-To-Talk disable. + setMutedDesktop(true); + } } else { // Should be muted when not pushing to talk while PTT is enabled. setMutedDesktop(true); @@ -202,9 +204,11 @@ void Audio::setPTTHMD(bool enabled) { _pttHMD = enabled; } }); - if (!enabled && _settingsLoaded) { - // Set to default behavior (unmuted for HMD) on Push-To-Talk disable. - setMutedHMD(false); + if (!enabled) { + if (_settingsLoaded) { + // Set to default behavior (unmuted for HMD) on Push-To-Talk disable. + setMutedHMD(false); + } } else { // Should be muted when not pushing to talk while PTT is enabled. setMutedHMD(true); @@ -358,11 +362,6 @@ void Audio::onContextChanged() { changed = true; } }); - if (isHMD) { - setMuted(getMutedHMD()); - } else { - setMuted(getMutedDesktop()); - } if (changed) { emit contextChanged(isHMD ? Audio::HMD : Audio::DESKTOP); } From af3d981ad163be12a9d4d66ff7049c04c11067d1 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 18 Apr 2019 17:44:08 -0700 Subject: [PATCH 39/74] Bringing the Luci interface into the new Prop framework and moving some tools there too --- .../utilities/lib/jet/qml/TaskPropView.qml | 35 ++-- .../utilities/lib/prop/PropGroup.qml | 121 +----------- .../utilities/lib/prop/style/PiCanvasIcon.qml | 9 +- .../utilities/lib/prop/style/PiCheckBox.qml | 2 - .../lib/prop/style/PiFolderPanel.qml | 24 +-- .../utilities/render/antialiasing.js | 2 +- .../utilities/render/antialiasing.qml | 182 ------------------ .../utilities/render/deferredLighting.qml | 177 +---------------- scripts/developer/utilities/render/luci.qml | 60 +++--- .../utilities/render/luci/Antialiasing.qml | 176 +++++++++++++++++ .../utilities/render/luci/BoundingBoxes.qml | 84 ++++++++ .../utilities/render/luci/Framebuffer.qml | 69 +++++++ .../utilities/render/luci/ShadingModel.qml | 25 +-- .../utilities/render/luci/ToneMapping.qml | 40 ++++ .../developer/utilities/render/luci/qmldir | 6 +- 15 files changed, 449 insertions(+), 563 deletions(-) delete mode 100644 scripts/developer/utilities/render/antialiasing.qml create mode 100644 scripts/developer/utilities/render/luci/Antialiasing.qml create mode 100644 scripts/developer/utilities/render/luci/BoundingBoxes.qml create mode 100644 scripts/developer/utilities/render/luci/Framebuffer.qml create mode 100644 scripts/developer/utilities/render/luci/ToneMapping.qml diff --git a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml index e53932a9f9..0587352b4e 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml @@ -30,9 +30,10 @@ Prop.PropGroup { property var showProps: true property var showSubs: true - property var jobEnabled: true + property var jobEnabled: rootConfig.getConfig(jobPath).enabled + property var jobCpuTime: rootConfig.getConfig(jobPath).cpuRunTime.toPrecision(3) - property var toggleJobActivation: function() { + property var toggleJobActivation: function() { console.log("the button has been pressed and jobEnabled is " + jobEnabled ) jobEnabled = !jobEnabled; rootConfig.getConfig(jobPath).enabled = jobEnabled; @@ -44,29 +45,31 @@ Prop.PropGroup { id: header Prop.PropLabel { text: root.label - //horizontalAlignment: Text.AlignHCenter + horizontalAlignment: Text.AlignHCenter anchors.left: parent.left - anchors.right: enabledIcon.left + anchors.right: cpuTime.left anchors.verticalCenter: parent.verticalCenter - } + } + Prop.PropLabel { + id: cpuTime + visible: root.jobEnabled + width: 50 + text: jobCpuTime + horizontalAlignment: Text.AlignLeft + anchors.rightMargin: 5 + anchors.right:enabledIcon.right + anchors.verticalCenter: parent.verticalCenter + } Prop.PropCanvasIcon { id: enabledIcon - anchors.right: enabledIcon2.left + anchors.right:parent.right anchors.verticalCenter: parent.verticalCenter filled: root.jobEnabled fillColor: (root.jobEnabled ? global.colorGreenHighlight : global.colorOrangeAccent) icon: 5 iconMouseArea.onClicked: { toggleJobActivation() } } - Prop.PropCanvasIcon { - id: enabledIcon2 - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - filled: root.jobEnabled - fillColor: (root.jobEnabled ? global.colorGreenHighlight : global.colorOrangeAccent) - icon: 7 - iconMouseArea.onClicked: { toggleJobActivation() } - } + } } @@ -78,7 +81,7 @@ Prop.PropGroup { for (var p in props) { propsModel.push({"object": rootConfig.getConfig(jobPath), "property":props[p] }) } - root.updatePropItems(propsModel); + root.updatePropItems(root.propItemsPanel, propsModel); } if (showSubs) { diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 2f15e60a0c..384b50ecad 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -10,123 +10,14 @@ import QtQuick 2.7 -//Item { +// PropGroup is mostly reusing the look and feel of the PropFolderPanel +// It is populated by calling "updatePropItems" +// or adding manually new Items to the "propItemsPanel" PropFolderPanel { Global { id: global } id: root - - // property var label: "group" - - // property alias isUnfold: headerFolderIcon.icon - // property var indentDepth: 0 - //property alias propItemsPanel: _panelFrameData - // property alias propItemsPanel: propItemsContainer - //property var propItemsPanel: propItemsContainer - - panelFrameData: Component { // default is a column - id: groupPanelFrameData - Column { - id: propItemsContainer - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: 0 - anchors.rightMargin: 0 - - clip: true - } - } - - // Panel Header Data Component -/* property Component panelHeaderData: defaultPanelHeaderData - Component { // default is a Label - id: defaultPanelHeaderData - PropLabel { - text: root.label - horizontalAlignment: Text.AlignHCenter - } - } - - // Header Item - Rectangle { - id: header - height: global.slimHeight - anchors.left: parent.left - anchors.right: parent.right - - color: global.colorBackShadow // header of group is darker - - // First in the header, some indentation spacer - Item { - id: indentSpacer - width: (headerFolderIcon.width * root.indentDepth) + global.horizontalMargin // Must be non-zero - height: parent.height - - anchors.verticalCenter: parent.verticalCenter - } - - // Second, the folder button / indicator - Item { - id: headerFolder - anchors.left: indentSpacer.right - width: headerFolderIcon.width * 2 - anchors.verticalCenter: header.verticalCenter - height: parent.height - - PropCanvasIcon { - id: headerFolderIcon - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - fillColor: global.colorOrangeAccent - filled: root.propItemsPanel.height > 4 - iconMouseArea.onClicked: { root.isUnfold = !root.isUnfold } - } - } - - // Next the header container - // by default containing a Label showing the root.label - Loader { - sourceComponent: panelHeaderData - anchors.left: headerFolder.right - anchors.right: header.right - anchors.verticalCenter: header.verticalCenter - height: parent.height - } - } - - // The Panel container - Rectangle { - visible: root.isUnfold - - color: "transparent" - border.color: global.colorBorderLight - border.width: global.valueBorderWidth - radius: global.valueBorderRadius - - anchors.margins: 0 - anchors.left: parent.left - anchors.right: parent.right - anchors.top: header.bottom - anchors.bottom: root.bottom - - Column { - id: propItemsContainer - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: 0 - anchors.rightMargin: 0 - - clip: true - - // Where the propItems are added - } - } - - height: header.height + isUnfold * propItemsContainer.height - anchors.margins: 0 - anchors.left: parent.left - anchors.right: parent.right -*/ + 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: // [ ..., PropItemInfo, ...] @@ -134,7 +25,8 @@ PropFolderPanel { // type: "PropXXXX", object: JSobject, property: "propName" // } // - function updatePropItems(propItemsModel) { + function updatePropItems(propItemsContainer, propItemsModel) { + root.hasContent = false for (var i = 0; i < propItemsModel.length; i++) { var proItem = propItemsModel[i]; // valid object @@ -191,6 +83,7 @@ PropFolderPanel { }) } break; } + root.hasContent = true } else { console.log('Invalid property: ' + JSON.stringify(proItem)); } diff --git a/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml b/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml index 3feed342b8..2fc3ed10ec 100644 --- a/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml +++ b/scripts/developer/utilities/lib/prop/style/PiCanvasIcon.qml @@ -79,12 +79,9 @@ Canvas { context.lineTo(width * 0.75, height * 0.25); context.closePath(); } break; - default: {// Down Arrow - /* context.moveTo(0, height * 0.25); - context.lineTo(width, height * 0.25); - context.lineTo(width / 2, height); - context.closePath();*/ - } + default: { + + } } if (filled) { context.fillStyle = fillColor; diff --git a/scripts/developer/utilities/lib/prop/style/PiCheckBox.qml b/scripts/developer/utilities/lib/prop/style/PiCheckBox.qml index 108a763be3..1e1f03669b 100644 --- a/scripts/developer/utilities/lib/prop/style/PiCheckBox.qml +++ b/scripts/developer/utilities/lib/prop/style/PiCheckBox.qml @@ -20,6 +20,4 @@ HifiControls.CheckBox { //anchors.verticalCenter: root.verticalCenter //width: root.width * global.valueAreaWidthScale height: global.slimHeight - - onCheckedChanged: { root.valueVarSetter(checked); } } \ No newline at end of file diff --git a/scripts/developer/utilities/lib/prop/style/PiFolderPanel.qml b/scripts/developer/utilities/lib/prop/style/PiFolderPanel.qml index b80ab47fc6..d66c0708d3 100644 --- a/scripts/developer/utilities/lib/prop/style/PiFolderPanel.qml +++ b/scripts/developer/utilities/lib/prop/style/PiFolderPanel.qml @@ -17,6 +17,7 @@ Item { property var label: "panel" property alias isUnfold: headerFolderIcon.icon + property alias hasContent: headerFolderIcon.filled property var indentDepth: 0 // Panel Header Data Component @@ -37,7 +38,7 @@ Item { } } - //property alias panelFrameContent: frame._panelFrameData.data + property alias panelFrameContent: _panelFrameData.item // Header Item Rectangle { @@ -45,13 +46,14 @@ Item { height: global.slimHeight anchors.left: parent.left anchors.right: parent.right + anchors.margins: 0 color: global.colorBackShadow // header of group is darker // First in the header, some indentation spacer Item { id: indentSpacer - width: (headerFolderIcon.width * root.indentDepth) + global.horizontalMargin // Must be non-zero + width: (headerFolderIcon.width * root.indentDepth) + global.horizontalMargin // Must be non-zero height: parent.height anchors.verticalCenter: parent.verticalCenter @@ -70,7 +72,6 @@ Item { anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter fillColor: global.colorOrangeAccent - filled: root.frame.height > 4 iconMouseArea.onClicked: { root.isUnfold = !root.isUnfold } } } @@ -81,6 +82,7 @@ Item { sourceComponent: panelHeaderData anchors.left: headerFolder.right anchors.right: header.right + anchors.rightMargin: global.horizontalMargin * 2 anchors.verticalCenter: header.verticalCenter height: parent.height } @@ -104,29 +106,17 @@ Item { // Next the panel frame data Loader { + id: _panelFrameData sourceComponent: panelFrameData anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 0 anchors.rightMargin: 0 - id: _panelFrameData clip: true } - - /* Column { - id: propItemsContainer - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: 0 - anchors.rightMargin: 0 - - clip: true - - // Where the propItems are added - }*/ } - height: header.height + isUnfold * _panelFrameData.height + height: header.height + isUnfold * _panelFrameData.item.height anchors.margins: 0 anchors.left: parent.left anchors.right: parent.right diff --git a/scripts/developer/utilities/render/antialiasing.js b/scripts/developer/utilities/render/antialiasing.js index e915d75e93..5484565b36 100644 --- a/scripts/developer/utilities/render/antialiasing.js +++ b/scripts/developer/utilities/render/antialiasing.js @@ -13,7 +13,7 @@ (function() { var TABLET_BUTTON_NAME = "TAA"; - var QMLAPP_URL = Script.resolvePath("./antialiasing.qml"); + var QMLAPP_URL = Script.resolvePath("./luci/Antialiasing.qml"); var onLuciScreen = false; diff --git a/scripts/developer/utilities/render/antialiasing.qml b/scripts/developer/utilities/render/antialiasing.qml deleted file mode 100644 index 5abfd30935..0000000000 --- a/scripts/developer/utilities/render/antialiasing.qml +++ /dev/null @@ -1,182 +0,0 @@ -// -// Antialiasing.qml -// -// Created by Sam Gateau on 8/14/2017 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.3 - -import stylesUit 1.0 -import controlsUit 1.0 as HifiControls - -import "configSlider" -import "../lib/plotperf" - -Item { -Rectangle { - id: root; - - HifiConstants { id: hifi; } - color: hifi.colors.baseGray; - - Column { - id: antialiasing - spacing: 20 - padding: 10 - - Column{ - spacing: 10 - - Row { - spacing: 10 - id: fxaaOnOff - property bool debugFXAA: false - HifiControls.Button { - function getTheText() { - if (Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff) { - return "FXAA" - } else { - return "TAA" - } - } - text: getTheText() - onClicked: { - var onOff = !Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff; - if (onOff) { - Render.getConfig("RenderMainView.JitterCam").none(); - Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = true; - } else { - Render.getConfig("RenderMainView.JitterCam").play(); - Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = false; - } - - } - } - } - Separator {} - Row { - spacing: 10 - - HifiControls.Button { - text: { - var state = 2 - (Render.getConfig("RenderMainView.JitterCam").freeze * 1 - Render.getConfig("RenderMainView.JitterCam").stop * 2); - if (state === 2) { - return "Jitter" - } else if (state === 1) { - return "Paused at " + Render.getConfig("RenderMainView.JitterCam").index + "" - } else { - return "No Jitter" - } - } - onClicked: { Render.getConfig("RenderMainView.JitterCam").cycleStopPauseRun(); } - } - HifiControls.Button { - text: "<" - onClicked: { Render.getConfig("RenderMainView.JitterCam").prev(); } - } - HifiControls.Button { - text: ">" - onClicked: { Render.getConfig("RenderMainView.JitterCam").next(); } - } - } - Separator {} - HifiControls.CheckBox { - boxSize: 20 - text: "Constrain color" - checked: Render.getConfig("RenderMainView.Antialiasing")["constrainColor"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["constrainColor"] = checked } - } - ConfigSlider { - label: qsTr("Covariance gamma") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") - property: "covarianceGamma" - max: 1.5 - min: 0.5 - height: 38 - } - Separator {} - HifiControls.CheckBox { - boxSize: 20 - text: "Feedback history color" - checked: Render.getConfig("RenderMainView.Antialiasing")["feedbackColor"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["feedbackColor"] = checked } - } - - ConfigSlider { - label: qsTr("Source blend") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") - property: "blend" - max: 1.0 - min: 0.0 - height: 38 - } - - ConfigSlider { - label: qsTr("Post sharpen") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") - property: "sharpen" - max: 1.0 - min: 0.0 - } - Separator {} - Row { - - spacing: 10 - HifiControls.CheckBox { - boxSize: 20 - text: "Debug" - checked: Render.getConfig("RenderMainView.Antialiasing")["debug"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["debug"] = checked } - } - HifiControls.CheckBox { - boxSize: 20 - text: "Show Debug Cursor" - checked: Render.getConfig("RenderMainView.Antialiasing")["showCursorPixel"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["showCursorPixel"] = checked } - } - } - ConfigSlider { - label: qsTr("Debug Region <") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") - property: "debugX" - max: 1.0 - min: 0.0 - } - HifiControls.CheckBox { - boxSize: 20 - text: "Closest Fragment" - checked: Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"] = checked } - } - ConfigSlider { - label: qsTr("Debug Velocity Threshold [pix]") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") - property: "debugShowVelocityThreshold" - max: 50 - min: 0.0 - height: 38 - } - ConfigSlider { - label: qsTr("Debug Orb Zoom") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") - property: "debugOrbZoom" - max: 32.0 - min: 1.0 - height: 38 - } - } - } -} -} diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 63c2af1b0f..80ca8b09e1 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -29,57 +29,16 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.margins: hifi.dimensions.contentMargin.x - //padding: hifi.dimensions.contentMargin.x + + HifiControls.Label { text: "Shading" } - ShadingModel { + ShadingModel {} - } - Separator {} - Column { - anchors.left: parent.left - anchors.right: parent.right - spacing: 5 - Repeater { - model: [ "Tone Mapping Exposure:ToneMapping:exposure:5.0:-5.0" - ] - ConfigSlider { - label: qsTr(modelData.split(":")[0]) - integral: false - config: render.mainViewTask.getConfig(modelData.split(":")[1]) - property: modelData.split(":")[2] - max: modelData.split(":")[3] - min: modelData.split(":")[4] + Separator {} + ToneMapping {} - anchors.left: parent.left - anchors.right: parent.right - } - } - Item { - height: childrenRect.height - anchors.left: parent.left - anchors.right: parent.right - - HifiControls.Label { - text: "Tone Mapping Curve" - anchors.left: parent.left - } - - ComboBox { - anchors.right: parent.right - currentIndex: 1 - model: [ - "RGB", - "SRGB", - "Reinhard", - "Filmic", - ] - width: 200 - onCurrentIndexChanged: { render.mainViewTask.getConfig("ToneMapping")["curve"] = currentIndex; } - } - } - } Separator {} Column { anchors.left: parent.left @@ -102,133 +61,11 @@ Rectangle { } } Separator {} + Framebuffer {} - Item { - height: childrenRect.height - anchors.left: parent.left - anchors.right: parent.right - - id: framebuffer - - HifiControls.Label { - text: "Debug Framebuffer" - anchors.left: parent.left - } - - property var config: render.mainViewTask.getConfig("DebugDeferredBuffer") - - function setDebugMode(mode) { - framebuffer.config.enabled = (mode != 0); - framebuffer.config.mode = mode; - } - - ComboBox { - anchors.right: parent.right - currentIndex: 0 - model: ListModel { - id: cbItemsFramebuffer - ListElement { text: "Off"; color: "Yellow" } - ListElement { text: "Depth"; color: "Green" } - ListElement { text: "Albedo"; color: "Yellow" } - ListElement { text: "Normal"; color: "White" } - ListElement { text: "Roughness"; color: "White" } - ListElement { text: "Metallic"; color: "White" } - ListElement { text: "Emissive"; color: "White" } - ListElement { text: "Unlit"; color: "White" } - ListElement { text: "Occlusion"; color: "White" } - ListElement { text: "Lightmap"; color: "White" } - ListElement { text: "Scattering"; color: "White" } - ListElement { text: "Lighting"; color: "White" } - ListElement { text: "Shadow Cascade 0"; color: "White" } - ListElement { text: "Shadow Cascade 1"; color: "White" } - ListElement { text: "Shadow Cascade 2"; color: "White" } - ListElement { text: "Shadow Cascade 3"; color: "White" } - ListElement { text: "Shadow Cascade Indices"; color: "White" } - ListElement { text: "Linear Depth"; color: "White" } - ListElement { text: "Half Linear Depth"; color: "White" } - ListElement { text: "Half Normal"; color: "White" } - ListElement { text: "Mid Curvature"; color: "White" } - ListElement { text: "Mid Normal"; color: "White" } - ListElement { text: "Low Curvature"; color: "White" } - ListElement { text: "Low Normal"; color: "White" } - ListElement { text: "Curvature Occlusion"; color: "White" } - ListElement { text: "Debug Scattering"; color: "White" } - ListElement { text: "Ambient Occlusion"; color: "White" } - ListElement { text: "Ambient Occlusion Blurred"; color: "White" } - ListElement { text: "Ambient Occlusion Normal"; color: "White" } - ListElement { text: "Velocity"; color: "White" } - ListElement { text: "Custom"; color: "White" } - } - width: 200 - onCurrentIndexChanged: { framebuffer.setDebugMode(currentIndex) } - } - } - Separator {} - Row { - spacing: 5 - Column { - spacing: 5 + BoundingBoxes { - HifiControls.CheckBox { - boxSize: 20 - text: "Opaques" - checked: render.mainViewTask.getConfig("DrawOpaqueBounds")["enabled"] - onCheckedChanged: { render.mainViewTask.getConfig("DrawOpaqueBounds")["enabled"] = checked } - } - HifiControls.CheckBox { - boxSize: 20 - text: "Transparents" - checked: render.mainViewTask.getConfig("DrawTransparentBounds")["enabled"] - onCheckedChanged: { render.mainViewTask.getConfig("DrawTransparentBounds")["enabled"] = checked } - } - HifiControls.CheckBox { - boxSize: 20 - text: "Opaques in Front" - checked: render.mainViewTask.getConfig("DrawOverlayInFrontOpaqueBounds")["enabled"] - onCheckedChanged: { render.mainViewTask.getConfig("DrawOverlayInFrontOpaqueBounds")["enabled"] = checked } - } - HifiControls.CheckBox { - boxSize: 20 - text: "Transparents in Front" - checked: render.mainViewTask.getConfig("DrawOverlayInFrontTransparentBounds")["enabled"] - onCheckedChanged: { render.mainViewTask.getConfig("DrawOverlayInFrontTransparentBounds")["enabled"] = checked } - } - HifiControls.CheckBox { - boxSize: 20 - text: "Opaques in HUD" - checked: render.mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"] - onCheckedChanged: { render.mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"] = checked } - } - - } - Column { - spacing: 5 - HifiControls.CheckBox { - boxSize: 20 - text: "Metas" - checked: render.mainViewTask.getConfig("DrawMetaBounds")["enabled"] - onCheckedChanged: { render.mainViewTask.getConfig("DrawMetaBounds")["enabled"] = checked } - } - HifiControls.CheckBox { - boxSize: 20 - text: "Lights" - checked: render.mainViewTask.getConfig("DrawLightBounds")["enabled"] - onCheckedChanged: { render.mainViewTask.getConfig("DrawLightBounds")["enabled"] = checked; } - } - HifiControls.CheckBox { - boxSize: 20 - text: "Zones" - checked: render.mainViewTask.getConfig("DrawZones")["enabled"] - onCheckedChanged: { render.mainViewTask.getConfig("ZoneRenderer")["enabled"] = checked; render.mainViewTask.getConfig("DrawZones")["enabled"] = checked; } - } - HifiControls.CheckBox { - boxSize: 20 - text: "Transparents in HUD" - checked: render.mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"] - onCheckedChanged: { render.mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"] = checked } - } - } } Separator {} Row { diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index 7bce087fda..6ceee9a8d0 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -33,53 +33,43 @@ Rectangle { Column { width: render.width Prop.PropFolderPanel { - id: "shadingModel" label: "Shading Model" panelFrameData: Component { - ShadingModel { - } + ShadingModel {} } } - /* Prop.PropEnum { - label: "Tone Curve" - object: render.mainViewTask.getConfig("ToneMapping") - property: "curve" - enums: [ - "RGB", - "SRGB", - "Reinhard", - "Filmic", - ] - anchors.left: parent.left - anchors.right: parent.right - } */ - Jet.TaskPropView { - id: "theView" - jobPath: "RenderMainView" - label: "Le Render Main View" - - anchors.left: parent.left - anchors.right: parent.right + Prop.PropFolderPanel { + label: "Bounding Boxes" + panelFrameData: Component { + BoundingBoxes {} + } } - Jet.TaskPropView { - id: "the" - jobPath: "RenderMainView.RenderDeferredTask" - label: "Le Render Deferred Job" - - anchors.left: parent.left - anchors.right: parent.right + Prop.PropFolderPanel { + label: "Framebuffer" + panelFrameData: Component { + Framebuffer {} + } + } + Prop.PropFolderPanel { + label: "Tone Mapping" + panelFrameData: Component { + ToneMapping {} + } + } + Prop.PropFolderPanel { + label: "Antialiasing" + panelFrameData: Component { + Antialiasing {} + } } Jet.TaskPropView { id: "le" jobPath: "" label: "Le Render Engine" - anchors.left: parent.left - anchors.right: parent.right + // anchors.left: parent.left + // anchors.right: parent.right } } } - - Component.onCompleted: { - } } \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci/Antialiasing.qml b/scripts/developer/utilities/render/luci/Antialiasing.qml new file mode 100644 index 0000000000..e29bca43eb --- /dev/null +++ b/scripts/developer/utilities/render/luci/Antialiasing.qml @@ -0,0 +1,176 @@ +// +// Antialiasing.qml +// +// Created by Sam Gateau on 8/14/2017 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import stylesUit 1.0 +import controlsUit 1.0 as HifiControls + +import "../configSlider" +import "../../lib/plotperf" + + +Column{ + HifiConstants { id: hifi; } + + id: antialiasing + padding: 10 + anchors.left: parent.left + anchors.right: parent.right + + spacing: 10 + + Row { + spacing: 10 + id: fxaaOnOff + property bool debugFXAA: false + HifiControls.Button { + function getTheText() { + if (Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff) { + return "FXAA" + } else { + return "TAA" + } + } + text: getTheText() + onClicked: { + var onOff = !Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff; + if (onOff) { + Render.getConfig("RenderMainView.JitterCam").none(); + Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = true; + } else { + Render.getConfig("RenderMainView.JitterCam").play(); + Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = false; + } + + } + } + } + Separator {} + Row { + spacing: 10 + + HifiControls.Button { + text: { + var state = 2 - (Render.getConfig("RenderMainView.JitterCam").freeze * 1 - Render.getConfig("RenderMainView.JitterCam").stop * 2); + if (state === 2) { + return "Jitter" + } else if (state === 1) { + return "Paused at " + Render.getConfig("RenderMainView.JitterCam").index + "" + } else { + return "No Jitter" + } + } + onClicked: { Render.getConfig("RenderMainView.JitterCam").cycleStopPauseRun(); } + } + HifiControls.Button { + text: "<" + onClicked: { Render.getConfig("RenderMainView.JitterCam").prev(); } + } + HifiControls.Button { + text: ">" + onClicked: { Render.getConfig("RenderMainView.JitterCam").next(); } + } + } + Separator {} + HifiControls.CheckBox { + boxSize: 20 + text: "Constrain color" + checked: Render.getConfig("RenderMainView.Antialiasing")["constrainColor"] + onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["constrainColor"] = checked } + } + ConfigSlider { + label: qsTr("Covariance gamma") + integral: false + config: Render.getConfig("RenderMainView.Antialiasing") + property: "covarianceGamma" + max: 1.5 + min: 0.5 + height: 38 + } + Separator {} + HifiControls.CheckBox { + boxSize: 20 + text: "Feedback history color" + checked: Render.getConfig("RenderMainView.Antialiasing")["feedbackColor"] + onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["feedbackColor"] = checked } + } + + ConfigSlider { + label: qsTr("Source blend") + integral: false + config: Render.getConfig("RenderMainView.Antialiasing") + property: "blend" + max: 1.0 + min: 0.0 + height: 38 + } + + ConfigSlider { + label: qsTr("Post sharpen") + integral: false + config: Render.getConfig("RenderMainView.Antialiasing") + property: "sharpen" + max: 1.0 + min: 0.0 + } + Separator {} + Row { + + spacing: 10 + HifiControls.CheckBox { + boxSize: 20 + text: "Debug" + checked: Render.getConfig("RenderMainView.Antialiasing")["debug"] + onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["debug"] = checked } + } + HifiControls.CheckBox { + boxSize: 20 + text: "Show Debug Cursor" + checked: Render.getConfig("RenderMainView.Antialiasing")["showCursorPixel"] + onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["showCursorPixel"] = checked } + } + } + ConfigSlider { + label: qsTr("Debug Region <") + integral: false + config: Render.getConfig("RenderMainView.Antialiasing") + property: "debugX" + max: 1.0 + min: 0.0 + } + HifiControls.CheckBox { + boxSize: 20 + text: "Closest Fragment" + checked: Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"] + onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"] = checked } + } + ConfigSlider { + label: qsTr("Debug Velocity Threshold [pix]") + integral: false + config: Render.getConfig("RenderMainView.Antialiasing") + property: "debugShowVelocityThreshold" + max: 50 + min: 0.0 + height: 38 + } + ConfigSlider { + label: qsTr("Debug Orb Zoom") + integral: false + config: Render.getConfig("RenderMainView.Antialiasing") + property: "debugOrbZoom" + max: 32.0 + min: 1.0 + height: 38 + } +} + diff --git a/scripts/developer/utilities/render/luci/BoundingBoxes.qml b/scripts/developer/utilities/render/luci/BoundingBoxes.qml new file mode 100644 index 0000000000..636267729c --- /dev/null +++ b/scripts/developer/utilities/render/luci/BoundingBoxes.qml @@ -0,0 +1,84 @@ +// +// BoundingBoxes.qml +// +// Created by Sam Gateau on 4/18/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +import "../../lib/prop" as Prop + +Column { + + id: root; + + property var mainViewTask: Render.getConfig("RenderMainView") + + spacing: 5 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x + + Row { + anchors.left: parent.left + anchors.right: parent.right + + spacing: 5 + Column { + spacing: 5 + + Prop.PropCheckBox { + text: "Opaques" + checked: root.mainViewTask.getConfig("DrawOpaqueBounds")["enabled"] + onCheckedChanged: { root.mainViewTask.getConfig("DrawOpaqueBounds")["enabled"] = checked } + } + Prop.PropCheckBox { + text: "Transparents" + checked: root.mainViewTask.getConfig("DrawTransparentBounds")["enabled"] + onCheckedChanged: { root.mainViewTask.getConfig("DrawTransparentBounds")["enabled"] = checked } + } + Prop.PropCheckBox { + text: "Metas" + checked: root.mainViewTask.getConfig("DrawMetaBounds")["enabled"] + onCheckedChanged: { root.mainViewTask.getConfig("DrawMetaBounds")["enabled"] = checked } + } + Prop.PropCheckBox { + text: "Lights" + checked: root.mainViewTask.getConfig("DrawLightBounds")["enabled"] + onCheckedChanged: { root.mainViewTask.getConfig("DrawLightBounds")["enabled"] = checked; } + } + Prop.PropCheckBox { + text: "Zones" + checked: root.mainViewTask.getConfig("DrawZones")["enabled"] + onCheckedChanged: { root.mainViewTask.getConfig("ZoneRenderer")["enabled"] = checked; root.mainViewTask.getConfig("DrawZones")["enabled"] = checked; } + } + } + Column { + spacing: 5 + Prop.PropCheckBox { + text: "Opaques in Front" + checked: root.mainViewTask.getConfig("DrawOverlayInFrontOpaqueBounds")["enabled"] + onCheckedChanged: { root.mainViewTask.getConfig("DrawOverlayInFrontOpaqueBounds")["enabled"] = checked } + } + Prop.PropCheckBox { + text: "Transparents in Front" + checked: root.mainViewTask.getConfig("DrawOverlayInFrontTransparentBounds")["enabled"] + onCheckedChanged: { root.mainViewTask.getConfig("DrawOverlayInFrontTransparentBounds")["enabled"] = checked } + } + Prop.PropCheckBox { + text: "Opaques in HUD" + checked: root.mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"] + onCheckedChanged: { root.mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"] = checked } + } + Prop.PropCheckBox { + text: "Transparents in HUD" + checked: root.mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"] + onCheckedChanged: { root.mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"] = checked } + } + } + } +} diff --git a/scripts/developer/utilities/render/luci/Framebuffer.qml b/scripts/developer/utilities/render/luci/Framebuffer.qml new file mode 100644 index 0000000000..89d5e59002 --- /dev/null +++ b/scripts/developer/utilities/render/luci/Framebuffer.qml @@ -0,0 +1,69 @@ +// +// Framebuffer.qml +// +// Created by Sam Gateau on 4/18/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +import "../../lib/prop" as Prop + +Column { + anchors.left: parent.left + anchors.right: parent.right + + id: framebuffer + + property var config: Render.getConfig("RenderMainView.DebugDeferredBuffer") + + function setDebugMode(mode) { + framebuffer.config.enabled = (mode != 0); + framebuffer.config.mode = mode; + } + + Prop.PropEnum { + label: "Debug Buffer" + object: config + property: "mode" + valueVar: 0 + enums: [ + "Off", + "Depth", + "Albedo", + "Normal", + "Roughness", + "Metallic", + "Emissive", + "Unlit", + "Occlusion", + "Lightmap", + "Scattering", + "Lighting", + "Shadow Cascade 0", + "Shadow Cascade 1", + "Shadow Cascade 2", + "Shadow Cascade 3", + "Shadow Cascade Indices", + "Linear Depth", + "Half Linear Depth", + "Half Normal", + "Mid Curvature", + "Mid Normal", + "Low Curvature", + "Low Normal", + "Curvature Occlusion", + "Debug Scattering", + "Ambient Occlusion", + "Ambient Occlusion Blurred", + "Ambient Occlusion Normal", + "Velocity", + "Custom", + ] + + valueVarSetter: function (mode) { framebuffer.setDebugMode(mode) } + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci/ShadingModel.qml b/scripts/developer/utilities/render/luci/ShadingModel.qml index 2c16492e80..78ca7f1740 100644 --- a/scripts/developer/utilities/render/luci/ShadingModel.qml +++ b/scripts/developer/utilities/render/luci/ShadingModel.qml @@ -10,18 +10,8 @@ import QtQuick 2.7 -import stylesUit 1.0 -import controlsUit 1.0 as HifiControls - -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.3 - -import stylesUit 1.0 -import controlsUit 1.0 as HifiControls - import "../../lib/prop" as Prop - Column { id: shadingModel; @@ -32,9 +22,6 @@ Column { anchors.left: parent.left anchors.right: parent.right anchors.margins: hifi.dimensions.contentMargin.x - HifiControls.Label { - text: "Shading" - } Row { anchors.left: parent.left anchors.right: parent.right @@ -54,8 +41,8 @@ Column { ] Prop.PropCheckBox { text: modelData.split(":")[0] - checked: render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] - onCheckedChanged: { render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } + checked: shadingModel.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] + onCheckedChanged: { shadingModel.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } } } } @@ -76,8 +63,8 @@ Column { ] Prop.PropCheckBox { text: modelData.split(":")[0] - checked: render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] - onCheckedChanged: { render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } + checked: shadingModel.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] + onCheckedChanged: { shadingModel.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } } } } @@ -96,8 +83,8 @@ Column { ] Prop.PropCheckBox { text: modelData.split(":")[0] - checked: render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] - onCheckedChanged: { render.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } + checked: shadingModel.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] + onCheckedChanged: { shadingModel.mainViewTask.getConfig(modelData.split(":")[1])[modelData.split(":")[2]] = checked } } } } diff --git a/scripts/developer/utilities/render/luci/ToneMapping.qml b/scripts/developer/utilities/render/luci/ToneMapping.qml new file mode 100644 index 0000000000..a76990e37c --- /dev/null +++ b/scripts/developer/utilities/render/luci/ToneMapping.qml @@ -0,0 +1,40 @@ +// +// ToneMapping.qml +// +// Created by Sam Gateau on 4/17/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.7 + +import "../../lib/prop" as Prop + +Column { + anchors.left: parent.left + anchors.right: parent.right + Prop.PropScalar { + label: "Exposure" + object: Render.getConfig("RenderMainView.ToneMapping") + property: "exposure" + min: -4 + max: 4 + anchors.left: parent.left + anchors.right: parent.right + } + Prop.PropEnum { + label: "Tone Curve" + object: Render.getConfig("RenderMainView.ToneMapping") + property: "curve" + enums: [ + "RGB", + "SRGB", + "Reinhard", + "Filmic", + ] + anchors.left: parent.left + anchors.right: parent.right + } +} diff --git a/scripts/developer/utilities/render/luci/qmldir b/scripts/developer/utilities/render/luci/qmldir index cf63b1c2b7..c88dfee714 100644 --- a/scripts/developer/utilities/render/luci/qmldir +++ b/scripts/developer/utilities/render/luci/qmldir @@ -1,2 +1,6 @@ -ShadingModel 1.0 ShadingModel.qml \ No newline at end of file +ShadingModel 1.0 ShadingModel.qml +ToneMapping 1.0 ToneMapping.qml +BoundingBoxes 1.0 BoundingBoxes.qml +Framebuffer 1.0 Framebuffer.qml +Antialiasing 1.0 Antialiasing.qml \ No newline at end of file From 7d412f9109299331472836edacb3d036af15b631 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 19 Apr 2019 11:03:43 +0200 Subject: [PATCH 40/74] Simplified material binding in shadow mode. Added opacity mask to shadow fade. Adjusted default bias. --- .../src/RenderableMaterialEntityItem.cpp | 8 +-- .../src/RenderableShapeEntityItem.cpp | 3 +- .../src/graphics/MaterialTextures.slh | 7 --- .../render-utils/src/MeshPartPayload.cpp | 11 +--- .../render-utils/src/RenderPipelines.cpp | 61 +++++++------------ libraries/render-utils/src/RenderPipelines.h | 6 +- libraries/render-utils/src/RenderShadowTask.h | 4 +- libraries/render-utils/src/model_shadow.slf | 10 ++- .../render-utils/src/model_shadow_fade.slf | 15 ++++- 9 files changed, 50 insertions(+), 75 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 01d1098daa..9a634a85ad 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -313,11 +313,9 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { batch.setModelTransform(renderTransform); - if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) { - drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true); - - // bind the material - RenderPipelines::bindMaterial(drawMaterial, batch, args->_enableTexturing); + drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true); + // bind the material + if (RenderPipelines::bindMaterial(drawMaterial, batch, args->_renderMode, args->_enableTexturing)) { args->_details._materialSwitches++; } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index d859d4b739..2548ae5914 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -291,8 +291,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); } } else { - if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) { - RenderPipelines::bindMaterials(materials, batch, args->_enableTexturing); + if (RenderPipelines::bindMaterials(materials, batch, args->_renderMode, args->_enableTexturing)) { args->_details._materialSwitches++; } diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index 16c7f0e211..92e76e5736 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -149,13 +149,6 @@ float fetchScatteringMap(vec2 uv) { <@endfunc@> -<@func fetchMaterialAlbedoTextureCoord0(matKey, texcoord0, albedo)@> - if (getTexMapArray()._materialParams.y != 1.0 && clamp(<$texcoord0$>, vec2(0.0), vec2(1.0)) != <$texcoord0$>) { - discard; - } - vec4 <$albedo$> = fetchAlbedoMap(<$texcoord0$>); -<@endfunc@> - <@func fetchMaterialTexturesCoord0(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, scattering)@> if (getTexMapArray()._materialParams.y != 1.0 && clamp(<$texcoord0$>, vec2(0.0), vec2(1.0)) != <$texcoord0$>) { discard; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 9470f11d59..7be5f93a95 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -154,8 +154,7 @@ void MeshPartPayload::render(RenderArgs* args) { bindMesh(batch); // apply material properties - if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) { - RenderPipelines::bindMaterials(_drawMaterials, batch, args->_enableTexturing); + if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { args->_details._materialSwitches++; } @@ -434,13 +433,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { } // apply material properties - if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) { - RenderPipelines::bindMaterials(_drawMaterials, batch, args->_enableTexturing); - args->_details._materialSwitches++; - } else { - // We might have an opacity mask so we need to bind the albedo texture and material which might hold - // the alpha mask channel - RenderPipelines::bindMaterialsOpacityMask(_drawMaterials, batch, args->_enableTexturing); + if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { args->_details._materialSwitches++; } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index ba0a079c7f..cd4d787f0e 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -373,10 +373,10 @@ void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state, con gpu::Shader::createProgram(deformed_model_shadow_fade_dq), state, extraBatchSetter, itemSetter); } -void RenderPipelines::bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, bool enableTextures) { +bool RenderPipelines::bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures) { graphics::MultiMaterial multiMaterial; multiMaterial.push(graphics::MaterialLayer(material, 0)); - bindMaterials(multiMaterial, batch, enableTextures); + return bindMaterials(multiMaterial, batch, renderMode, enableTextures); } void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial) { @@ -730,17 +730,21 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial multiMaterial.setInitialized(); } -static gpu::TextureTablePointer defaultMaterialTextures = std::make_shared(); - -void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures) { +bool RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures) { if (multiMaterial.shouldUpdate()) { updateMultiMaterial(multiMaterial); } auto textureCache = DependencyManager::get(); + static gpu::TextureTablePointer defaultMaterialTextures = std::make_shared(); + static gpu::BufferView defaultMaterialSchema; + static std::once_flag once; std::call_once(once, [textureCache] { + graphics::MultiMaterial::Schema schema; + defaultMaterialSchema = gpu::BufferView(std::make_shared(sizeof(schema), (const gpu::Byte*) &schema, sizeof(schema))); + defaultMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture()); defaultMaterialTextures->setTexture(gr::Texture::MaterialMetallic, textureCache->getBlackTexture()); defaultMaterialTextures->setTexture(gr::Texture::MaterialRoughness, textureCache->getWhiteTexture()); @@ -750,49 +754,26 @@ void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu: // MaterialEmissiveLightmap has to be set later }); - auto& schemaBuffer = multiMaterial.getSchemaBuffer(); - batch.setUniformBuffer(gr::Buffer::Material, schemaBuffer); - if (enableTextures) { - batch.setResourceTextureTable(multiMaterial.getTextureTable()); - } else { - auto key = multiMaterial.getMaterialKey(); - if (key.isLightmapMap()) { - defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getBlackTexture()); - } else if (key.isEmissiveMap()) { - defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getGrayTexture()); - } - batch.setResourceTextureTable(defaultMaterialTextures); - } -} - -static gpu::BufferView defaultMaterialSchema; - -void RenderPipelines::bindMaterialsOpacityMask(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures) { - if (multiMaterial.shouldUpdate()) { - updateMultiMaterial(multiMaterial); - } - - if (multiMaterial.getMaterialKey().isOpacityMaskMap()) { - auto textureCache = DependencyManager::get(); - - static std::once_flag once; - std::call_once(once, [textureCache] { - defaultMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture()); - }); - + // For shadows, we only need opacity mask information + if (renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE || multiMaterial.getMaterialKey().isOpacityMaskMap()) { auto& schemaBuffer = multiMaterial.getSchemaBuffer(); batch.setUniformBuffer(gr::Buffer::Material, schemaBuffer); - if (enableTextures) { batch.setResourceTextureTable(multiMaterial.getTextureTable()); } else { + auto key = multiMaterial.getMaterialKey(); + if (key.isLightmapMap()) { + defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getBlackTexture()); + } else if (key.isEmissiveMap()) { + defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getGrayTexture()); + } batch.setResourceTextureTable(defaultMaterialTextures); } + return true; } else { - if (defaultMaterialSchema._buffer == nullptr) { - graphics::MultiMaterial::Schema schema; - defaultMaterialSchema = gpu::BufferView(std::make_shared(sizeof(schema), (const gpu::Byte*) &schema, sizeof(schema))); - } + batch.setResourceTextureTable(defaultMaterialTextures); batch.setUniformBuffer(gr::Buffer::Material, defaultMaterialSchema); + return false; } } + diff --git a/libraries/render-utils/src/RenderPipelines.h b/libraries/render-utils/src/RenderPipelines.h index 4a99b21e74..5b04de08b6 100644 --- a/libraries/render-utils/src/RenderPipelines.h +++ b/libraries/render-utils/src/RenderPipelines.h @@ -12,13 +12,13 @@ #define hifi_RenderPipelines_h #include +#include class RenderPipelines { public: - static void bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, bool enableTextures); static void updateMultiMaterial(graphics::MultiMaterial& multiMaterial); - static void bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures); - static void bindMaterialsOpacityMask(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures); + static bool bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures); + static bool bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures); }; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 1cfa786e43..ef469a7247 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -93,8 +93,8 @@ public: float constantBias1{ 0.15f }; float constantBias2{ 0.175f }; float constantBias3{ 0.2f }; - float slopeBias0{ 0.6f }; - float slopeBias1{ 0.6f }; + float slopeBias0{ 0.4f }; + float slopeBias1{ 0.45f }; float slopeBias2{ 0.65f }; float slopeBias3{ 0.7f }; diff --git a/libraries/render-utils/src/model_shadow.slf b/libraries/render-utils/src/model_shadow.slf index 956ece4923..6d8dfb7e2a 100644 --- a/libraries/render-utils/src/model_shadow.slf +++ b/libraries/render-utils/src/model_shadow.slf @@ -23,13 +23,11 @@ layout(location=0) out vec4 _fragColor; void main(void) { Material mat = getMaterial(); BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> - if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { - float opacity = 1.0; - <$fetchMaterialAlbedoTextureCoord0(matKey, _texCoord0, albedoTex)$> - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - } + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; // pass-through to set z-buffer _fragColor = vec4(1.0, 1.0, 1.0, 0.0); diff --git a/libraries/render-utils/src/model_shadow_fade.slf b/libraries/render-utils/src/model_shadow_fade.slf index 210b5482c8..1f94d4a0ac 100644 --- a/libraries/render-utils/src/model_shadow_fade.slf +++ b/libraries/render-utils/src/model_shadow_fade.slf @@ -9,13 +9,18 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - +<@include graphics/Material.slh@> +<@include graphics/MaterialTextures.slh@> <@include render-utils/ShaderConstants.h@> +<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + <@include Fade.slh@> <$declareFadeFragment()$> layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; +#define _texCoord0 _texCoord01.xy layout(location=0) out vec4 _fragColor; @@ -24,6 +29,14 @@ void main(void) { <$fetchFadeObjectParams(fadeParams)$> applyFadeClip(fadeParams, _positionWS.xyz); + Material mat = getMaterial(); + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + // pass-through to set z-buffer _fragColor = vec4(1.0, 1.0, 1.0, 0.0); } From 9065a032bde58b816aa688c594b7e7f2af152a76 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Thu, 18 Apr 2019 14:46:08 -0700 Subject: [PATCH 41/74] real fix From 38115b0c09461fe7b1f8572c070dc72fc9df653a Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Thu, 18 Apr 2019 21:00:15 -0700 Subject: [PATCH 42/74] simplify PTT logic --- interface/src/scripting/Audio.cpp | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index ce340f2665..bceafc3c42 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -174,16 +174,10 @@ void Audio::setPTTDesktop(bool enabled) { _pttDesktop = enabled; } }); - if (!enabled) { - if (_settingsLoaded) { - // Set to default behavior (unmuted for Desktop) on Push-To-Talk disable. - setMutedDesktop(true); - } - } else { - // Should be muted when not pushing to talk while PTT is enabled. + if (enabled || _settingsLoaded) { + // Set to default behavior (muted for Desktop) on Push-To-Talk disable or when enabled. Settings also need to be loaded. setMutedDesktop(true); } - if (changed) { emit pushToTalkChanged(enabled); emit pushToTalkDesktopChanged(enabled); @@ -204,14 +198,9 @@ void Audio::setPTTHMD(bool enabled) { _pttHMD = enabled; } }); - if (!enabled) { - if (_settingsLoaded) { - // Set to default behavior (unmuted for HMD) on Push-To-Talk disable. - setMutedHMD(false); - } - } else { - // Should be muted when not pushing to talk while PTT is enabled. - setMutedHMD(true); + if (enabled || _settingsLoaded) { + // Set to default behavior (unmuted for HMD) on Push-To-Talk disable or muted for when PTT is enabled. + setMutedHMD(enabled); } if (changed) { From 080cb36170036b2a51750b875956788ea94b15d3 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 19 Apr 2019 12:12:22 -0700 Subject: [PATCH 43/74] bake existing materialMap --- libraries/baking/src/MaterialBaker.cpp | 4 ++ libraries/baking/src/MaterialBaker.h | 3 + libraries/baking/src/ModelBaker.cpp | 89 +++++++++++++++++++------- libraries/baking/src/ModelBaker.h | 5 ++ 4 files changed, 78 insertions(+), 23 deletions(-) diff --git a/libraries/baking/src/MaterialBaker.cpp b/libraries/baking/src/MaterialBaker.cpp index 79e31014fd..85e203a2cb 100644 --- a/libraries/baking/src/MaterialBaker.cpp +++ b/libraries/baking/src/MaterialBaker.cpp @@ -276,4 +276,8 @@ void MaterialBaker::setMaterials(const QHash& materials, addTexture(material.name, image::TextureUsage::SCATTERING_TEXTURE, material.scatteringTexture); addTexture(material.name, image::TextureUsage::LIGHTMAP_TEXTURE, material.lightmapTexture); } +} + +void MaterialBaker::setMaterials(const NetworkMaterialResourcePointer& materialResource) { + _materialResource = materialResource; } \ No newline at end of file diff --git a/libraries/baking/src/MaterialBaker.h b/libraries/baking/src/MaterialBaker.h index 7a7411142e..9469466cb9 100644 --- a/libraries/baking/src/MaterialBaker.h +++ b/libraries/baking/src/MaterialBaker.h @@ -31,6 +31,9 @@ public: QString getBakedMaterialData() const { return _bakedMaterialData; } void setMaterials(const QHash& materials, const QString& baseURL); + void setMaterials(const NetworkMaterialResourcePointer& materialResource); + + NetworkMaterialResourcePointer getNetworkMaterialResource() const { return _materialResource; } static void setNextOvenWorkerThreadOperator(std::function getNextOvenWorkerThreadOperator) { _getNextOvenWorkerThreadOperator = getNextOvenWorkerThreadOperator; } diff --git a/libraries/baking/src/ModelBaker.cpp b/libraries/baking/src/ModelBaker.cpp index c15def18fc..9de32158c5 100644 --- a/libraries/baking/src/ModelBaker.cpp +++ b/libraries/baking/src/ModelBaker.cpp @@ -241,9 +241,6 @@ void ModelBaker::bakeSourceCopy() { config->getJobConfig("BuildDracoMesh")->setEnabled(true); // Do not permit potentially lossy modification of joint data meant for runtime ((PrepareJointsConfig*)config->getJobConfig("PrepareJoints"))->passthrough = true; - // The resources parsed from this job will not be used for now - // TODO: Proper full baking of all materials for a model - config->getJobConfig("ParseMaterialMapping")->setEnabled(false); // Begin hfm baking baker.run(); @@ -261,7 +258,7 @@ void ModelBaker::bakeSourceCopy() { return; } - if (_hfmModel->materials.size() > 0) { + if (!_hfmModel->materials.isEmpty()) { _materialBaker = QSharedPointer( new MaterialBaker(_modelURL.fileName(), true, _bakedOutputDir), &MaterialBaker::deleteLater @@ -270,7 +267,7 @@ void ModelBaker::bakeSourceCopy() { connect(_materialBaker.data(), &MaterialBaker::finished, this, &ModelBaker::handleFinishedMaterialBaker); _materialBaker->bake(); } else { - outputBakedFST(); + bakeMaterialMap(); } } @@ -286,26 +283,14 @@ void ModelBaker::handleFinishedMaterialBaker() { auto baseName = relativeBakedMaterialURL.left(relativeBakedMaterialURL.lastIndexOf('.')); relativeBakedMaterialURL = baseName + BAKED_MATERIAL_EXTENSION; - // First we add the materials in the model - QJsonArray materialMapping; - for (auto material : _hfmModel->materials) { - QJsonObject json; - json["mat::" + material.name] = relativeBakedMaterialURL + "#" + material.name; - materialMapping.push_back(json); - } - - // The we add any existing mappings from the mapping - if (_mapping.contains(MATERIAL_MAPPING_FIELD)) { - QByteArray materialMapValue = _mapping[MATERIAL_MAPPING_FIELD].toByteArray(); - QJsonObject oldMaterialMapping = QJsonDocument::fromJson(materialMapValue).object(); - for (auto key : oldMaterialMapping.keys()) { + auto materialResource = baker->getNetworkMaterialResource(); + if (materialResource) { + for (auto materialName : materialResource->parsedMaterials.names) { QJsonObject json; - json[key] = oldMaterialMapping[key]; - materialMapping.push_back(json); + json[QString("mat::" + QString(materialName.c_str()))] = relativeBakedMaterialURL + "#" + materialName.c_str(); + _materialMappingJSON.push_back(json); } } - - _mapping[MATERIAL_MAPPING_FIELD] = QJsonDocument(materialMapping).toJson(QJsonDocument::Compact); } else { // this material failed to bake - this doesn't fail the entire bake but we need to add the errors from // the material to our warnings @@ -315,7 +300,62 @@ void ModelBaker::handleFinishedMaterialBaker() { handleWarning("Failed to bake the materials for model with URL " + _modelURL.toString()); } - outputBakedFST(); + bakeMaterialMap(); +} + +void ModelBaker::bakeMaterialMap() { + if (!_materialMapping.empty()) { + // TODO: The existing material map must be baked in order, so we do it all on this thread to preserve the order. + // It could be spread over multiple threads if we had a good way of preserving the order once all of the bakers are done + _materialBaker = QSharedPointer( + new MaterialBaker("materialMap" + QString::number(_materialMapIndex++), true, _bakedOutputDir), + &MaterialBaker::deleteLater + ); + _materialBaker->setMaterials(_materialMapping.front().second); + connect(_materialBaker.data(), &MaterialBaker::finished, this, &ModelBaker::handleFinishedMaterialMapBaker); + _materialBaker->bake(); + } else { + outputBakedFST(); + } +} + +void ModelBaker::handleFinishedMaterialMapBaker() { + auto baker = qobject_cast(sender()); + + if (baker) { + if (!baker->hasErrors()) { + // this MaterialBaker is done and everything went according to plan + qCDebug(model_baking) << "Adding baked material to FST mapping " << baker->getBakedMaterialData(); + + QString materialName; + { + auto materialResource = baker->getNetworkMaterialResource(); + if (materialResource) { + auto url = materialResource->getURL(); + if (!url.isEmpty()) { + QString urlString = url.toDisplayString(); + auto index = urlString.lastIndexOf("#"); + if (index != -1) { + materialName = urlString.right(urlString.length() - index); + } + } + } + } + + QJsonObject json; + json[QString(_materialMapping.front().first.c_str())] = baker->getMaterialData() + BAKED_MATERIAL_EXTENSION + materialName; + _materialMappingJSON.push_back(json); + } else { + // this material failed to bake - this doesn't fail the entire bake but we need to add the errors from + // the material to our warnings + _warningList << baker->getWarnings(); + } + } else { + handleWarning("Failed to bake the materialMap for model with URL " + _modelURL.toString() + " and mapping target " + _materialMapping.front().first.c_str()); + } + + _materialMapping.erase(_materialMapping.begin()); + bakeMaterialMap(); } void ModelBaker::outputUnbakedFST() { @@ -364,6 +404,9 @@ void ModelBaker::outputBakedFST() { outputMapping[FILENAME_FIELD] = _bakedModelURL.fileName(); outputMapping.remove(TEXDIR_FIELD); outputMapping.remove(COMMENT_FIELD); + if (!_materialMappingJSON.isEmpty()) { + outputMapping[MATERIAL_MAPPING_FIELD] = QJsonDocument(_materialMappingJSON).toJson(QJsonDocument::Compact); + } hifi::ByteArray fstOut = FSTReader::writeMapping(outputMapping); QFile fstOutputFile { outputFSTURL }; diff --git a/libraries/baking/src/ModelBaker.h b/libraries/baking/src/ModelBaker.h index da42871d28..b98d9716e1 100644 --- a/libraries/baking/src/ModelBaker.h +++ b/libraries/baking/src/ModelBaker.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "Baker.h" #include "MaterialBaker.h" @@ -80,15 +81,19 @@ protected slots: void handleModelNetworkReply(); virtual void bakeSourceCopy(); void handleFinishedMaterialBaker(); + void handleFinishedMaterialMapBaker(); private: void outputUnbakedFST(); void outputBakedFST(); + void bakeMaterialMap(); bool _hasBeenBaked { false }; hfm::Model::Pointer _hfmModel; MaterialMapping _materialMapping; + int _materialMapIndex { 0 }; + QJsonArray _materialMappingJSON; QSharedPointer _materialBaker; }; From 65f4fac99304217eee4adabbf3df063b88194f89 Mon Sep 17 00:00:00 2001 From: raveenajain Date: Fri, 19 Apr 2019 21:40:57 +0100 Subject: [PATCH 44/74] move debug code --- libraries/fbx/src/GLTFSerializer.cpp | 40 ++++++++++++++++++++++++---- libraries/fbx/src/GLTFSerializer.h | 1 + 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index a4d18fb111..fe8bd3167f 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -909,7 +909,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { auto& node = _file.nodes[nodeIndex]; if (node.defined["mesh"]) { - qCDebug(modelformat) << "node_transforms" << node.transforms; foreach(auto &primitive, _file.meshes[node.mesh].primitives) { hfmModel.meshes.append(HFMMesh()); HFMMesh& mesh = hfmModel.meshes[hfmModel.meshes.size() - 1]; @@ -1276,7 +1275,6 @@ HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) { QString fname = hifi::URL(url).fileName(); hifi::URL textureUrl = _url.resolved(url); - qCDebug(modelformat) << "fname: " << fname; fbxtex.name = fname; fbxtex.filename = textureUrl.toEncoded(); @@ -1371,10 +1369,7 @@ bool GLTFSerializer::readArray(const hifi::ByteArray& bin, int byteOffset, int c blobstream.setVersion(QDataStream::Qt_5_9); blobstream.setFloatingPointPrecision(QDataStream::FloatingPointPrecision::SinglePrecision); - qCDebug(modelformat) << "size1: " << count; int dataskipped = blobstream.skipRawData(byteOffset); - qCDebug(modelformat) << "dataskipped: " << dataskipped; - int bufferCount = 0; switch (accessorType) { case GLTFAccessorType::SCALAR: @@ -1467,6 +1462,38 @@ void GLTFSerializer::retriangulate(const QVector& inIndices, const QVector< } } +void GLTFSerializer::glTFDebugDump() { + qCDebug(modelformat) << "---------------- Nodes ----------------"; + for (GLTFNode node : _file.nodes) { + if (node.defined["mesh"]) { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << " node_transforms" << node.transforms; + qCDebug(modelformat) << "\n"; + } + } + + qCDebug(modelformat) << "---------------- Accessors ----------------"; + for (GLTFAccessor accessor : _file.accessors) { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << "count: " << accessor.count; + qCDebug(modelformat) << "byteOffset: " << accessor.byteOffset; + qCDebug(modelformat) << "\n"; + } + + qCDebug(modelformat) << "---------------- Textures ----------------"; + for (GLTFTexture texture : _file.textures) { + if (texture.defined["source"]) { + qCDebug(modelformat) << "\n"; + QString url = _file.images[texture.source].uri; + QString fname = hifi::URL(url).fileName(); + qCDebug(modelformat) << "fname: " << fname; + qCDebug(modelformat) << "\n"; + } + } + + qCDebug(modelformat) << "\n"; +} + void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) { qCDebug(modelformat) << "---------------- hfmModel ----------------"; qCDebug(modelformat) << " hasSkeletonJoints =" << hfmModel.hasSkeletonJoints; @@ -1607,5 +1634,8 @@ void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) { qCDebug(modelformat) << "\n"; } + qCDebug(modelformat) << "---------------- GLTF Model ----------------"; + glTFDebugDump(); + qCDebug(modelformat) << "\n"; } diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/fbx/src/GLTFSerializer.h index a9e7152e5b..8784667d1e 100755 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -784,6 +784,7 @@ private: void setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material); HFMTexture getHFMTexture(const GLTFTexture& texture); + void glTFDebugDump(); void hfmDebugDump(const HFMModel& hfmModel); }; From f2312f77c1936d8d89768178f7972e900a3b8f04 Mon Sep 17 00:00:00 2001 From: raveenajain Date: Fri, 19 Apr 2019 22:47:47 +0100 Subject: [PATCH 45/74] remove unused var --- libraries/fbx/src/GLTFSerializer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index fe8bd3167f..0264accdc3 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1368,8 +1368,8 @@ bool GLTFSerializer::readArray(const hifi::ByteArray& bin, int byteOffset, int c blobstream.setByteOrder(QDataStream::LittleEndian); blobstream.setVersion(QDataStream::Qt_5_9); blobstream.setFloatingPointPrecision(QDataStream::FloatingPointPrecision::SinglePrecision); + blobstream.skipRawData(byteOffset); - int dataskipped = blobstream.skipRawData(byteOffset); int bufferCount = 0; switch (accessorType) { case GLTFAccessorType::SCALAR: From 15e4df2b6124e1f9ab97cfa38aea2ff3133fae2c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Apr 2019 09:32:42 -0700 Subject: [PATCH 46/74] Fix domain baker not finishing (threading, material key) This addresses 2 cases where the domain baker would not finish 1. For material baking, we were storing a value in _entitiesNeedingRewrite with a different key than what we use when we later remove it from _entitiesNeedingRewrite 2. The domain baker runs on a worker thread. When starting a baker for an item in the domain, we do an invokeMethod, which will happen synchronously if the baker ends up on the same thread as the thread that the domain baker is on. This can cause issues if the baker finishes immediately. The case I saw was a local model url that immediately failed, and finished before return from the invokeMethod in the domain baker . --- tools/oven/src/DomainBaker.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/oven/src/DomainBaker.cpp b/tools/oven/src/DomainBaker.cpp index b6adee28dc..f2abf17854 100644 --- a/tools/oven/src/DomainBaker.cpp +++ b/tools/oven/src/DomainBaker.cpp @@ -171,7 +171,7 @@ void DomainBaker::addModelBaker(const QString& property, const QString& url, con // move the baker to the baker thread // and kickoff the bake baker->moveToThread(Oven::instance().getNextWorkerThread()); - QMetaObject::invokeMethod(baker.data(), "bake"); + QMetaObject::invokeMethod(baker.data(), "bake", Qt::QueuedConnection); // keep track of the total number of baking entities ++_totalNumberOfSubBakes; @@ -212,7 +212,7 @@ void DomainBaker::addTextureBaker(const QString& property, const QString& url, i // move the baker to a worker thread and kickoff the bake textureBaker->moveToThread(Oven::instance().getNextWorkerThread()); - QMetaObject::invokeMethod(textureBaker.data(), "bake"); + QMetaObject::invokeMethod(textureBaker.data(), "bake", Qt::QueuedConnection); // keep track of the total number of baking entities ++_totalNumberOfSubBakes; @@ -247,7 +247,7 @@ void DomainBaker::addScriptBaker(const QString& property, const QString& url, co // move the baker to a worker thread and kickoff the bake scriptBaker->moveToThread(Oven::instance().getNextWorkerThread()); - QMetaObject::invokeMethod(scriptBaker.data(), "bake"); + QMetaObject::invokeMethod(scriptBaker.data(), "bake", Qt::QueuedConnection); // keep track of the total number of baking entities ++_totalNumberOfSubBakes; @@ -272,7 +272,7 @@ void DomainBaker::addMaterialBaker(const QString& property, const QString& data, // setup a baker for this material QSharedPointer materialBaker { - new MaterialBaker(data, isURL, _contentOutputPath, destinationPath), + new MaterialBaker(materialData, isURL, _contentOutputPath, destinationPath), &MaterialBaker::deleteLater }; @@ -284,7 +284,7 @@ void DomainBaker::addMaterialBaker(const QString& property, const QString& data, // move the baker to a worker thread and kickoff the bake materialBaker->moveToThread(Oven::instance().getNextWorkerThread()); - QMetaObject::invokeMethod(materialBaker.data(), "bake"); + QMetaObject::invokeMethod(materialBaker.data(), "bake", Qt::QueuedConnection); // keep track of the total number of baking entities ++_totalNumberOfSubBakes; From ba02aa7098324996ec877a3caa3108d7c1537675 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 19 Apr 2019 16:56:55 -0700 Subject: [PATCH 47/74] making luci2 better --- .../utilities/lib/jet/qml/TaskPropView.qml | 12 ++- .../utilities/render/debugCulling.js | 2 +- scripts/developer/utilities/render/luci.js | 85 ++---------------- scripts/developer/utilities/render/luci.qml | 25 ++++++ .../render/{culling.qml => luci/Culling.qml} | 21 +++-- .../developer/utilities/render/luci/Page.js | 90 +++++++++++++++++++ .../developer/utilities/render/luci/qmldir | 3 +- scripts/developer/utilities/render/luci2.js | 87 ++++++++++++++++-- .../utilities/render/materialInspector.js | 8 +- 9 files changed, 236 insertions(+), 97 deletions(-) rename scripts/developer/utilities/render/{culling.qml => luci/Culling.qml} (86%) create mode 100644 scripts/developer/utilities/render/luci/Page.js diff --git a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml index 0587352b4e..165edcf2e1 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskPropView.qml @@ -31,7 +31,15 @@ Prop.PropGroup { property var showProps: true property var showSubs: true property var jobEnabled: rootConfig.getConfig(jobPath).enabled - property var jobCpuTime: rootConfig.getConfig(jobPath).cpuRunTime.toPrecision(3) + property var jobCpuTime: pullCpuTime() + + function pullCpuTime() { + if (jobEnabled) { + return rootConfig.getConfig(jobPath).cpuRunTime.toPrecision(3); + } else { + return '.' + } + } property var toggleJobActivation: function() { console.log("the button has been pressed and jobEnabled is " + jobEnabled ) @@ -52,7 +60,7 @@ Prop.PropGroup { } Prop.PropLabel { id: cpuTime - visible: root.jobEnabled + visible: false // root.jobEnabled width: 50 text: jobCpuTime horizontalAlignment: Text.AlignLeft diff --git a/scripts/developer/utilities/render/debugCulling.js b/scripts/developer/utilities/render/debugCulling.js index 788c7cb4a0..e7c68fd717 100644 --- a/scripts/developer/utilities/render/debugCulling.js +++ b/scripts/developer/utilities/render/debugCulling.js @@ -10,7 +10,7 @@ // // Set up the qml ui -var qml = Script.resolvePath('culling.qml'); +var qml = Script.resolvePath('luci/Culling.qml'); var window = new OverlayWindow({ title: 'Render Draws', source: qml, diff --git a/scripts/developer/utilities/render/luci.js b/scripts/developer/utilities/render/luci.js index bae5c4646d..fd84f55e65 100644 --- a/scripts/developer/utilities/render/luci.js +++ b/scripts/developer/utilities/render/luci.js @@ -10,10 +10,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + + (function() { var AppUi = Script.require('appUi'); var MaterialInspector = Script.require('./materialInspector.js'); + var Page = Script.require('./luci/Page.js'); var moveDebugCursor = false; var onMousePressEvent = function (e) { @@ -43,83 +46,12 @@ Render.getConfig("RenderMainView").getConfig("DebugDeferredBuffer").size = { x: nx, y: ny, z: 1.0, w: 1.0 }; } - function Page(title, qmlurl, width, height, handleWindowFunc) { - this.title = title; - this.qml = qmlurl; - this.width = width; - this.height = height; - this.handleWindowFunc = handleWindowFunc; - this.window; - - print("Page: New Page:" + JSON.stringify(this)); - } - - Page.prototype.killView = function () { - print("Page: Kill window for page:" + JSON.stringify(this)); - if (this.window) { - print("Page: Kill window for page:" + this.title); - //this.window.closed.disconnect(function () { - // this.killView(); - //}); - this.window.close(); - this.window = false; - } - }; - - Page.prototype.createView = function () { - var that = this; - if (!this.window) { - print("Page: New window for page:" + this.title); - this.window = Desktop.createWindow(Script.resolvePath(this.qml), { - title: this.title, - presentationMode: Desktop.PresentationMode.NATIVE, - size: {x: this.width, y: this.height} - }); - this.handleWindowFunc(this.window); - this.window.closed.connect(function () { - that.killView(); - this.handleWindowFunc(undefined); - }); - } - }; - - - var Pages = function () { - this._pages = {}; - }; - - Pages.prototype.addPage = function (command, title, qmlurl, width, height, handleWindowFunc) { - if (handleWindowFunc === undefined) { - // Workaround for bad linter - handleWindowFunc = function(window){}; - } - this._pages[command] = new Page(title, qmlurl, width, height, handleWindowFunc); - }; - - Pages.prototype.open = function (command) { - print("Pages: command = " + command); - if (!this._pages[command]) { - print("Pages: unknown command = " + command); - return; - } - this._pages[command].createView(); - }; - - Pages.prototype.clear = function () { - for (var p in this._pages) { - print("Pages: kill page: " + p); - this._pages[p].killView(); - delete this._pages[p]; - } - this._pages = {}; - }; var pages = new Pages(); - pages.addPage('openEngineView', 'Render Engine', 'engineInspector.qml', 300, 400); - pages.addPage('openEngineLODView', 'Render LOD', 'lod.qml', 300, 400); - pages.addPage('openCullInspectorView', 'Cull Inspector', 'culling.qml', 300, 400); - pages.addPage('openMaterialInspectorView', 'Material Inspector', 'materialInspector.qml', 300, 400, MaterialInspector.setWindow); + pages.addPage('openEngineLODView', 'Render LOD', '../lod.qml', 300, 400); + pages.addPage('openCullInspectorView', 'Cull Inspector', '../luci/Culling.qml', 300, 400); + pages.addPage('openMaterialInspectorView', 'Material Inspector', '../materialInspector.qml', 300, 400, MaterialInspector.setWindow); function fromQml(message) { if (pages.open(message.method)) { @@ -132,7 +64,7 @@ ui = new AppUi({ buttonName: "LUCI", home: Script.resolvePath("deferredLighting.qml"), - additionalAppScreens: Script.resolvePath("engineInspector.qml"), + additionalAppScreens : Script.resolvePath("engineInspector.qml"), onMessage: fromQml, normalButton: Script.resolvePath("../../../system/assets/images/luci-i.svg"), activeButton: Script.resolvePath("../../../system/assets/images/luci-a.svg") @@ -144,8 +76,5 @@ Controller.mouseReleaseEvent.disconnect(onMouseReleaseEvent); Controller.mouseMoveEvent.disconnect(onMouseMoveEvent); pages.clear(); - // killEngineInspectorView(); - // killCullInspectorView(); - // killEngineLODWindow(); }); }()); diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index 6ceee9a8d0..a904ec52fc 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -62,6 +62,31 @@ Rectangle { Antialiasing {} } } + Prop.PropFolderPanel { + label: "Culling" + panelFrameData: Component { + Culling {} + } + } + Prop.PropFolderPanel { + label: "Tools" + panelFrameData: Component { + Row { + HifiControls.Button { + text: "LOD" + onClicked: { + sendToScript({method: "openEngineLODView"}); + } + } + HifiControls.Button { + text: "Material" + onClicked: { + sendToScript({method: "openMaterialInspectorView"}); + } + } + } + } + } Jet.TaskPropView { id: "le" jobPath: "" diff --git a/scripts/developer/utilities/render/culling.qml b/scripts/developer/utilities/render/luci/Culling.qml similarity index 86% rename from scripts/developer/utilities/render/culling.qml rename to scripts/developer/utilities/render/luci/Culling.qml index 801cb5b573..d881ddf7a6 100644 --- a/scripts/developer/utilities/render/culling.qml +++ b/scripts/developer/utilities/render/luci/Culling.qml @@ -9,11 +9,16 @@ // import QtQuick 2.5 import QtQuick.Controls 1.4 -import "configSlider" + +import "../../lib/prop" as Prop Column { id: root spacing: 8 + + anchors.left: parent.left; + anchors.right: parent.right; + property var sceneOctree: Render.getConfig("RenderMainView.DrawSceneOctree"); property var itemSelection: Render.getConfig("RenderMainView.DrawItemSelection"); @@ -36,6 +41,10 @@ Column { GroupBox { title: "Culling" + + anchors.left: parent.left; + anchors.right: parent.right; + Row { spacing: 8 Column { @@ -91,6 +100,7 @@ Column { } } } + } GroupBox { @@ -103,13 +113,14 @@ Column { anchors.right: parent.right; Repeater { model: [ "Opaque:RenderMainView.DrawOpaqueDeferred", "Transparent:RenderMainView.DrawTransparentDeferred", "Light:RenderMainView.DrawLight", - "Opaque Overlays:RenderMainView.DrawOverlay3DOpaque", "Transparent Overlays:RenderMainView.DrawOverlay3DTransparent" ] - ConfigSlider { + "Opaque InFront:RenderMainView.DrawInFrontOpaque", "Transparent InFront:RenderMainView.DrawInFrontTransparent", + "Opaque HUD:RenderMainView.DrawHUDOpaque", "Transparent HUD:RenderMainView.DrawHUDTransparent" ] + Prop.PropScalar { label: qsTr(modelData.split(":")[0]) integral: true - config: Render.getConfig(modelData.split(":")[1]) + object: Render.getConfig(modelData.split(":")[1]) property: "maxDrawn" - max: config.numDrawn + max: object.numDrawn min: -1 } } diff --git a/scripts/developer/utilities/render/luci/Page.js b/scripts/developer/utilities/render/luci/Page.js new file mode 100644 index 0000000000..06c9704abf --- /dev/null +++ b/scripts/developer/utilities/render/luci/Page.js @@ -0,0 +1,90 @@ +// +// Page.js +// +// Sam Gateau, created on 4/19/2019 +// 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 +// +"use strict"; + +(function() { +function Page(title, qmlurl, width, height, onViewCreated, onViewClosed) { + this.title = title; + this.qml = qmlurl; + this.width = width; + this.height = height; + this.onViewCreated = onViewCreated; + this.onViewClosed = onViewClosed; + + this.window; + + print("Page: New Page:" + JSON.stringify(this)); +} + +Page.prototype.killView = function () { + print("Page: Kill window for page:" + JSON.stringify(this)); + if (this.window) { + print("Page: Kill window for page:" + this.title); + //this.window.closed.disconnect(function () { + // this.killView(); + //}); + this.window.close(); + this.window = false; + } +}; + +Page.prototype.createView = function () { + var that = this; + if (!this.window) { + print("Page: New window for page:" + this.title); + this.window = Desktop.createWindow(Script.resolvePath(this.qml), { + title: this.title, + presentationMode: Desktop.PresentationMode.NATIVE, + size: {x: this.width, y: this.height} + }); + this.onViewCreated(this.window); + this.window.closed.connect(function () { + that.killView(); + that.onViewClosed(); + }); + } +}; + + +Pages = function () { + this._pages = {}; +}; + +Pages.prototype.addPage = function (command, title, qmlurl, width, height, onViewCreated, onViewClosed) { + if (onViewCreated === undefined) { + // Workaround for bad linter + onViewCreated = function(window) {}; + } + if (onViewClosed === undefined) { + // Workaround for bad linter + onViewClosed = function() {}; + } + this._pages[command] = new Page(title, qmlurl, width, height, onViewCreated, onViewClosed); +}; + +Pages.prototype.open = function (command) { + print("Pages: command = " + command); + if (!this._pages[command]) { + print("Pages: unknown command = " + command); + return; + } + this._pages[command].createView(); +}; + +Pages.prototype.clear = function () { + for (var p in this._pages) { + print("Pages: kill page: " + p); + this._pages[p].killView(); + delete this._pages[p]; + } + this._pages = {}; +}; + +}()); diff --git a/scripts/developer/utilities/render/luci/qmldir b/scripts/developer/utilities/render/luci/qmldir index c88dfee714..7a7d6a8ca6 100644 --- a/scripts/developer/utilities/render/luci/qmldir +++ b/scripts/developer/utilities/render/luci/qmldir @@ -3,4 +3,5 @@ ShadingModel 1.0 ShadingModel.qml ToneMapping 1.0 ToneMapping.qml BoundingBoxes 1.0 BoundingBoxes.qml Framebuffer 1.0 Framebuffer.qml -Antialiasing 1.0 Antialiasing.qml \ No newline at end of file +Antialiasing 1.0 Antialiasing.qml +Culling 1.0 Culling.qml \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci2.js b/scripts/developer/utilities/render/luci2.js index d6bb005795..a34cf88415 100644 --- a/scripts/developer/utilities/render/luci2.js +++ b/scripts/developer/utilities/render/luci2.js @@ -1,10 +1,83 @@ + + +var MaterialInspector = Script.require('./materialInspector.js'); +var Page = Script.require('./luci/Page.js'); + + function openView() { - // Set up the qml ui - var window = Desktop.createWindow(Script.resolvePath('luci.qml'), { - title: this.title, - presentationMode: Desktop.PresentationMode.NATIVE, - size: {x: 300, y: 400} - }); //window.closed.connect(function() { Script.stop(); }); + + + var pages = new Pages(); + function fromQml(message) { + if (pages.open(message.method)) { + return; + } + } + + var luciWindow + function openLuciWindow(window) { + if (luciWindow !== undefined) { + activeWindow.fromQml.disconnect(fromQml); + } + if (window !== undefined) { + window.fromQml.connect(fromQml); + } + luciWindow = window; + + + var moveDebugCursor = false; + var onMousePressEvent = function (e) { + if (e.isMiddleButton) { + moveDebugCursor = true; + setDebugCursor(e.x, e.y); + } + }; + Controller.mousePressEvent.connect(onMousePressEvent); + + var onMouseReleaseEvent = function () { + moveDebugCursor = false; + }; + Controller.mouseReleaseEvent.connect(onMouseReleaseEvent); + + var onMouseMoveEvent = function (e) { + if (moveDebugCursor) { + setDebugCursor(e.x, e.y); + } + }; + Controller.mouseMoveEvent.connect(onMouseMoveEvent); + + function setDebugCursor(x, y) { + var nx = 2.0 * (x / Window.innerWidth) - 1.0; + var ny = 1.0 - 2.0 * ((y) / (Window.innerHeight)); + + Render.getConfig("RenderMainView").getConfig("DebugDeferredBuffer").size = { x: nx, y: ny, z: 1.0, w: 1.0 }; + } + + } + + function closeLuciWindow() { + if (luciWindow !== undefined) { + activeWindow.fromQml.disconnect(fromQml); + } + luciWindow = {}; + + Controller.mousePressEvent.disconnect(onMousePressEvent); + Controller.mouseReleaseEvent.disconnect(onMouseReleaseEvent); + Controller.mouseMoveEvent.disconnect(onMouseMoveEvent); + pages.clear(); + } + + pages.addPage('Luci', 'Luci', '../luci.qml', 300, 420, openLuciWindow, closeLuciWindow); + pages.addPage('openEngineLODView', 'Render LOD', '../lod.qml', 300, 400); + pages.addPage('openMaterialInspectorView', 'Material Inspector', '../materialInspector.qml', 300, 400, MaterialInspector.setWindow, MaterialInspector.setWindow); + + pages.open('Luci'); + + + return pages; } -openView(); \ No newline at end of file + + +openView(); + diff --git a/scripts/developer/utilities/render/materialInspector.js b/scripts/developer/utilities/render/materialInspector.js index 76e5da5cd0..98d9f769fb 100644 --- a/scripts/developer/utilities/render/materialInspector.js +++ b/scripts/developer/utilities/render/materialInspector.js @@ -109,7 +109,9 @@ function mouseReleaseEvent(event) { } function killWindow() { - setWindow(undefined); + activeWindow = undefined; + + // setWindow(undefined); } function toQml(message) { @@ -138,14 +140,14 @@ function setSelectedObject(id, type) { function setWindow(window) { if (activeWindow !== undefined) { setSelectedObject(Uuid.NULL, ""); - activeWindow.closed.disconnect(killWindow); + // activeWindow.closed.disconnect(killWindow); activeWindow.fromQml.disconnect(fromQml); Controller.mousePressEvent.disconnect(mousePressEvent); Controller.mouseReleaseEvent.disconnect(mouseReleaseEvent); activeWindow.close(); } if (window !== undefined) { - window.closed.connect(killWindow); + // window.closed.connect(killWindow); window.fromQml.connect(fromQml); Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); From 5e251b10336314d13724d1b37c18b1c1b20500d8 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Fri, 19 Apr 2019 17:03:43 -0700 Subject: [PATCH 48/74] Don't double-free an openssl struct --- interface/src/commerce/Wallet.cpp | 604 +++++++++++++++--------------- 1 file changed, 303 insertions(+), 301 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 5644f9ea4c..e1e872ac24 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -41,326 +41,246 @@ #include "ui/SecurityImageProvider.h" #include "scripting/HMDScriptingInterface.h" -static const char* KEY_FILE = "hifikey"; -static const char* INSTRUCTIONS_FILE = "backup_instructions.html"; -static const char* IMAGE_HEADER = "-----BEGIN SECURITY IMAGE-----\n"; -static const char* IMAGE_FOOTER = "-----END SECURITY IMAGE-----\n"; +namespace { + const char* KEY_FILE = "hifikey"; + const char* INSTRUCTIONS_FILE = "backup_instructions.html"; + const char* IMAGE_HEADER = "-----BEGIN SECURITY IMAGE-----\n"; + const char* IMAGE_FOOTER = "-----END SECURITY IMAGE-----\n"; -void initialize() { - static bool initialized = false; - if (!initialized) { - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); - initialized = true; - } -} - -QString keyFilePath() { - auto accountManager = DependencyManager::get(); - return PathUtils::getAppDataFilePath(QString("%1.%2").arg(accountManager->getAccountInfo().getUsername(), KEY_FILE)); -} -bool Wallet::copyKeyFileFrom(const QString& pathname) { - QString existing = getKeyFilePath(); - qCDebug(commerce) << "Old keyfile" << existing; - if (!existing.isEmpty()) { - QString backup = QString(existing).insert(existing.indexOf(KEY_FILE) - 1, - QDateTime::currentDateTime().toString(Qt::ISODate).replace(":", "")); - qCDebug(commerce) << "Renaming old keyfile to" << backup; - if (!QFile::rename(existing, backup)) { - qCCritical(commerce) << "Unable to backup" << existing << "to" << backup; - return false; + void initialize() { + static bool initialized = false; + if (!initialized) { + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + initialized = true; } } - QString destination = keyFilePath(); - bool result = QFile::copy(pathname, destination); - qCDebug(commerce) << "copy" << pathname << "to" << destination << "=>" << result; - return result; -} -// use the cached _passphrase if it exists, otherwise we need to prompt -int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) { - // just return a hardcoded pwd for now - auto wallet = DependencyManager::get(); - auto passphrase = wallet->getPassphrase(); - if (passphrase && !passphrase->isEmpty()) { - QString saltedPassphrase(*passphrase); - saltedPassphrase.append(wallet->getSalt()); - strcpy(password, saltedPassphrase.toUtf8().constData()); - return static_cast(passphrase->size()); - } else { - // this shouldn't happen - so lets log it to tell us we have - // a problem with the flow... - qCCritical(commerce) << "no cached passphrase while decrypting!"; - return 0; + QString keyFilePath() { + auto accountManager = DependencyManager::get(); + return PathUtils::getAppDataFilePath(QString("%1.%2").arg(accountManager->getAccountInfo().getUsername(), KEY_FILE)); } -} -EC_KEY* readKeys(QString filename) { - QFile file(filename); - EC_KEY* key = NULL; - if (file.open(QFile::ReadOnly)) { - // file opened successfully - qCDebug(commerce) << "opened key file" << filename; + // use the cached _passphrase if it exists, otherwise we need to prompt + int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) { + // just return a hardcoded pwd for now + auto wallet = DependencyManager::get(); + auto passphrase = wallet->getPassphrase(); + if (passphrase && !passphrase->isEmpty()) { + QString saltedPassphrase(*passphrase); + saltedPassphrase.append(wallet->getSalt()); + strcpy(password, saltedPassphrase.toUtf8().constData()); + return static_cast(passphrase->size()); + } else { + // this shouldn't happen - so lets log it to tell us we have + // a problem with the flow... + qCCritical(commerce) << "no cached passphrase while decrypting!"; + return 0; + } + } - QByteArray pemKeyBytes = file.readAll(); - BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length()); - if ((key = PEM_read_bio_EC_PUBKEY(bufio, NULL, NULL, NULL))) { - // now read private key + EC_KEY* readKeys(QString filename) { + QFile file(filename); + EC_KEY* key = NULL; + if (file.open(QFile::ReadOnly)) { + // file opened successfully + qCDebug(commerce) << "opened key file" << filename; - qCDebug(commerce) << "read public key"; + QByteArray pemKeyBytes = file.readAll(); + BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length()); + if ((key = PEM_read_bio_EC_PUBKEY(bufio, NULL, NULL, NULL))) { + // now read private key - if ((key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL))) { - qCDebug(commerce) << "read private key"; - BIO_free(bufio); - file.close(); + qCDebug(commerce) << "read public key"; + + if ((key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL))) { + qCDebug(commerce) << "read private key"; + } else { + qCDebug(commerce) << "failed to read private key"; + } } else { - qCDebug(commerce) << "failed to read private key"; + qCDebug(commerce) << "failed to read public key"; } - } else { - qCDebug(commerce) << "failed to read public key"; - } - BIO_free(bufio); - file.close(); - } else { - qCDebug(commerce) << "failed to open key file" << filename; - } - return key; -} - -bool Wallet::writeBackupInstructions() { - QString inputFilename(PathUtils::resourcesPath() + "html/commerce/backup_instructions.html"); - QString outputFilename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE); - QFile inputFile(inputFilename); - QFile outputFile(outputFilename); - bool retval = false; - - if (getKeyFilePath().isEmpty()) { - return false; - } - - if (QFile::exists(inputFilename) && inputFile.open(QIODevice::ReadOnly)) { - if (outputFile.open(QIODevice::ReadWrite)) { - // Read the data from the original file, then close it - QByteArray fileData = inputFile.readAll(); - inputFile.close(); - - // Translate the data from the original file into a QString - QString text(fileData); - - // Replace the necessary string - text.replace(QString("HIFIKEY_PATH_REPLACEME"), keyFilePath()); - - // Write the new text back to the file - outputFile.write(text.toUtf8()); - - // Close the output file - outputFile.close(); - - retval = true; - qCDebug(commerce) << "wrote html file successfully"; - } else { - qCDebug(commerce) << "failed to open output html file" << outputFilename; - } - } else { - qCDebug(commerce) << "failed to open input html file" << inputFilename; - } - return retval; -} - -bool writeKeys(QString filename, EC_KEY* keys) { - BIO* bio = BIO_new(BIO_s_mem()); - bool retval = false; - if (!PEM_write_bio_EC_PUBKEY(bio, keys)) { - BIO_free(bio); - qCCritical(commerce) << "failed to write public key"; - return retval; - } - - if (!PEM_write_bio_ECPrivateKey(bio, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) { - BIO_free(bio); - qCCritical(commerce) << "failed to write private key"; - return retval; - } - - QFile file(filename); - if (!file.open(QIODevice::WriteOnly)) { - const char* bio_data; - long bio_size = BIO_get_mem_data(bio, &bio_data); - - QByteArray keyBytes(bio_data, bio_size); - file.write(keyBytes); - retval = true; - qCDebug(commerce) << "wrote keys successfully"; - file.close(); - } else { - qCDebug(commerce) << "failed to open key file" << filename; - } - BIO_free(bio); - return retval; -} - -bool Wallet::setWallet(const QByteArray& wallet) { - QFile file(keyFilePath()); - if (!file.open(QIODevice::WriteOnly)) { - qCCritical(commerce) << "Unable to open wallet for write in" << keyFilePath(); - return false; - } - if (file.write(wallet) != wallet.count()) { - qCCritical(commerce) << "Unable to write wallet in" << keyFilePath(); - return false; - } - file.close(); - return true; -} -QByteArray Wallet::getWallet() { - QFile file(keyFilePath()); - if (!file.open(QIODevice::ReadOnly)) { - qCInfo(commerce) << "No existing wallet in" << keyFilePath(); - return QByteArray(); - } - QByteArray wallet = file.readAll(); - file.close(); - return wallet; -} - -QPair generateECKeypair() { - EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1); - QPair retval{}; - - EC_KEY_set_asn1_flag(keyPair, OPENSSL_EC_NAMED_CURVE); - if (!EC_KEY_generate_key(keyPair)) { - qCDebug(commerce) << "Error generating EC Keypair -" << ERR_get_error(); - return retval; - } - - // grab the public key and private key from the file - unsigned char* publicKeyDER = NULL; - int publicKeyLength = i2d_EC_PUBKEY(keyPair, &publicKeyDER); - - unsigned char* privateKeyDER = NULL; - int privateKeyLength = i2d_ECPrivateKey(keyPair, &privateKeyDER); - - if (publicKeyLength <= 0 || privateKeyLength <= 0) { - qCDebug(commerce) << "Error getting DER public or private key from EC struct -" << ERR_get_error(); - - // cleanup the EC struct - EC_KEY_free(keyPair); - - // cleanup the public and private key DER data, if required - if (publicKeyLength > 0) { - OPENSSL_free(publicKeyDER); - } - - if (privateKeyLength > 0) { - OPENSSL_free(privateKeyDER); - } - - return retval; - } - - if (!writeKeys(keyFilePath(), keyPair)) { - qCDebug(commerce) << "couldn't save keys!"; - return retval; - } - - EC_KEY_free(keyPair); - - // prepare the return values. TODO: Fix this - we probably don't really even want the - // private key at all (better to read it when we need it?). Or maybe we do, when we have - // multiple keys? - retval.first = new QByteArray(reinterpret_cast(publicKeyDER), publicKeyLength); - retval.second = new QByteArray(reinterpret_cast(privateKeyDER), privateKeyLength); - - // cleanup the publicKeyDER and publicKeyDER data - OPENSSL_free(publicKeyDER); - OPENSSL_free(privateKeyDER); - return retval; -} -// END copied code (which will soon change) - -// the public key can just go into a byte array -QByteArray readPublicKey(QString filename) { - QByteArray retval; - QFile file(filename); - if (file.open(QIODevice::ReadOnly)) { - // file opened successfully - qCDebug(commerce) << "opened key file" << filename; - - QByteArray pemKeyBytes = file.readAll(); - BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length()); - - EC_KEY* key = PEM_read_bio_EC_PUBKEY(bufio, NULL, NULL, NULL); - if (key) { - // file read successfully - unsigned char* publicKeyDER = NULL; - int publicKeyLength = i2d_EC_PUBKEY(key, &publicKeyDER); - // TODO: check for 0 length? - - // cleanup - EC_KEY_free(key); - - qCDebug(commerce) << "parsed public key file successfully"; - - QByteArray retval((char*)publicKeyDER, publicKeyLength); - OPENSSL_free(publicKeyDER); BIO_free(bufio); file.close(); + } else { + qCDebug(commerce) << "failed to open key file" << filename; + } + return key; + } + + bool writeKeys(QString filename, EC_KEY* keys) { + BIO* bio = BIO_new(BIO_s_mem()); + bool retval = false; + if (!PEM_write_bio_EC_PUBKEY(bio, keys)) { + BIO_free(bio); + qCCritical(commerce) << "failed to write public key"; return retval; - } else { - qCDebug(commerce) << "couldn't parse" << filename; } - BIO_free(bufio); - file.close(); - } else { - qCDebug(commerce) << "couldn't open" << filename; - } - return QByteArray(); -} -// the private key should be read/copied into heap memory. For now, we need the EC_KEY struct -// so I'll return that. -EC_KEY* readPrivateKey(QString filename) { - QFile file(filename); - EC_KEY* key = NULL; - if (file.open(QIODevice::ReadOnly)) { - // file opened successfully - qCDebug(commerce) << "opened key file" << filename; - - QByteArray pemKeyBytes = file.readAll(); - BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length()); - - if ((key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL))) { - qCDebug(commerce) << "parsed private key file successfully"; - - } else { - qCDebug(commerce) << "couldn't parse" << filename; - // if the passphrase is wrong, then let's not cache it - DependencyManager::get()->setPassphrase(""); + if (!PEM_write_bio_ECPrivateKey(bio, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) { + BIO_free(bio); + qCCritical(commerce) << "failed to write private key"; + return retval; } - BIO_free(bufio); - file.close(); - } else { - qCDebug(commerce) << "couldn't open" << filename; - } - return key; -} -// QT's QByteArray will convert to Base64 without any embedded newlines. This just -// writes it with embedded newlines, which is more readable. -void outputBase64WithNewlines(QFile& file, const QByteArray& b64Array) { - for (int i = 0; i < b64Array.size(); i += 64) { - file.write(b64Array.mid(i, 64)); - file.write("\n"); - } -} + QFile file(filename); + if (!file.open(QIODevice::WriteOnly)) { + const char* bio_data; + long bio_size = BIO_get_mem_data(bio, &bio_data); -void initializeAESKeys(unsigned char* ivec, unsigned char* ckey, const QByteArray& salt) { - // use the ones in the wallet - auto wallet = DependencyManager::get(); - memcpy(ivec, wallet->getIv(), 16); - memcpy(ckey, wallet->getCKey(), 32); -} + QByteArray keyBytes(bio_data, bio_size); + file.write(keyBytes); + retval = true; + qCDebug(commerce) << "wrote keys successfully"; + file.close(); + } else { + qCDebug(commerce) << "failed to open key file" << filename; + } + BIO_free(bio); + return retval; + } + + QPair generateECKeypair() { + EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1); + QPair retval {}; + + EC_KEY_set_asn1_flag(keyPair, OPENSSL_EC_NAMED_CURVE); + if (!EC_KEY_generate_key(keyPair)) { + qCDebug(commerce) << "Error generating EC Keypair -" << ERR_get_error(); + return retval; + } + + // grab the public key and private key from the file + unsigned char* publicKeyDER = NULL; + int publicKeyLength = i2d_EC_PUBKEY(keyPair, &publicKeyDER); + + unsigned char* privateKeyDER = NULL; + int privateKeyLength = i2d_ECPrivateKey(keyPair, &privateKeyDER); + + if (publicKeyLength <= 0 || privateKeyLength <= 0) { + qCDebug(commerce) << "Error getting DER public or private key from EC struct -" << ERR_get_error(); + + // cleanup the EC struct + EC_KEY_free(keyPair); + + // cleanup the public and private key DER data, if required + if (publicKeyLength > 0) { + OPENSSL_free(publicKeyDER); + } + + if (privateKeyLength > 0) { + OPENSSL_free(privateKeyDER); + } + + return retval; + } + + if (!writeKeys(keyFilePath(), keyPair)) { + qCDebug(commerce) << "couldn't save keys!"; + return retval; + } + + EC_KEY_free(keyPair); + + // prepare the return values. TODO: Fix this - we probably don't really even want the + // private key at all (better to read it when we need it?). Or maybe we do, when we have + // multiple keys? + retval.first = new QByteArray(reinterpret_cast(publicKeyDER), publicKeyLength); + retval.second = new QByteArray(reinterpret_cast(privateKeyDER), privateKeyLength); + + // cleanup the publicKeyDER and publicKeyDER data + OPENSSL_free(publicKeyDER); + OPENSSL_free(privateKeyDER); + return retval; + } + // END copied code (which will soon change) + + // the public key can just go into a byte array + QByteArray readPublicKey(QString filename) { + QByteArray retval; + QFile file(filename); + if (file.open(QIODevice::ReadOnly)) { + // file opened successfully + qCDebug(commerce) << "opened key file" << filename; + + QByteArray pemKeyBytes = file.readAll(); + BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length()); + + EC_KEY* key = PEM_read_bio_EC_PUBKEY(bufio, NULL, NULL, NULL); + if (key) { + // file read successfully + unsigned char* publicKeyDER = NULL; + int publicKeyLength = i2d_EC_PUBKEY(key, &publicKeyDER); + // TODO: check for 0 length? + + // cleanup + EC_KEY_free(key); + + qCDebug(commerce) << "parsed public key file successfully"; + + QByteArray retval((char*)publicKeyDER, publicKeyLength); + OPENSSL_free(publicKeyDER); + BIO_free(bufio); + file.close(); + return retval; + } else { + qCDebug(commerce) << "couldn't parse" << filename; + } + BIO_free(bufio); + file.close(); + } else { + qCDebug(commerce) << "couldn't open" << filename; + } + return QByteArray(); + } + + // the private key should be read/copied into heap memory. For now, we need the EC_KEY struct + // so I'll return that. + EC_KEY* readPrivateKey(QString filename) { + QFile file(filename); + EC_KEY* key = NULL; + if (file.open(QIODevice::ReadOnly)) { + // file opened successfully + qCDebug(commerce) << "opened key file" << filename; + + QByteArray pemKeyBytes = file.readAll(); + BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length()); + + if ((key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL))) { + qCDebug(commerce) << "parsed private key file successfully"; + + } else { + qCDebug(commerce) << "couldn't parse" << filename; + // if the passphrase is wrong, then let's not cache it + DependencyManager::get()->setPassphrase(""); + } + BIO_free(bufio); + file.close(); + } else { + qCDebug(commerce) << "couldn't open" << filename; + } + return key; + } + + // QT's QByteArray will convert to Base64 without any embedded newlines. This just + // writes it with embedded newlines, which is more readable. + void outputBase64WithNewlines(QFile& file, const QByteArray& b64Array) { + for (int i = 0; i < b64Array.size(); i += 64) { + file.write(b64Array.mid(i, 64)); + file.write("\n"); + } + } + + void initializeAESKeys(unsigned char* ivec, unsigned char* ckey, const QByteArray& salt) { + // use the ones in the wallet + auto wallet = DependencyManager::get(); + memcpy(ivec, wallet->getIv(), 16); + memcpy(ckey, wallet->getCKey(), 32); + } + +} // close unnamed namespace Wallet::Wallet() { auto nodeList = DependencyManager::get(); @@ -423,6 +343,88 @@ Wallet::~Wallet() { } } +bool Wallet::setWallet(const QByteArray& wallet) { + QFile file(keyFilePath()); + if (!file.open(QIODevice::WriteOnly)) { + qCCritical(commerce) << "Unable to open wallet for write in" << keyFilePath(); + return false; + } + if (file.write(wallet) != wallet.count()) { + qCCritical(commerce) << "Unable to write wallet in" << keyFilePath(); + return false; + } + file.close(); + return true; +} +QByteArray Wallet::getWallet() { + QFile file(keyFilePath()); + if (!file.open(QIODevice::ReadOnly)) { + qCInfo(commerce) << "No existing wallet in" << keyFilePath(); + return QByteArray(); + } + QByteArray wallet = file.readAll(); + file.close(); + return wallet; +} + +bool Wallet::copyKeyFileFrom(const QString& pathname) { + QString existing = getKeyFilePath(); + qCDebug(commerce) << "Old keyfile" << existing; + if (!existing.isEmpty()) { + QString backup = QString(existing).insert(existing.indexOf(KEY_FILE) - 1, + QDateTime::currentDateTime().toString(Qt::ISODate).replace(":", "")); + qCDebug(commerce) << "Renaming old keyfile to" << backup; + if (!QFile::rename(existing, backup)) { + qCCritical(commerce) << "Unable to backup" << existing << "to" << backup; + return false; + } + } + QString destination = keyFilePath(); + bool result = QFile::copy(pathname, destination); + qCDebug(commerce) << "copy" << pathname << "to" << destination << "=>" << result; + return result; +} + +bool Wallet::writeBackupInstructions() { + QString inputFilename(PathUtils::resourcesPath() + "html/commerce/backup_instructions.html"); + QString outputFilename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE); + QFile inputFile(inputFilename); + QFile outputFile(outputFilename); + bool retval = false; + + if (getKeyFilePath().isEmpty()) { + return false; + } + + if (QFile::exists(inputFilename) && inputFile.open(QIODevice::ReadOnly)) { + if (outputFile.open(QIODevice::ReadWrite)) { + // Read the data from the original file, then close it + QByteArray fileData = inputFile.readAll(); + inputFile.close(); + + // Translate the data from the original file into a QString + QString text(fileData); + + // Replace the necessary string + text.replace(QString("HIFIKEY_PATH_REPLACEME"), keyFilePath()); + + // Write the new text back to the file + outputFile.write(text.toUtf8()); + + // Close the output file + outputFile.close(); + + retval = true; + qCDebug(commerce) << "wrote html file successfully"; + } else { + qCDebug(commerce) << "failed to open output html file" << outputFilename; + } + } else { + qCDebug(commerce) << "failed to open input html file" << inputFilename; + } + return retval; +} + bool Wallet::setPassphrase(const QString& passphrase) { if (_passphrase) { delete _passphrase; From 55f3c3a11a6e5176588a69959f3e137c3dcd7501 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Fri, 19 Apr 2019 18:21:31 -0700 Subject: [PATCH 49/74] allowing context change to change mute state --- interface/src/scripting/Audio.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index bceafc3c42..5dd1488606 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -351,6 +351,13 @@ void Audio::onContextChanged() { changed = true; } }); + if (_settingsLoaded) { + if (isHMD) { + setMuted(getMutedHMD()); + } else { + setMuted(getMutedDesktop()); + } + } if (changed) { emit contextChanged(isHMD ? Audio::HMD : Audio::DESKTOP); } From 0f2dbd7b6ae3de2854dee283e156a23b29c3bec0 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 4 Apr 2019 17:36:10 -0700 Subject: [PATCH 50/74] Fix mac warnings --- interface/src/Application.cpp | 6 +++--- interface/src/avatar/AvatarManager.cpp | 2 +- interface/src/ui/LoginDialog.cpp | 2 +- libraries/animation/src/AnimVariant.h | 2 +- libraries/entities/src/EntityItem.cpp | 2 +- .../model-baker/src/model-baker/BuildDracoMeshTask.cpp | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7ba45da1fd..08dfa63715 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2337,7 +2337,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - EntityItem::setBillboardRotationOperator([this](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos) { + EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos) { if (billboardMode == BillboardMode::YAW) { //rotate about vertical to face the camera glm::vec3 dPosition = frustumPos - position; @@ -2365,7 +2365,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID) { userKickConfirmation(nodeID); }); - render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([this](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { + render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([=](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { bool isTablet = url == TabletScriptingInterface::QML; if (htmlContent) { webSurface = DependencyManager::get()->acquire(render::entities::WebEntityRenderer::QML); @@ -2405,7 +2405,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo const uint8_t TABLET_FPS = 90; webSurface->setMaxFps(isTablet ? TABLET_FPS : DEFAULT_MAX_FPS); }); - render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([this](QSharedPointer& webSurface, bool& cachedWebSurface, std::vector& connections) { + render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([=](QSharedPointer& webSurface, bool& cachedWebSurface, std::vector& connections) { QQuickItem* rootItem = webSurface->getRootItem(); // Fix for crash in QtWebEngineCore when rapidly switching domains diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 8274259922..ba1309d5b8 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -727,7 +727,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic boxHit._distance = FLT_MAX; for (size_t i = 0; i < hit._boundJoints.size(); i++) { - assert(hit._boundJoints[i] < multiSpheres.size()); + assert(hit._boundJoints[i] < (int)multiSpheres.size()); auto &mSphere = multiSpheres[hit._boundJoints[i]]; if (mSphere.isValid()) { float boundDistance = FLT_MAX; diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index b4f504822f..459b224474 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -138,7 +138,7 @@ void LoginDialog::login(const QString& username, const QString& password) const void LoginDialog::loginThroughOculus() { qDebug() << "Attempting to login through Oculus"; if (auto oculusPlatformPlugin = PluginManager::getInstance()->getOculusPlatformPlugin()) { - oculusPlatformPlugin->requestNonceAndUserID([this] (QString nonce, QString oculusID) { + oculusPlatformPlugin->requestNonceAndUserID([] (QString nonce, QString oculusID) { DependencyManager::get()->requestAccessTokenWithOculus(nonce, oculusID); }); } diff --git a/libraries/animation/src/AnimVariant.h b/libraries/animation/src/AnimVariant.h index eb9ebd33dd..a8bdb885e5 100644 --- a/libraries/animation/src/AnimVariant.h +++ b/libraries/animation/src/AnimVariant.h @@ -261,7 +261,7 @@ public: qCDebug(animation) << " " << pair.first << "=" << pair.second.getString(); break; default: - assert(("invalid AnimVariant::Type", false)); + assert(false); } } } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a532064b6c..e1ede9192a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -791,7 +791,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef bool otherOverwrites = overwriteLocalData && !weOwnSimulation; // calculate hasGrab once outside the lambda rather than calling it every time inside bool hasGrab = stillHasGrabAction(); - auto shouldUpdate = [this, lastEdited, otherOverwrites, filterRejection, hasGrab](quint64 updatedTimestamp, bool valueChanged) { + auto shouldUpdate = [lastEdited, otherOverwrites, filterRejection, hasGrab](quint64 updatedTimestamp, bool valueChanged) { if (hasGrab) { return false; } diff --git a/libraries/model-baker/src/model-baker/BuildDracoMeshTask.cpp b/libraries/model-baker/src/model-baker/BuildDracoMeshTask.cpp index 2e378965de..25a45cefe5 100644 --- a/libraries/model-baker/src/model-baker/BuildDracoMeshTask.cpp +++ b/libraries/model-baker/src/model-baker/BuildDracoMeshTask.cpp @@ -52,7 +52,7 @@ std::vector createMaterialList(const hfm::Mesh& mesh) { } std::unique_ptr createDracoMesh(const hfm::Mesh& mesh, const std::vector& normals, const std::vector& tangents, const std::vector& materialList) { - Q_ASSERT(normals.size() == 0 || normals.size() == mesh.vertices.size()); + Q_ASSERT(normals.size() == 0 || (int)normals.size() == mesh.vertices.size()); Q_ASSERT(mesh.colors.size() == 0 || mesh.colors.size() == mesh.vertices.size()); Q_ASSERT(mesh.texCoords.size() == 0 || mesh.texCoords.size() == mesh.vertices.size()); From 97632534e52434776023946f7546457737b3a654 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 22 Apr 2019 09:14:32 -0700 Subject: [PATCH 51/74] REvert unecessary modified files to upstream master, just leaving the true new feature in this branch --- .../hmd/DebugHmdDisplayPlugin.cpp | 5 - .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 8 +- .../gpu-gl-common/src/gpu/gl/GLBackend.h | 10 +- .../src/gpu/gl/GLBackendTransform.cpp | 45 +- .../gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp | 21 +- libraries/gpu/src/gpu/Context.cpp | 945 ------------------ libraries/gpu/src/gpu/Framebuffer.cpp | 30 +- libraries/gpu/src/gpu/Framebuffer.h | 11 +- libraries/gpu/src/gpu/Texture.h | 8 +- libraries/gpu/src/gpu/Transform.slh | 11 +- libraries/shaders/headers/450/header.glsl | 1 - tools/shadergen.py | 4 - 12 files changed, 21 insertions(+), 1078 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp index cd7478d002..b4527ff90c 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp @@ -26,8 +26,6 @@ bool DebugHmdDisplayPlugin::isSupported() const { void DebugHmdDisplayPlugin::resetSensors() { _currentRenderFrameInfo.renderPose = glm::mat4(); // identity - _currentRenderFrameInfo.renderPose = glm::translate(glm::mat4(), glm::vec3(0.0f, 1.76f, 0.0f)); - } bool DebugHmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) { @@ -37,8 +35,6 @@ bool DebugHmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) { // FIXME simulate head movement //_currentRenderFrameInfo.renderPose = ; //_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose; - _currentRenderFrameInfo.renderPose = glm::translate(glm::mat4(), glm::vec3(0.0f, 1.76f, 0.0f)); - _currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose; withNonPresentThreadLock([&] { _frameInfos[frameIndex] = _currentRenderFrameInfo; @@ -78,7 +74,6 @@ bool DebugHmdDisplayPlugin::internalActivate() { // uncomment to capture a quarter size frame //_renderTargetSize /= 2; _cullingProjection = _eyeProjections[0]; - // This must come after the initialization, so that the values calculated // above are available during the customizeContext call (when not running // in threaded present mode) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index 844c1ce2bf..fef458f536 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -447,24 +447,20 @@ void GLBackend::render(const Batch& batch) { renderPassTransfer(batch); } -//#ifdef GPU_STEREO_DRAWCALL_INSTANCED -#ifdef GPU_STEREO_VIEWPORT_CLIPPED +#ifdef GPU_STEREO_DRAWCALL_INSTANCED if (_stereo.isStereo()) { glEnable(GL_CLIP_DISTANCE0); } #endif -//#endif { GL_PROFILE_RANGE(render_gpu_gl_detail, _stereo.isStereo() ? "Render Stereo" : "Render"); renderPassDraw(batch); } -//#ifdef GPU_STEREO_DRAWCALL_INSTANCED -#ifdef GPU_STEREO_VIEWPORT_CLIPPED +#ifdef GPU_STEREO_DRAWCALL_INSTANCED if (_stereo.isStereo()) { glDisable(GL_CLIP_DISTANCE0); } #endif -//#endif // Restore the saved stereo state for the next batch _stereo._enable = savedStereo; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 327488da36..ffd0466b79 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -36,8 +36,7 @@ #define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE #else //#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER -//#define GPU_STEREO_TECHNIQUE_INSTANCED -#define GPU_STEREO_TECHNIQUE_INSTANCED_MULTIVIEWPORT +#define GPU_STEREO_TECHNIQUE_INSTANCED #endif // Let these be configured by the one define picked above @@ -52,13 +51,6 @@ #ifdef GPU_STEREO_TECHNIQUE_INSTANCED #define GPU_STEREO_DRAWCALL_INSTANCED -#define GPU_STEREO_VIEWPORT_CLIPPED -#define GPU_STEREO_CAMERA_BUFFER -#endif - -#ifdef GPU_STEREO_TECHNIQUE_INSTANCED_MULTIVIEWPORT -#define GPU_STEREO_DRAWCALL_INSTANCED -#define GPU_STEREO_MULTI_VIEWPORT #define GPU_STEREO_CAMERA_BUFFER #endif diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp index 698a70af5a..555a0a1e41 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp @@ -39,48 +39,6 @@ void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) #ifdef GPU_STEREO_DRAWCALL_INSTANCED { - #ifdef GPU_STEREO_MULTI_VIEWPORT - ivec4& vp = _transform._viewport; - auto sideWidth = vp.z / 2; - - vec4 leftRight[3]; - - // Mono - leftRight[0] = vp; - // adding this here as im doing Layered, force the first viewport here to be half of it - leftRight[0].x = 0; - leftRight[0].z = sideWidth; - - // Left side - leftRight[1] = vp; - leftRight[1].x = 0; - leftRight[1].z = sideWidth; - - // right side - leftRight[2] = vp; - leftRight[2].x = sideWidth; - leftRight[2].z = sideWidth; - - glViewportArrayv(0, 3, (float*)leftRight); - - // Where we assign the GL viewport - if (_stereo.isStereo()) { - - // ivec4 leftRight[3]; - // leftRight[0] = vp; - vp.z /= 2; - /* leftRight[1] = vp; // left side - leftRight[2] = vp; // right side - leftRight[2].x += vp.z; - glViewportArrayv(0, 3, (float*) leftRight); -*/ - if (_stereo._pass) { - vp.x += vp.z; - } - } else { - // glViewport(vp.x, vp.y, vp.z, vp.w); - } - #else ivec4& vp = _transform._viewport; glViewport(vp.x, vp.y, vp.z, vp.w); @@ -91,7 +49,6 @@ void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) vp.x += vp.z; } } - #endif } #else if (!_inRenderTransferPass && !isStereo()) { @@ -166,7 +123,7 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo if (_invalidView || _invalidProj || _invalidViewport) { size_t offset = _cameraUboSize * _cameras.size(); - Vec2 finalJitter = _projectionJitter / Vec2(framebufferSize); + Vec2 finalJitter = _projectionJitter / Vec2(framebufferSize); _cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset)); if (stereo.isStereo()) { diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp index a86e6637a2..7a299e792b 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp @@ -60,23 +60,12 @@ public: } if (gltexture) { - if (!_gpuObject.isLayered()) { - if (gltexture->_target == GL_TEXTURE_2D) { - glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0); - } else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) { - glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0); - } else { - glNamedFramebufferTextureLayer(_id, colorAttachments[unit], gltexture->_texture, 0, b._subresource); - } + if (gltexture->_target == GL_TEXTURE_2D) { + glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0); + } else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) { + glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0); } else { - if (gltexture->_target == GL_TEXTURE_2D) { - glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0); - } else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) { - glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0); - } else { - glNamedFramebufferTextureLayer(_id, colorAttachments[unit], gltexture->_texture, 0, - b._subresource); - } + glNamedFramebufferTextureLayer(_id, colorAttachments[unit], gltexture->_texture, 0, b._subresource); } _colorBuffers.push_back(colorAttachments[unit]); } else { diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index e3c75a24d6..45ee4263a3 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -421,951 +421,6 @@ void gpu::doInBatch(const char* name, const std::shared_ptr& context, const std::function& f) { auto batch = Context::acquireBatch(name); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - f(*batch); context->appendFrameBatch(batch); } diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index 41406b4b93..e88d986da6 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -82,14 +82,6 @@ uint32 Framebuffer::getFrameCount() const { } } -uint16 evalRenderBufferNumLayers(const Texture& texture, uint16 subresource) { - if (subresource == TextureView::UNDEFINED_SUBRESOURCE) { - return texture.getNumSlices(); - } else { - return 1; - } -} - bool Framebuffer::validateTargetCompatibility(const Texture& texture, uint32 subresource) const { if (texture.getType() == Texture::TEX_1D) { return false; @@ -100,8 +92,7 @@ bool Framebuffer::validateTargetCompatibility(const Texture& texture, uint32 sub } else { if ((texture.getWidth() == getWidth()) && (texture.getHeight() == getHeight()) && - (texture.getNumSamples() == getNumSamples()) && - (evalRenderBufferNumLayers(texture, subresource) == getNumLayers())) { + (texture.getNumSamples() == getNumSamples())) { return true; } else { return false; @@ -109,7 +100,7 @@ bool Framebuffer::validateTargetCompatibility(const Texture& texture, uint32 sub } } -void Framebuffer::updateSize(const TexturePointer& texture, uint32 subresource) { +void Framebuffer::updateSize(const TexturePointer& texture) { if (!isEmpty()) { return; } @@ -118,9 +109,8 @@ void Framebuffer::updateSize(const TexturePointer& texture, uint32 subresource) _width = texture->getWidth(); _height = texture->getHeight(); _numSamples = texture->getNumSamples(); - _numLayers = evalRenderBufferNumLayers(*texture, subresource); } else { - _width = _height = _numSamples = _numLayers = 0; + _width = _height = _numSamples = 0; } } @@ -148,14 +138,6 @@ uint16 Framebuffer::getNumSamples() const { } } -uint16 Framebuffer::getNumLayers() const { - if (isSwapchain()) { - return getSwapchain()->getNumLayers(); - } else { - return _numLayers; - } -} - // Render buffers int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uint32 subresource) { if (isSwapchain()) { @@ -182,7 +164,7 @@ int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uin ++_colorStamps[slot]; - updateSize(texture, subresource); + updateSize(texture); // assign the new one _renderBuffers[slot] = TextureView(texture, subresource); @@ -209,7 +191,7 @@ void Framebuffer::removeRenderBuffers() { renderBuffer._texture.reset(); } - updateSize(TexturePointer(nullptr), TextureView::UNDEFINED_SUBRESOURCE); + updateSize(TexturePointer(nullptr)); } @@ -258,7 +240,7 @@ bool Framebuffer::assignDepthStencilBuffer(const TexturePointer& texture, const } ++_depthStamp; - updateSize(texture, subresource); + updateSize(texture); // assign the new one _depthStencilBuffer = TextureView(texture, subresource, format); diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 3d2b869958..47b2775d52 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -27,7 +27,6 @@ public: uint16 getWidth() const { return _width; } uint16 getHeight() const { return _height; } uint16 getNumSamples() const { return _numSamples; } - uint16 getNumLayers() const { return _numLayers; } bool hasDepthStencil() const { return _hasDepthStencil; } bool isFullscreen() const { return _isFullscreen; } @@ -55,7 +54,6 @@ protected: uint16 _width = 1; uint16 _height = 1; uint16 _numSamples = 1; - uint16 _numLayers = 1; uint16 _swapInterval = 0; bool _hasDepthStencil = false; @@ -117,6 +115,7 @@ public: uint32 getDepthStencilBufferSubresource() const; Format getDepthStencilBufferFormat() const; + // Properties Masks getBufferMask() const { return _bufferMask; } bool isEmpty() const { return (_bufferMask == 0); } @@ -131,10 +130,6 @@ public: uint16 getWidth() const; uint16 getHeight() const; uint16 getNumSamples() const; - - uint16 getNumLayers() const; - bool isLayered() const { return getNumLayers() > 1; } - const std::string& getName() const { return _name; } void setName(const std::string& name) { _name = name; } @@ -175,9 +170,7 @@ protected: uint16 _height = 0; uint16 _numSamples = 0; - uint16 _numLayers = 0; - - void updateSize(const TexturePointer& texture, uint32 subresource); + void updateSize(const TexturePointer& texture); bool assignDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource); friend class Serializer; diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 537169bf67..26ff86af9c 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -646,11 +646,9 @@ typedef std::vector< TexturePointer > Textures; class TextureView { public: typedef Resource::Size Size; - - static const uint16 UNDEFINED_SUBRESOURCE { uint16(-1) }; TexturePointer _texture = TexturePointer(NULL); - uint16 _subresource = UNDEFINED_SUBRESOURCE; + uint16 _subresource = 0; Element _element = Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); TextureView() {}; @@ -662,7 +660,7 @@ public: // create the TextureView and own the Texture TextureView(Texture* newTexture, const Element& element) : _texture(newTexture), - _subresource(UNDEFINED_SUBRESOURCE), + _subresource(0), _element(element) {}; TextureView(const TexturePointer& texture, uint16 subresource, const Element& element) : @@ -684,8 +682,6 @@ public: bool operator !() const { return (!_texture); } bool isValid() const { return bool(_texture); } - - bool isSubresource() const { return (_subresource != UNDEFINED_SUBRESOURCE); } }; typedef std::vector TextureViews; diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 484ad7ebd2..3015de7e0e 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -168,17 +168,10 @@ TransformObject getTransformObject() { vec2 eyeOffsetScale = vec2(-0.5, +0.5); uint eyeIndex = uint(_stereoSide); #if !defined(GPU_GLES) || (defined(HAVE_EXT_clip_cull_distance) && !defined(VULKAN)) -#ifdef GPU_GL450 - /* gl_ViewportIndex = _stereoSide + 1; - // gl_ViewportIndex = 2 - _stereoSide; - */// THIs is the layered version - gl_Layer = _stereoSide; -#else gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]); #endif -#endif - // float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w; - // <$clipPos$>.x = newClipPosX; + float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w; + <$clipPos$>.x = newClipPosX; #endif #else diff --git a/libraries/shaders/headers/450/header.glsl b/libraries/shaders/headers/450/header.glsl index e3f0021d16..ef0ec09414 100644 --- a/libraries/shaders/headers/450/header.glsl +++ b/libraries/shaders/headers/450/header.glsl @@ -1,4 +1,3 @@ -#extension GL_ARB_shader_viewport_layer_array : require #define GPU_SSBO_TRANSFORM_OBJECT #define BITFIELD int #define LAYOUT(X) layout(X) diff --git a/tools/shadergen.py b/tools/shadergen.py index 4ce4d2818f..f82b471f17 100644 --- a/tools/shadergen.py +++ b/tools/shadergen.py @@ -215,10 +215,6 @@ def processCommand(line): if (dialect == '310es'): spirvCrossDialect = '320es' spirvCrossArgs = [spirvCrossExec, '--output', glslFile, spirvFile, '--version', spirvCrossDialect] if (dialect == '410'): spirvCrossArgs.append('--no-420pack-extension') - if (dialect == '450'): - spirvCrossArgs.append('--extension') - spirvCrossArgs.append('GL_ARB_shader_viewport_layer_array') - executeSubprocess(spirvCrossArgs) else: # This logic is necessary because cmake will agressively keep re-executing the shadergen From 98a7e4e7110996ea972d0b859af7eb9783502b24 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 22 Apr 2019 11:34:58 -0700 Subject: [PATCH 52/74] fix version not being preserved --- tools/oven/src/DomainBaker.cpp | 14 ++++---------- tools/oven/src/DomainBaker.h | 2 ++ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/tools/oven/src/DomainBaker.cpp b/tools/oven/src/DomainBaker.cpp index b6adee28dc..fc065619d7 100644 --- a/tools/oven/src/DomainBaker.cpp +++ b/tools/oven/src/DomainBaker.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include "Gzip.h" @@ -132,10 +131,10 @@ void DomainBaker::loadLocalFile() { } // read the file contents to a JSON document - auto jsonDocument = QJsonDocument::fromJson(fileContents); + _json = QJsonDocument::fromJson(fileContents); // grab the entities object from the root JSON object - _entities = jsonDocument.object()[ENTITIES_OBJECT_KEY].toArray(); + _entities = _json.object()[ENTITIES_OBJECT_KEY].toArray(); if (_entities.isEmpty()) { // add an error to our list stating that the models file was empty @@ -749,15 +748,10 @@ void DomainBaker::writeNewEntitiesFile() { // time to write out a main models.json.gz file // first setup a document with the entities array below the entities key - QJsonDocument entitiesDocument; - - QJsonObject rootObject; - rootObject[ENTITIES_OBJECT_KEY] = _entities; - - entitiesDocument.setObject(rootObject); + _json.object()[ENTITIES_OBJECT_KEY] = _entities; // turn that QJsonDocument into a byte array ready for compression - QByteArray jsonByteArray = entitiesDocument.toJson(); + QByteArray jsonByteArray = _json.toJson(); // compress the json byte array using gzip QByteArray compressedJson; diff --git a/tools/oven/src/DomainBaker.h b/tools/oven/src/DomainBaker.h index e8102ec7e8..d4414bbf99 100644 --- a/tools/oven/src/DomainBaker.h +++ b/tools/oven/src/DomainBaker.h @@ -12,6 +12,7 @@ #ifndef hifi_DomainBaker_h #define hifi_DomainBaker_h +#include #include #include #include @@ -59,6 +60,7 @@ private: QString _originalOutputPath; QUrl _destinationPath; + QJsonDocument _json; QJsonArray _entities; QHash> _modelBakers; From 8dabcb76b8b0ea917fcbefdf71b8674cc5bca780 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 22 Apr 2019 21:30:57 +0200 Subject: [PATCH 53/74] Taking into account comments --- libraries/render-utils/src/RenderPipelines.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index cd4d787f0e..ac2eb8e475 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -755,18 +755,21 @@ bool RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu: }); // For shadows, we only need opacity mask information - if (renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE || multiMaterial.getMaterialKey().isOpacityMaskMap()) { + auto key = multiMaterial.getMaterialKey(); + if (renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE || key.isOpacityMaskMap()) { auto& schemaBuffer = multiMaterial.getSchemaBuffer(); batch.setUniformBuffer(gr::Buffer::Material, schemaBuffer); if (enableTextures) { batch.setResourceTextureTable(multiMaterial.getTextureTable()); } else { - auto key = multiMaterial.getMaterialKey(); - if (key.isLightmapMap()) { - defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getBlackTexture()); - } else if (key.isEmissiveMap()) { - defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getGrayTexture()); + if (renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) { + if (key.isLightmapMap()) { + defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getBlackTexture()); + } else if (key.isEmissiveMap()) { + defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getGrayTexture()); + } } + batch.setResourceTextureTable(defaultMaterialTextures); } return true; From 22c2bfc07515dcfd5bea86fab87577d33348b996 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Apr 2019 15:03:12 -0700 Subject: [PATCH 54/74] fix material target parentIDChanged --- scripts/system/html/js/entityProperties.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 4cee3c0bc7..d7800ada5d 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -2950,7 +2950,7 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI */ function parentIDChanged() { - if (currentSelections.length === 1 && currentSelections[0].type === "Material") { + if (currentSelections.length === 1 && currentSelections[0].properties.type === "Material") { requestMaterialTarget(); } } From 4fc97effda095a84131b89059d0a347a78511bfd Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 22 Apr 2019 16:22:18 -0700 Subject: [PATCH 55/74] combine snapshotOperator lists per sam's suggestions --- interface/src/Application.cpp | 22 ++++++------------- interface/src/Application.h | 7 ++---- interface/src/graphics/GraphicsEngine.cpp | 3 --- interface/src/ui/Snapshot.cpp | 4 ++-- interface/src/ui/SnapshotAnimated.cpp | 2 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 15 +++++-------- libraries/gpu/src/gpu/Frame.h | 3 +-- 7 files changed, 18 insertions(+), 38 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 27c6ef2f64..f46d0d3ddd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -8441,23 +8441,15 @@ void Application::loadAvatarBrowser() const { void Application::addSnapshotOperator(const SnapshotOperator& snapshotOperator) { std::lock_guard lock(_snapshotMutex); _snapshotOperators.push(snapshotOperator); + _hasPrimarySnapshot |= std::get<2>(snapshotOperator); } bool Application::takeSnapshotOperators(std::queue& snapshotOperators) { std::lock_guard lock(_snapshotMutex); + bool hasPrimarySnapshot = _hasPrimarySnapshot; + _hasPrimarySnapshot = false; _snapshotOperators.swap(snapshotOperators); - return !snapshotOperators.empty(); -} - -void Application::addSecondarySnapshotOperator(const SecondarySnapshotOperator& snapshotOperator) { - std::lock_guard lock(_snapshotMutex); - _secondarySnapshotOperators.push(snapshotOperator); -} - -bool Application::takeSecondarySnapshotOperators(std::queue& snapshotOperators) { - std::lock_guard lock(_snapshotMutex); - _secondarySnapshotOperators.swap(snapshotOperators); - return !snapshotOperators.empty(); + return hasPrimarySnapshot; } void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { @@ -8476,15 +8468,15 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, DependencyManager::get()); }); } - }, aspectRatio }); + }, aspectRatio, true }); } void Application::takeSecondaryCameraSnapshot(const bool& notify, const QString& filename) { - addSecondarySnapshotOperator([notify, filename](const QImage& snapshot) { + addSnapshotOperator({ [notify, filename](const QImage& snapshot) { QString snapshotPath = DependencyManager::get()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); emit DependencyManager::get()->stillSnapshotTaken(snapshotPath, notify); - }); + }, 0, false }); } void Application::takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat, const bool& notify, const QString& filename) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 967790d034..12523f3108 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -345,12 +345,9 @@ public: void toggleAwayMode(); #endif - using SnapshotOperator = std::pair, float>; - using SecondarySnapshotOperator = std::function; + using SnapshotOperator = std::tuple, float, bool>; void addSnapshotOperator(const SnapshotOperator& snapshotOperator); bool takeSnapshotOperators(std::queue& snapshotOperators); - void addSecondarySnapshotOperator(const SecondarySnapshotOperator& snapshotOperator); - bool takeSecondarySnapshotOperators(std::queue& snapshotOperators); signals: void svoImportRequested(const QString& url); @@ -798,7 +795,7 @@ private: SharedSoundPointer _sampleSound; std::mutex _snapshotMutex; std::queue _snapshotOperators; - std::queue _secondarySnapshotOperators; + bool _hasPrimarySnapshot { false }; DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin; QString _autoSwitchDisplayModeSupportedHMDPluginName; diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 09471a9570..267822baf2 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -245,7 +245,6 @@ void GraphicsEngine::render_performFrame() { } std::queue snapshotOperators; - std::queue secondarySnapshotOperators; if (!_programsCompiled.load()) { gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { batch.setFramebuffer(finalFramebuffer); @@ -274,7 +273,6 @@ void GraphicsEngine::render_performFrame() { renderArgs._hudOperator = displayPlugin->getHUDOperator(); renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture(); renderArgs._takingSnapshot = qApp->takeSnapshotOperators(snapshotOperators); - qApp->takeSecondarySnapshotOperators(secondarySnapshotOperators); renderArgs._blitFramebuffer = finalFramebuffer; render_runRenderFrame(&renderArgs); } @@ -290,7 +288,6 @@ void GraphicsEngine::render_performFrame() { } }; frame->snapshotOperators = snapshotOperators; - frame->secondarySnapshotOperators = secondarySnapshotOperators; // deliver final scene rendering commands to the display plugin { PROFILE_RANGE(render, "/pluginOutput"); diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 94523fa6dd..93d9188cc8 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -168,7 +168,7 @@ void Snapshot::takeNextSnapshot() { if (_taking360Snapshot) { if (!_waitingOnSnapshot) { _waitingOnSnapshot = true; - qApp->addSecondarySnapshotOperator([this](const QImage& snapshot) { + qApp->addSnapshotOperator({ [this](const QImage& snapshot) { // Order is: // 0. Down // 1. Front @@ -202,7 +202,7 @@ void Snapshot::takeNextSnapshot() { _waitingOnSnapshot = false; _snapshotIndex++; - }); + }, 0, false }); } } else { _snapshotTimer.stop(); diff --git a/interface/src/ui/SnapshotAnimated.cpp b/interface/src/ui/SnapshotAnimated.cpp index 03ec86e342..f8f6a30635 100644 --- a/interface/src/ui/SnapshotAnimated.cpp +++ b/interface/src/ui/SnapshotAnimated.cpp @@ -86,7 +86,7 @@ void SnapshotAnimated::captureFrames() { SnapshotAnimated::snapshotAnimatedTimerRunning = false; } } - }, SnapshotAnimated::aspectRatio }); + }, SnapshotAnimated::aspectRatio, true }); } else { // Notify the user that we're processing the snapshot // This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called. diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index e80102ec85..4c3de004bd 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -725,20 +725,15 @@ void OpenGLDisplayPlugin::present() { PROFILE_RANGE_EX(render, "snapshotOperators", 0xffff00ff, frameId) while (!_currentFrame->snapshotOperators.empty()) { auto& snapshotOperator = _currentFrame->snapshotOperators.front(); - snapshotOperator.first(getScreenshot(snapshotOperator.second)); + if (std::get<2>(snapshotOperator)) { + std::get<0>(snapshotOperator)(getScreenshot(std::get<1>(snapshotOperator))); + } else { + std::get<0>(snapshotOperator)(getSecondaryCameraScreenshot()); + } _currentFrame->snapshotOperators.pop(); } } - { // If we have any secondary camera snapshots this frame, handle them - PROFILE_RANGE_EX(render, "secondarySnapshotOperators", 0x00ff00ff, frameId) - while (!_currentFrame->secondarySnapshotOperators.empty()) { - auto& snapshotOperator = _currentFrame->secondarySnapshotOperators.front(); - snapshotOperator(getSecondaryCameraScreenshot()); - _currentFrame->secondarySnapshotOperators.pop(); - } - } - // Take the composite framebuffer and send it to the output device { PROFILE_RANGE_EX(render, "internalPresent", 0xff00ffff, frameId) diff --git a/libraries/gpu/src/gpu/Frame.h b/libraries/gpu/src/gpu/Frame.h index 541b9393d3..9aa99e50f7 100644 --- a/libraries/gpu/src/gpu/Frame.h +++ b/libraries/gpu/src/gpu/Frame.h @@ -42,8 +42,7 @@ namespace gpu { /// How to process the framebuffer when the frame dies. MUST BE THREAD SAFE FramebufferRecycler framebufferRecycler; - std::queue, float>> snapshotOperators; - std::queue> secondarySnapshotOperators; + std::queue, float, bool>> snapshotOperators; protected: friend class Deserializer; From 7f4292440abb7869cd7d20ec148aa151e791644f Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 12 Apr 2019 09:10:12 -0700 Subject: [PATCH 56/74] Fix oven integration in the asset server --- assignment-client/src/assets/AssetServer.cpp | 134 +++++++++++------- assignment-client/src/assets/AssetServer.h | 7 +- .../src/assets/BakeAssetTask.cpp | 34 +++-- assignment-client/src/assets/BakeAssetTask.h | 2 +- 4 files changed, 111 insertions(+), 66 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index c2aec9b058..88f81f639b 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -1326,12 +1326,40 @@ void AssetServer::handleFailedBake(QString originalAssetHash, QString assetPath, } void AssetServer::handleCompletedBake(QString originalAssetHash, QString originalAssetPath, - QString bakedTempOutputDir, QVector bakedFilePaths) { + QString bakedTempOutputDir) { bool errorCompletingBake { false }; QString errorReason; qDebug() << "Completing bake for " << originalAssetHash; + + + QDir outputDir(bakedTempOutputDir); + auto directories = outputDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + assert(directories.size() == 1); + QString bakedDirectoryPath; + for (const auto& dirName : directories) { + outputDir.cd(dirName); + if (outputDir.exists("baked") && outputDir.exists("original")) { + bakedDirectoryPath = outputDir.filePath("baked"); + } + outputDir.cdUp(); + } + + assert(!bakedDirectoryPath.isEmpty()); + + QDirIterator it(bakedDirectoryPath, QDirIterator::Subdirectories); + QVector bakedFilePaths; + while (it.hasNext()) { + it.next(); + if (it.fileInfo().isFile()) { + bakedFilePaths.push_back(it.filePath()); + } + } + + QDir bakedDirectory(bakedDirectoryPath); + QString redirectTarget; + for (auto& filePath : bakedFilePaths) { // figure out the hash for the contents of this file QFile file(filePath); @@ -1340,62 +1368,59 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina AssetUtils::AssetHash bakedFileHash; - if (file.open(QIODevice::ReadOnly)) { - QCryptographicHash hasher(QCryptographicHash::Sha256); - - if (hasher.addData(&file)) { - bakedFileHash = hasher.result().toHex(); - } else { - // stop handling this bake, couldn't hash the contents of the file - errorCompletingBake = true; - errorReason = "Failed to finalize bake"; - break; - } - - // first check that we don't already have this bake file in our list - auto bakeFileDestination = _filesDirectory.absoluteFilePath(bakedFileHash); - if (!QFile::exists(bakeFileDestination)) { - // copy each to our files folder (with the hash as their filename) - if (!file.copy(_filesDirectory.absoluteFilePath(bakedFileHash))) { - // stop handling this bake, couldn't copy the bake file into our files directory - errorCompletingBake = true; - errorReason = "Failed to copy baked assets to asset server"; - break; - } - } - - // setup the mapping for this bake file - auto relativeFilePath = QUrl(filePath).fileName(); - qDebug() << "Relative file path is: " << relativeFilePath; - if (relativeFilePath.endsWith(".fbx", Qt::CaseInsensitive)) { - // for an FBX file, we replace the filename with the simple name - // (to handle the case where two mapped assets have the same hash but different names) - relativeFilePath = BAKED_ASSET_SIMPLE_FBX_NAME; - } else if (relativeFilePath.endsWith(".js", Qt::CaseInsensitive)) { - relativeFilePath = BAKED_ASSET_SIMPLE_JS_NAME; - } else if (!originalAssetPath.endsWith(".fbx", Qt::CaseInsensitive)) { - relativeFilePath = BAKED_ASSET_SIMPLE_TEXTURE_NAME; - } - - QString bakeMapping = getBakeMapping(originalAssetHash, relativeFilePath); - - // add a mapping (under the hidden baked folder) for this file resulting from the bake - if (setMapping(bakeMapping, bakedFileHash)) { - qDebug() << "Added" << bakeMapping << "for bake file" << bakedFileHash << "from bake of" << originalAssetHash; - } else { - qDebug() << "Failed to set mapping"; - // stop handling this bake, couldn't add a mapping for this bake file - errorCompletingBake = true; - errorReason = "Failed to finalize bake"; - break; - } - } else { + if (!file.open(QIODevice::ReadOnly)) { qDebug() << "Failed to open baked file: " << filePath; // stop handling this bake, we couldn't open one of the files for reading errorCompletingBake = true; errorReason = "Failed to finalize bake"; break; } + + QCryptographicHash hasher(QCryptographicHash::Sha256); + + if (!hasher.addData(&file)) { + // stop handling this bake, couldn't hash the contents of the file + errorCompletingBake = true; + errorReason = "Failed to finalize bake"; + break; + } + + bakedFileHash = hasher.result().toHex(); + + // first check that we don't already have this bake file in our list + auto bakeFileDestination = _filesDirectory.absoluteFilePath(bakedFileHash); + if (!QFile::exists(bakeFileDestination)) { + // copy each to our files folder (with the hash as their filename) + if (!file.copy(_filesDirectory.absoluteFilePath(bakedFileHash))) { + // stop handling this bake, couldn't copy the bake file into our files directory + errorCompletingBake = true; + errorReason = "Failed to copy baked assets to asset server"; + break; + } + } + + // setup the mapping for this bake file + auto relativeFilePath = bakedDirectory.relativeFilePath(filePath); + qDebug() << "Relative file path is: " << relativeFilePath; + + QString bakeMapping = getBakeMapping(originalAssetHash, relativeFilePath); + + // Check if this is the file we should redirect to when someone asks for the original asset + if ((relativeFilePath.endsWith(".baked.fst", Qt::CaseInsensitive) && originalAssetPath.endsWith(".fbx")) || + (relativeFilePath.endsWith(".texmeta.json", Qt::CaseInsensitive) && !originalAssetPath.endsWith(".fbx"))) { + redirectTarget = bakeMapping; + } + + // add a mapping (under the hidden baked folder) for this file resulting from the bake + if (!setMapping(bakeMapping, bakedFileHash)) { + qDebug() << "Failed to set mapping"; + // stop handling this bake, couldn't add a mapping for this bake file + errorCompletingBake = true; + errorReason = "Failed to finalize bake"; + break; + } + + qDebug() << "Added" << bakeMapping << "for bake file" << bakedFileHash << "from bake of" << originalAssetHash; } for (auto& filePath : bakedFilePaths) { @@ -1411,9 +1436,12 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina auto type = assetTypeForFilename(originalAssetPath); auto currentTypeVersion = currentBakeVersionForAssetType(type); + assert(!redirectTarget.isEmpty()); + AssetMeta meta; meta.bakeVersion = currentTypeVersion; meta.failedLastBake = errorCompletingBake; + meta.redirectTarget = redirectTarget; if (errorCompletingBake) { qWarning() << "Could not complete bake for" << originalAssetHash; @@ -1435,6 +1463,7 @@ void AssetServer::handleAbortedBake(QString originalAssetHash, QString assetPath static const QString BAKE_VERSION_KEY = "bake_version"; static const QString FAILED_LAST_BAKE_KEY = "failed_last_bake"; static const QString LAST_BAKE_ERRORS_KEY = "last_bake_errors"; +static const QString REDIRECT_TARGET_KEY = "redirect_target"; std::pair AssetServer::readMetaFile(AssetUtils::AssetHash hash) { auto metaFilePath = AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + hash + "/" + "meta.json"; @@ -1461,6 +1490,7 @@ std::pair AssetServer::readMetaFile(AssetUtils::AssetHash hash) auto bakeVersion = root[BAKE_VERSION_KEY]; auto failedLastBake = root[FAILED_LAST_BAKE_KEY]; auto lastBakeErrors = root[LAST_BAKE_ERRORS_KEY]; + auto redirectTarget = root[REDIRECT_TARGET_KEY]; if (bakeVersion.isDouble() && failedLastBake.isBool() @@ -1470,6 +1500,7 @@ std::pair AssetServer::readMetaFile(AssetUtils::AssetHash hash) meta.bakeVersion = bakeVersion.toInt(); meta.failedLastBake = failedLastBake.toBool(); meta.lastBakeErrors = lastBakeErrors.toString(); + meta.redirectTarget = redirectTarget.toString(); return { true, meta }; } else { @@ -1488,6 +1519,7 @@ bool AssetServer::writeMetaFile(AssetUtils::AssetHash originalAssetHash, const A metaFileObject[BAKE_VERSION_KEY] = (int)meta.bakeVersion; metaFileObject[FAILED_LAST_BAKE_KEY] = meta.failedLastBake; metaFileObject[LAST_BAKE_ERRORS_KEY] = meta.lastBakeErrors; + metaFileObject[REDIRECT_TARGET_KEY] = meta.redirectTarget; QJsonDocument metaFileDoc; metaFileDoc.setObject(metaFileObject); diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h index b3d0f18a8f..fe84df5141 100644 --- a/assignment-client/src/assets/AssetServer.h +++ b/assignment-client/src/assets/AssetServer.h @@ -62,12 +62,10 @@ enum class ScriptBakeVersion : BakeVersion { }; struct AssetMeta { - AssetMeta() { - } - BakeVersion bakeVersion { INITIAL_BAKE_VERSION }; bool failedLastBake { false }; QString lastBakeErrors; + QString redirectTarget; }; class BakeAssetTask; @@ -139,8 +137,7 @@ private: void bakeAsset(const AssetUtils::AssetHash& assetHash, const AssetUtils::AssetPath& assetPath, const QString& filePath); /// Move baked content for asset to baked directory and update baked status - void handleCompletedBake(QString originalAssetHash, QString assetPath, QString bakedTempOutputDir, - QVector bakedFilePaths); + void handleCompletedBake(QString originalAssetHash, QString assetPath, QString bakedTempOutputDir); void handleFailedBake(QString originalAssetHash, QString assetPath, QString errors); void handleAbortedBake(QString originalAssetHash, QString assetPath); diff --git a/assignment-client/src/assets/BakeAssetTask.cpp b/assignment-client/src/assets/BakeAssetTask.cpp index ecb4ede5d8..7ca87fe4e3 100644 --- a/assignment-client/src/assets/BakeAssetTask.cpp +++ b/assignment-client/src/assets/BakeAssetTask.cpp @@ -57,12 +57,19 @@ void BakeAssetTask::run() { return; } + // Make a new temporary directory for the Oven to work in QString tempOutputDir = PathUtils::generateTemporaryDir(); + + // Copy file to bake the temporary dir and give a name the oven can work with + auto assetName = _assetPath.split("/").last(); + auto tempAssetPath = tempOutputDir + "/" + assetName; + QFile::copy(_filePath, tempAssetPath); + auto base = QFileInfo(QCoreApplication::applicationFilePath()).absoluteDir(); QString path = base.absolutePath() + "/oven"; QString extension = _assetPath.mid(_assetPath.lastIndexOf('.') + 1); QStringList args { - "-i", _filePath, + "-i", tempAssetPath, "-o", tempOutputDir, "-t", extension, }; @@ -72,7 +79,7 @@ void BakeAssetTask::run() { QEventLoop loop; connect(_ovenProcess.get(), static_cast(&QProcess::finished), - this, [&loop, this, tempOutputDir](int exitCode, QProcess::ExitStatus exitStatus) { + this, [&loop, this, tempOutputDir, tempAssetPath](int exitCode, QProcess::ExitStatus exitStatus) { qDebug() << "Baking process finished: " << exitCode << exitStatus; if (exitStatus == QProcess::CrashExit) { @@ -82,18 +89,20 @@ void BakeAssetTask::run() { QString errors = "Fatal error occurred while baking"; emit bakeFailed(_assetHash, _assetPath, errors); } - } else if (exitCode == OVEN_STATUS_CODE_SUCCESS) { - QDir outputDir = tempOutputDir; - auto files = outputDir.entryInfoList(QDir::Files); - QVector outputFiles; - for (auto& file : files) { - outputFiles.push_back(file.absoluteFilePath()); + if (!QDir(tempOutputDir).rmdir(".")) { + qWarning() << "Failed to remove temporary directory:" << tempOutputDir; } + } else if (exitCode == OVEN_STATUS_CODE_SUCCESS) { + // Remove temp copy of the original asset + QFile::remove(tempAssetPath); - emit bakeComplete(_assetHash, _assetPath, tempOutputDir, outputFiles); + emit bakeComplete(_assetHash, _assetPath, tempOutputDir); } else if (exitStatus == QProcess::NormalExit && exitCode == OVEN_STATUS_CODE_ABORT) { _wasAborted.store(true); emit bakeAborted(_assetHash, _assetPath); + if (!QDir(tempOutputDir).rmdir(".")) { + qWarning() << "Failed to remove temporary directory:" << tempOutputDir; + } } else { QString errors; if (exitCode == OVEN_STATUS_CODE_FAIL) { @@ -108,6 +117,9 @@ void BakeAssetTask::run() { } } emit bakeFailed(_assetHash, _assetPath, errors); + if (!QDir(tempOutputDir).rmdir(".")) { + qWarning() << "Failed to remove temporary directory:" << tempOutputDir; + } } loop.quit(); @@ -115,9 +127,13 @@ void BakeAssetTask::run() { qDebug() << "Starting oven for " << _assetPath; _ovenProcess->start(path, args, QIODevice::ReadOnly); + qDebug() << "Running:" << path << args; if (!_ovenProcess->waitForStarted(-1)) { QString errors = "Oven process failed to start"; emit bakeFailed(_assetHash, _assetPath, errors); + if (!QDir(tempOutputDir).rmdir(".")) { + qWarning() << "Failed to remove temporary directory:" << tempOutputDir; + } return; } diff --git a/assignment-client/src/assets/BakeAssetTask.h b/assignment-client/src/assets/BakeAssetTask.h index 24b070d08a..2d50a26bc1 100644 --- a/assignment-client/src/assets/BakeAssetTask.h +++ b/assignment-client/src/assets/BakeAssetTask.h @@ -37,7 +37,7 @@ public slots: void abort(); signals: - void bakeComplete(QString assetHash, QString assetPath, QString tempOutputDir, QVector outputFiles); + void bakeComplete(QString assetHash, QString assetPath, QString tempOutputDir); void bakeFailed(QString assetHash, QString assetPath, QString errors); void bakeAborted(QString assetHash, QString assetPath); From 080ef882a87a74643870cd35b8009210616bdb88 Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 12 Apr 2019 11:26:40 -0700 Subject: [PATCH 57/74] Update Asset Server redirect and baking conditions --- assignment-client/src/assets/AssetServer.cpp | 132 +++++++++---------- 1 file changed, 60 insertions(+), 72 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 88f81f639b..4805d2fe4c 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -107,6 +107,10 @@ BakeVersion currentBakeVersionForAssetType(BakedAssetType type) { } } +QString getBakeMapping(const AssetUtils::AssetHash& hash, const QString& relativeFilePath) { + return AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + hash + "/" + relativeFilePath; +} + const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server"; void AssetServer::bakeAsset(const AssetUtils::AssetHash& assetHash, const AssetUtils::AssetPath& assetPath, const QString& filePath) { @@ -141,26 +145,22 @@ std::pair AssetServer::getAssetStatus(const A return { AssetUtils::Baked, "" }; } - auto dotIndex = path.lastIndexOf("."); - if (dotIndex == -1) { + BakedAssetType type = assetTypeForFilename(path); + + if (type == BakedAssetType::Undefined) { return { AssetUtils::Irrelevant, "" }; } - auto extension = path.mid(dotIndex + 1); + bool loaded; + AssetMeta meta; + std::tie(loaded, meta) = readMetaFile(hash); - QString bakedFilename; - - if (BAKEABLE_MODEL_EXTENSIONS.contains(extension)) { - bakedFilename = BAKED_MODEL_SIMPLE_NAME; - } else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit()) && hasMetaFile(hash)) { - bakedFilename = BAKED_TEXTURE_SIMPLE_NAME; - } else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) { - bakedFilename = BAKED_SCRIPT_SIMPLE_NAME; - } else { - return { AssetUtils::Irrelevant, "" }; + QString bakedFilename = bakedFilenameForAssetType(type); + auto bakedPath = getBakeMapping(hash, bakedFilename); + if (loaded && !meta.redirectTarget.isEmpty()) { + bakedPath = meta.redirectTarget; } - auto bakedPath = AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + hash + "/" + bakedFilename; auto jt = _fileMappings.find(bakedPath); if (jt != _fileMappings.end()) { if (jt->second == hash) { @@ -168,14 +168,8 @@ std::pair AssetServer::getAssetStatus(const A } else { return { AssetUtils::Baked, "" }; } - } else { - bool loaded; - AssetMeta meta; - - std::tie(loaded, meta) = readMetaFile(hash); - if (loaded && meta.failedLastBake) { - return { AssetUtils::Error, meta.lastBakeErrors }; - } + } else if (loaded && meta.failedLastBake) { + return { AssetUtils::Error, meta.lastBakeErrors }; } return { AssetUtils::Pending, "" }; @@ -227,8 +221,16 @@ bool AssetServer::needsToBeBaked(const AssetUtils::AssetPath& path, const AssetU return false; } + bool loaded; + AssetMeta meta; + std::tie(loaded, meta) = readMetaFile(assetHash); + QString bakedFilename = bakedFilenameForAssetType(type); - auto bakedPath = AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + assetHash + "/" + bakedFilename; + auto bakedPath = getBakeMapping(assetHash, bakedFilename); + if (loaded && !meta.redirectTarget.isEmpty()) { + bakedPath = meta.redirectTarget; + } + auto mappingIt = _fileMappings.find(bakedPath); bool bakedMappingExists = mappingIt != _fileMappings.end(); @@ -238,10 +240,6 @@ bool AssetServer::needsToBeBaked(const AssetUtils::AssetPath& path, const AssetU return false; } - bool loaded; - AssetMeta meta; - std::tie(loaded, meta) = readMetaFile(assetHash); - if (type == BakedAssetType::Texture && !loaded) { return false; } @@ -633,36 +631,33 @@ void AssetServer::handleGetMappingOperation(ReceivedMessage& message, NLPacketLi if (it != _fileMappings.end()) { // check if we should re-direct to a baked asset - - // first, figure out from the mapping extension what type of file this is - auto assetPathExtension = assetPath.mid(assetPath.lastIndexOf('.') + 1).toLower(); - - auto type = assetTypeForFilename(assetPath); - QString bakedRootFile = bakedFilenameForAssetType(type); - auto originalAssetHash = it->second; QString redirectedAssetHash; - QString bakedAssetPath; quint8 wasRedirected = false; bool bakingDisabled = false; - if (!bakedRootFile.isEmpty()) { - // we ran into an asset for which we could have a baked version, let's check if it's ready - bakedAssetPath = AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + originalAssetHash + "/" + bakedRootFile; - auto bakedIt = _fileMappings.find(bakedAssetPath); + bool loaded; + AssetMeta meta; + std::tie(loaded, meta) = readMetaFile(originalAssetHash); - if (bakedIt != _fileMappings.end()) { - if (bakedIt->second != originalAssetHash) { - qDebug() << "Did find baked version for: " << originalAssetHash << assetPath; - // we found a baked version of the requested asset to serve, redirect to that - redirectedAssetHash = bakedIt->second; - wasRedirected = true; - } else { - qDebug() << "Did not find baked version for: " << originalAssetHash << assetPath << " (disabled)"; - bakingDisabled = true; - } + auto type = assetTypeForFilename(assetPath); + QString bakedRootFile = bakedFilenameForAssetType(type); + QString bakedAssetPath = getBakeMapping(originalAssetHash, bakedRootFile); + + if (loaded && !meta.redirectTarget.isEmpty()) { + bakedAssetPath = meta.redirectTarget; + } + + auto bakedIt = _fileMappings.find(bakedAssetPath); + if (bakedIt != _fileMappings.end()) { + if (bakedIt->second != originalAssetHash) { + qDebug() << "Did find baked version for: " << originalAssetHash << assetPath; + // we found a baked version of the requested asset to serve, redirect to that + redirectedAssetHash = bakedIt->second; + wasRedirected = true; } else { - qDebug() << "Did not find baked version for: " << originalAssetHash << assetPath; + qDebug() << "Did not find baked version for: " << originalAssetHash << assetPath << " (disabled)"; + bakingDisabled = true; } } @@ -684,20 +679,13 @@ void AssetServer::handleGetMappingOperation(ReceivedMessage& message, NLPacketLi auto query = QUrlQuery(url.query()); bool isSkybox = query.hasQueryItem("skybox"); - if (isSkybox) { - bool loaded; - AssetMeta meta; - std::tie(loaded, meta) = readMetaFile(originalAssetHash); - - if (!loaded) { - AssetMeta needsBakingMeta; - needsBakingMeta.bakeVersion = NEEDS_BAKING_BAKE_VERSION; - - writeMetaFile(originalAssetHash, needsBakingMeta); - if (!bakingDisabled) { - maybeBake(assetPath, originalAssetHash); - } + if (isSkybox && !loaded) { + AssetMeta needsBakingMeta; + needsBakingMeta.bakeVersion = NEEDS_BAKING_BAKE_VERSION; + writeMetaFile(originalAssetHash, needsBakingMeta); + if (!bakingDisabled) { + maybeBake(assetPath, originalAssetHash); } } } @@ -1297,14 +1285,6 @@ bool AssetServer::renameMapping(AssetUtils::AssetPath oldPath, AssetUtils::Asset } } -static const QString BAKED_ASSET_SIMPLE_FBX_NAME = "asset.fbx"; -static const QString BAKED_ASSET_SIMPLE_TEXTURE_NAME = "texture.ktx"; -static const QString BAKED_ASSET_SIMPLE_JS_NAME = "asset.js"; - -QString getBakeMapping(const AssetUtils::AssetHash& hash, const QString& relativeFilePath) { - return AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + hash + "/" + relativeFilePath; -} - void AssetServer::handleFailedBake(QString originalAssetHash, QString assetPath, QString errors) { qDebug() << "Failed to bake: " << originalAssetHash << assetPath << "(" << errors << ")"; @@ -1553,10 +1533,18 @@ bool AssetServer::setBakingEnabled(const AssetUtils::AssetPathList& paths, bool if (type == BakedAssetType::Undefined) { continue; } - QString bakedFilename = bakedFilenameForAssetType(type); auto hash = it->second; + + bool loaded; + AssetMeta meta; + std::tie(loaded, meta) = readMetaFile(hash); + + QString bakedFilename = bakedFilenameForAssetType(type); auto bakedMapping = getBakeMapping(hash, bakedFilename); + if (loaded && !meta.redirectTarget.isEmpty()) { + bakedMapping = meta.redirectTarget; + } auto it = _fileMappings.find(bakedMapping); bool currentlyDisabled = (it != _fileMappings.end() && it->second == hash); From 9deb4e47adc0001b8055c0144445ec969f25fdb2 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 23 Apr 2019 08:46:54 -0700 Subject: [PATCH 58/74] comment out warning --- libraries/shared/src/VariantMapToScriptValue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/VariantMapToScriptValue.cpp b/libraries/shared/src/VariantMapToScriptValue.cpp index 437f60a2ed..b3c02d99f4 100644 --- a/libraries/shared/src/VariantMapToScriptValue.cpp +++ b/libraries/shared/src/VariantMapToScriptValue.cpp @@ -44,7 +44,7 @@ QScriptValue variantToScriptValue(QVariant& qValue, QScriptEngine& scriptEngine) if (qValue.canConvert()) { return qValue.toFloat(); } - qCDebug(shared) << "unhandled QScript type" << qValue.type(); + //qCDebug(shared) << "unhandled QScript type" << qValue.type(); break; } From ad22af1379781f2bece4f4a6d5a8a861d2c7015a Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Mon, 22 Apr 2019 19:08:15 -0700 Subject: [PATCH 59/74] set AudioClient mute state as catch-all --- interface/src/scripting/Audio.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index 5dd1488606..b406c097e7 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -352,11 +352,11 @@ void Audio::onContextChanged() { } }); if (_settingsLoaded) { - if (isHMD) { - setMuted(getMutedHMD()); - } else { - setMuted(getMutedDesktop()); - } + bool isMuted = isHMD ? getMutedHMD() : getMutedDesktop(); + setMuted(isMuted); + // always set audio client muted state on context changed - sometimes setMuted does not catch it. + auto client = DependencyManager::get().data(); + QMetaObject::invokeMethod(client, "setMuted", Q_ARG(bool, isMuted), Q_ARG(bool, false)); } if (changed) { emit contextChanged(isHMD ? Audio::HMD : Audio::DESKTOP); From 48aef3e6d9ac0e79967ab18be4ef99c59f2c3951 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 23 Apr 2019 08:45:38 -0700 Subject: [PATCH 60/74] build error --- interface/src/Application.cpp | 10 +++++----- interface/src/ui/Snapshot.cpp | 4 ++-- interface/src/ui/SnapshotAnimated.cpp | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f46d0d3ddd..77c3d438a4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -8441,7 +8441,7 @@ void Application::loadAvatarBrowser() const { void Application::addSnapshotOperator(const SnapshotOperator& snapshotOperator) { std::lock_guard lock(_snapshotMutex); _snapshotOperators.push(snapshotOperator); - _hasPrimarySnapshot |= std::get<2>(snapshotOperator); + _hasPrimarySnapshot = _hasPrimarySnapshot || std::get<2>(snapshotOperator); } bool Application::takeSnapshotOperators(std::queue& snapshotOperators) { @@ -8453,7 +8453,7 @@ bool Application::takeSnapshotOperators(std::queue& snapshotOp } void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { - addSnapshotOperator({ [notify, includeAnimated, aspectRatio, filename](const QImage& snapshot) { + addSnapshotOperator(std::make_tuple([notify, includeAnimated, aspectRatio, filename](const QImage& snapshot) { QString path = DependencyManager::get()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); // If we're not doing an animated snapshot as well... @@ -8468,15 +8468,15 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, DependencyManager::get()); }); } - }, aspectRatio, true }); + }, aspectRatio, true)); } void Application::takeSecondaryCameraSnapshot(const bool& notify, const QString& filename) { - addSnapshotOperator({ [notify, filename](const QImage& snapshot) { + addSnapshotOperator(std::make_tuple([notify, filename](const QImage& snapshot) { QString snapshotPath = DependencyManager::get()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); emit DependencyManager::get()->stillSnapshotTaken(snapshotPath, notify); - }, 0, false }); + }, 0.0f, false)); } void Application::takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat, const bool& notify, const QString& filename) { diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 93d9188cc8..d97c401351 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -168,7 +168,7 @@ void Snapshot::takeNextSnapshot() { if (_taking360Snapshot) { if (!_waitingOnSnapshot) { _waitingOnSnapshot = true; - qApp->addSnapshotOperator({ [this](const QImage& snapshot) { + qApp->addSnapshotOperator(std::make_tuple([this](const QImage& snapshot) { // Order is: // 0. Down // 1. Front @@ -202,7 +202,7 @@ void Snapshot::takeNextSnapshot() { _waitingOnSnapshot = false; _snapshotIndex++; - }, 0, false }); + }, 0.0f, false)); } } else { _snapshotTimer.stop(); diff --git a/interface/src/ui/SnapshotAnimated.cpp b/interface/src/ui/SnapshotAnimated.cpp index f8f6a30635..b8cffca8ab 100644 --- a/interface/src/ui/SnapshotAnimated.cpp +++ b/interface/src/ui/SnapshotAnimated.cpp @@ -60,7 +60,7 @@ void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio void SnapshotAnimated::captureFrames() { if (SnapshotAnimated::snapshotAnimatedTimerRunning) { - qApp->addSnapshotOperator({ [](const QImage& snapshot) { + qApp->addSnapshotOperator(std::make_tuple([](const QImage& snapshot) { // Get a screenshot from the display, then scale the screenshot down, // then convert it to the image format the GIF library needs, // then save all that to the QImage named "frame" @@ -86,7 +86,7 @@ void SnapshotAnimated::captureFrames() { SnapshotAnimated::snapshotAnimatedTimerRunning = false; } } - }, SnapshotAnimated::aspectRatio, true }); + }, SnapshotAnimated::aspectRatio, true)); } else { // Notify the user that we're processing the snapshot // This also pops up the "Share" dialog. The unprocessed GIF will be visualized as a loading icon until processingGifCompleted() is called. From 8a7503ef51a15013c0eee06a270b5c10f57dccfd Mon Sep 17 00:00:00 2001 From: amer cerkic Date: Tue, 23 Apr 2019 11:45:25 -0700 Subject: [PATCH 61/74] turning on blit present for quest --- libraries/oculusMobile/src/ovr/VrHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/oculusMobile/src/ovr/VrHandler.cpp b/libraries/oculusMobile/src/ovr/VrHandler.cpp index a7b0f9f8ee..aff1f256b5 100644 --- a/libraries/oculusMobile/src/ovr/VrHandler.cpp +++ b/libraries/oculusMobile/src/ovr/VrHandler.cpp @@ -28,7 +28,7 @@ static AAssetManager* ASSET_MANAGER = nullptr; -#define USE_BLIT_PRESENT 0 +#define USE_BLIT_PRESENT 1 #if !USE_BLIT_PRESENT From 1c888d63f05bb4635ac7cc1da07709ef3c16698b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 23 Apr 2019 13:44:36 -0700 Subject: [PATCH 62/74] don't try to bake materialURL if it points to materialData --- tools/oven/src/DomainBaker.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/oven/src/DomainBaker.cpp b/tools/oven/src/DomainBaker.cpp index fc065619d7..ee50dc1588 100644 --- a/tools/oven/src/DomainBaker.cpp +++ b/tools/oven/src/DomainBaker.cpp @@ -409,7 +409,10 @@ void DomainBaker::enumerateEntities() { // Materials if (entity.contains(MATERIAL_URL_KEY)) { - addMaterialBaker(MATERIAL_URL_KEY, entity[MATERIAL_URL_KEY].toString(), true, *it); + QString materialURL = entity[MATERIAL_URL_KEY].toString(); + if (!materialURL.startsWith("materialData")) { + addMaterialBaker(MATERIAL_URL_KEY, materialURL, true, *it); + } } if (entity.contains(MATERIAL_DATA_KEY)) { addMaterialBaker(MATERIAL_DATA_KEY, entity[MATERIAL_DATA_KEY].toString(), false, *it, _destinationPath); From b1f00d6f22d6a261218fe11efea94d8e0f99bcd1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 11 Apr 2019 16:41:31 -0700 Subject: [PATCH 63/74] attempt to handle atp redirects from .fbx to .baked.fst --- .../src/material-networking/TextureCache.cpp | 6 +- .../src/model-networking/ModelCache.cpp | 315 ++++++++---------- .../src/model-networking/ModelCache.h | 43 ++- 3 files changed, 171 insertions(+), 193 deletions(-) diff --git a/libraries/material-networking/src/material-networking/TextureCache.cpp b/libraries/material-networking/src/material-networking/TextureCache.cpp index 6ceb5d328a..25e7eeb25d 100644 --- a/libraries/material-networking/src/material-networking/TextureCache.cpp +++ b/libraries/material-networking/src/material-networking/TextureCache.cpp @@ -635,11 +635,9 @@ void NetworkTexture::makeLocalRequest() { } bool NetworkTexture::handleFailedRequest(ResourceRequest::Result result) { - if (_currentlyLoadingResourceType != ResourceType::KTX - && result == ResourceRequest::Result::RedirectFail) { - + if (_shouldFailOnRedirect && result == ResourceRequest::Result::RedirectFail) { auto newPath = _request->getRelativePathUrl(); - if (newPath.fileName().endsWith(".ktx")) { + if (newPath.fileName().toLower().endsWith(".ktx")) { _currentlyLoadingResourceType = ResourceType::KTX; _activeUrl = newPath; _shouldFailOnRedirect = false; diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 26fc0095c5..b914faaab9 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -31,8 +31,6 @@ Q_LOGGING_CATEGORY(trace_resource_parse_geometry, "trace.resource.parse.geometry") -class GeometryReader; - class GeometryExtra { public: const GeometryMappingPair& mapping; @@ -87,113 +85,6 @@ namespace std { }; } -QUrl resolveTextureBaseUrl(const QUrl& url, const QUrl& textureBaseUrl) { - return textureBaseUrl.isValid() ? textureBaseUrl : url; -} - -class GeometryMappingResource : public GeometryResource { - Q_OBJECT -public: - GeometryMappingResource(const QUrl& url) : GeometryResource(url) {}; - - QString getType() const override { return "GeometryMapping"; } - - virtual void downloadFinished(const QByteArray& data) override; - -private slots: - void onGeometryMappingLoaded(bool success); - -private: - GeometryResource::Pointer _geometryResource; - QMetaObject::Connection _connection; -}; - -void GeometryMappingResource::downloadFinished(const QByteArray& data) { - PROFILE_ASYNC_BEGIN(resource_parse_geometry, "GeometryMappingResource::downloadFinished", _url.toString(), - { { "url", _url.toString() } }); - - // store parsed contents of FST file - _mapping = FSTReader::readMapping(data); - - QString filename = _mapping.value("filename").toString(); - - if (filename.isNull()) { - finishedLoading(false); - } else { - const QString baseURL = _mapping.value("baseURL").toString(); - const QUrl base = _effectiveBaseURL.resolved(baseURL); - QUrl url = base.resolved(filename); - - QString texdir = _mapping.value(TEXDIR_FIELD).toString(); - if (!texdir.isNull()) { - if (!texdir.endsWith('/')) { - texdir += '/'; - } - _textureBaseUrl = resolveTextureBaseUrl(url, base.resolved(texdir)); - } else { - _textureBaseUrl = url.resolved(QUrl(".")); - } - - auto scripts = FSTReader::getScripts(base, _mapping); - if (scripts.size() > 0) { - _mapping.remove(SCRIPT_FIELD); - for (auto &scriptPath : scripts) { - _mapping.insertMulti(SCRIPT_FIELD, scriptPath); - } - } - - auto animGraphVariant = _mapping.value("animGraphUrl"); - - if (animGraphVariant.isValid()) { - QUrl fstUrl(animGraphVariant.toString()); - if (fstUrl.isValid()) { - _animGraphOverrideUrl = base.resolved(fstUrl); - } else { - _animGraphOverrideUrl = QUrl(); - } - } else { - _animGraphOverrideUrl = QUrl(); - } - - auto modelCache = DependencyManager::get(); - GeometryExtra extra { GeometryMappingPair(base, _mapping), _textureBaseUrl, false }; - - // Get the raw GeometryResource - _geometryResource = modelCache->getResource(url, QUrl(), &extra, std::hash()(extra)).staticCast(); - // Avoid caching nested resources - their references will be held by the parent - _geometryResource->_isCacheable = false; - - if (_geometryResource->isLoaded()) { - onGeometryMappingLoaded(!_geometryResource->getURL().isEmpty()); - } else { - if (_connection) { - disconnect(_connection); - } - - _connection = connect(_geometryResource.data(), &Resource::finished, - this, &GeometryMappingResource::onGeometryMappingLoaded); - } - } -} - -void GeometryMappingResource::onGeometryMappingLoaded(bool success) { - if (success && _geometryResource) { - _hfmModel = _geometryResource->_hfmModel; - _materialMapping = _geometryResource->_materialMapping; - _meshParts = _geometryResource->_meshParts; - _meshes = _geometryResource->_meshes; - _materials = _geometryResource->_materials; - - // Avoid holding onto extra references - _geometryResource.reset(); - // Make sure connection will not trigger again - disconnect(_connection); // FIXME Should not have to do this - } - - PROFILE_ASYNC_END(resource_parse_geometry, "GeometryMappingResource::downloadFinished", _url.toString()); - finishedLoading(success); -} - class GeometryReader : public QRunnable { public: GeometryReader(const ModelLoader& modelLoader, QWeakPointer& resource, const QUrl& url, const GeometryMappingPair& mapping, @@ -308,47 +199,137 @@ void GeometryReader::run() { } } -class GeometryDefinitionResource : public GeometryResource { - Q_OBJECT -public: - GeometryDefinitionResource(const ModelLoader& modelLoader, const QUrl& url) : GeometryResource(url), _modelLoader(modelLoader) {} - GeometryDefinitionResource(const GeometryDefinitionResource& other) : - GeometryResource(other), - _modelLoader(other._modelLoader), - _mapping(other._mapping), - _combineParts(other._combineParts) {} +QUrl resolveTextureBaseUrl(const QUrl& url, const QUrl& textureBaseUrl) { + return textureBaseUrl.isValid() ? textureBaseUrl : url; +} - QString getType() const override { return "GeometryDefinition"; } +GeometryResource::GeometryResource(const GeometryResource& other) : + Resource(other), + Geometry(other), + _modelLoader(other._modelLoader), + _mappingPair(other._mappingPair), + _textureBaseURL(other._textureBaseURL), + _combineParts(other._combineParts), + _isCacheable(other._isCacheable) +{ + if (other._geometryResource) { + _startedLoading = false; + } +} - virtual void downloadFinished(const QByteArray& data) override; +void GeometryResource::downloadFinished(const QByteArray& data) { + if (_activeUrl.fileName().toLower().endsWith(".fst")) { + PROFILE_ASYNC_BEGIN(resource_parse_geometry, "GeometryResource::downloadFinished", _url.toString(), { { "url", _url.toString() } }); - void setExtra(void* extra) override; + // store parsed contents of FST file + _mapping = FSTReader::readMapping(data); -protected: - Q_INVOKABLE void setGeometryDefinition(HFMModel::Pointer hfmModel, const MaterialMapping& materialMapping); + QString filename = _mapping.value("filename").toString(); -private: - ModelLoader _modelLoader; - GeometryMappingPair _mapping; - bool _combineParts; -}; + if (filename.isNull()) { + finishedLoading(false); + } else { + const QString baseURL = _mapping.value("baseURL").toString(); + const QUrl base = _effectiveBaseURL.resolved(baseURL); + QUrl url = base.resolved(filename); -void GeometryDefinitionResource::setExtra(void* extra) { + QString texdir = _mapping.value(TEXDIR_FIELD).toString(); + if (!texdir.isNull()) { + if (!texdir.endsWith('/')) { + texdir += '/'; + } + _textureBaseURL = resolveTextureBaseUrl(url, base.resolved(texdir)); + } else { + _textureBaseURL = url.resolved(QUrl(".")); + } + + auto scripts = FSTReader::getScripts(base, _mapping); + if (scripts.size() > 0) { + _mapping.remove(SCRIPT_FIELD); + for (auto &scriptPath : scripts) { + _mapping.insertMulti(SCRIPT_FIELD, scriptPath); + } + } + + auto animGraphVariant = _mapping.value("animGraphUrl"); + + if (animGraphVariant.isValid()) { + QUrl fstUrl(animGraphVariant.toString()); + if (fstUrl.isValid()) { + _animGraphOverrideUrl = base.resolved(fstUrl); + } else { + _animGraphOverrideUrl = QUrl(); + } + } else { + _animGraphOverrideUrl = QUrl(); + } + + auto modelCache = DependencyManager::get(); + GeometryExtra extra { GeometryMappingPair(base, _mapping), _textureBaseURL, false }; + + // Get the raw GeometryResource + _geometryResource = modelCache->getResource(url, QUrl(), &extra, std::hash()(extra)).staticCast(); + // Avoid caching nested resources - their references will be held by the parent + _geometryResource->_isCacheable = false; + + if (_geometryResource->isLoaded()) { + onGeometryMappingLoaded(!_geometryResource->getURL().isEmpty()); + } else { + if (_connection) { + disconnect(_connection); + } + + _connection = connect(_geometryResource.data(), &Resource::finished, this, &GeometryResource::onGeometryMappingLoaded); + } + } + } else { + if (_url != _effectiveBaseURL) { + _url = _effectiveBaseURL; + _textureBaseURL = _effectiveBaseURL; + } + QThreadPool::globalInstance()->start(new GeometryReader(_modelLoader, _self, _effectiveBaseURL, _mappingPair, data, _combineParts, _request->getWebMediaType())); + } +} + +bool GeometryResource::handleFailedRequest(ResourceRequest::Result result) { + if (_shouldFailOnRedirect && result == ResourceRequest::Result::RedirectFail) { + auto newPath = _request->getRelativePathUrl(); + if (newPath.fileName().toLower().endsWith(".fst")) { + _activeUrl = newPath; + _shouldFailOnRedirect = false; + makeRequest(); + return true; + } + } + return Resource::handleFailedRequest(result); +} + +void GeometryResource::onGeometryMappingLoaded(bool success) { + if (success && _geometryResource) { + _hfmModel = _geometryResource->_hfmModel; + _materialMapping = _geometryResource->_materialMapping; + _meshParts = _geometryResource->_meshParts; + _meshes = _geometryResource->_meshes; + _materials = _geometryResource->_materials; + + // Avoid holding onto extra references + _geometryResource.reset(); + // Make sure connection will not trigger again + disconnect(_connection); // FIXME Should not have to do this + } + + PROFILE_ASYNC_END(resource_parse_geometry, "GeometryResource::downloadFinished", _url.toString()); + finishedLoading(success); +} + +void GeometryResource::setExtra(void* extra) { const GeometryExtra* geometryExtra = static_cast(extra); - _mapping = geometryExtra ? geometryExtra->mapping : GeometryMappingPair(QUrl(), QVariantHash()); - _textureBaseUrl = geometryExtra ? resolveTextureBaseUrl(_url, geometryExtra->textureBaseUrl) : QUrl(); + _mappingPair = geometryExtra ? geometryExtra->mapping : GeometryMappingPair(QUrl(), QVariantHash()); + _textureBaseURL = geometryExtra ? resolveTextureBaseUrl(_url, geometryExtra->textureBaseUrl) : QUrl(); _combineParts = geometryExtra ? geometryExtra->combineParts : true; } -void GeometryDefinitionResource::downloadFinished(const QByteArray& data) { - if (_url != _effectiveBaseURL) { - _url = _effectiveBaseURL; - _textureBaseUrl = _effectiveBaseURL; - } - QThreadPool::globalInstance()->start(new GeometryReader(_modelLoader, _self, _effectiveBaseURL, _mapping, data, _combineParts, _request->getWebMediaType())); -} - -void GeometryDefinitionResource::setGeometryDefinition(HFMModel::Pointer hfmModel, const MaterialMapping& materialMapping) { +void GeometryResource::setGeometryDefinition(HFMModel::Pointer hfmModel, const MaterialMapping& materialMapping) { // Assume ownership of the processed HFMModel _hfmModel = hfmModel; _materialMapping = materialMapping; @@ -357,7 +338,7 @@ void GeometryDefinitionResource::setGeometryDefinition(HFMModel::Pointer hfmMode QHash materialIDAtlas; for (const HFMMaterial& material : _hfmModel->materials) { materialIDAtlas[material.materialID] = _materials.size(); - _materials.push_back(std::make_shared(material, _textureBaseUrl)); + _materials.push_back(std::make_shared(material, _textureBaseURL)); } std::shared_ptr meshes = std::make_shared(); @@ -380,6 +361,23 @@ void GeometryDefinitionResource::setGeometryDefinition(HFMModel::Pointer hfmMode finishedLoading(true); } +void GeometryResource::deleter() { + resetTextures(); + Resource::deleter(); +} + +void GeometryResource::setTextures() { + if (_hfmModel) { + for (const HFMMaterial& material : _hfmModel->materials) { + _materials.push_back(std::make_shared(material, _textureBaseURL)); + } + } +} + +void GeometryResource::resetTextures() { + _materials.clear(); +} + ModelCache::ModelCache() { const qint64 GEOMETRY_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; setUnusedResourceCacheSize(GEOMETRY_DEFAULT_UNUSED_MAX_SIZE); @@ -392,26 +390,14 @@ ModelCache::ModelCache() { } QSharedPointer ModelCache::createResource(const QUrl& url) { - Resource* resource = nullptr; - if (url.path().toLower().endsWith(".fst")) { - resource = new GeometryMappingResource(url); - } else { - resource = new GeometryDefinitionResource(_modelLoader, url); - } - - return QSharedPointer(resource, &Resource::deleter); + return QSharedPointer(new GeometryResource(url, _modelLoader), &GeometryResource::deleter); } QSharedPointer ModelCache::createResourceCopy(const QSharedPointer& resource) { - if (resource->getURL().path().toLower().endsWith(".fst")) { - return QSharedPointer(new GeometryMappingResource(*resource.staticCast()), &Resource::deleter); - } else { - return QSharedPointer(new GeometryDefinitionResource(*resource.staticCast()), &Resource::deleter); - } + return QSharedPointer(new GeometryResource(*resource.staticCast()), &GeometryResource::deleter); } -GeometryResource::Pointer ModelCache::getGeometryResource(const QUrl& url, - const GeometryMappingPair& mapping, const QUrl& textureBaseUrl) { +GeometryResource::Pointer ModelCache::getGeometryResource(const QUrl& url, const GeometryMappingPair& mapping, const QUrl& textureBaseUrl) { bool combineParts = true; GeometryExtra geometryExtra = { mapping, textureBaseUrl, combineParts }; GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra, std::hash()(geometryExtra)).staticCast(); @@ -531,23 +517,6 @@ const std::shared_ptr Geometry::getShapeMaterial(int partID) co return nullptr; } -void GeometryResource::deleter() { - resetTextures(); - Resource::deleter(); -} - -void GeometryResource::setTextures() { - if (_hfmModel) { - for (const HFMMaterial& material : _hfmModel->materials) { - _materials.push_back(std::make_shared(material, _textureBaseUrl)); - } - } -} - -void GeometryResource::resetTextures() { - _materials.clear(); -} - void GeometryResourceWatcher::startWatching() { connect(_resource.data(), &Resource::finished, this, &GeometryResourceWatcher::resourceFinished); connect(_resource.data(), &Resource::onRefresh, this, &GeometryResourceWatcher::resourceRefreshed); diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index ca1ceaff16..034a00912a 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -24,8 +24,6 @@ class MeshPart; -class GeometryMappingResource; - using GeometryMappingPair = std::pair; Q_DECLARE_METATYPE(GeometryMappingPair) @@ -60,8 +58,6 @@ public: const QVariantHash& getMapping() const { return _mapping; } protected: - friend class GeometryMappingResource; - // Shared across all geometries, constant throughout lifetime std::shared_ptr _hfmModel; MaterialMapping _materialMapping; @@ -80,23 +76,30 @@ private: /// A geometry loaded from the network. class GeometryResource : public Resource, public Geometry { + Q_OBJECT public: using Pointer = QSharedPointer; - GeometryResource(const QUrl& url) : Resource(url) {} - GeometryResource(const GeometryResource& other) : - Resource(other), - Geometry(other), - _textureBaseUrl(other._textureBaseUrl), - _isCacheable(other._isCacheable) {} + GeometryResource(const QUrl& url, const ModelLoader& modelLoader) : Resource(url), _modelLoader(modelLoader) { _shouldFailOnRedirect = !url.fileName().toLower().endsWith(".fst"); } + GeometryResource(const GeometryResource& other); - virtual bool areTexturesLoaded() const override { return isLoaded() && Geometry::areTexturesLoaded(); } + QString getType() const override { return "Geometry"; } virtual void deleter() override; + virtual void downloadFinished(const QByteArray& data) override; + bool handleFailedRequest(ResourceRequest::Result result) override; + void setExtra(void* extra) override; + + virtual bool areTexturesLoaded() const override { return isLoaded() && Geometry::areTexturesLoaded(); } + +private slots: + void onGeometryMappingLoaded(bool success); + protected: friend class ModelCache; - friend class GeometryMappingResource; + + Q_INVOKABLE void setGeometryDefinition(HFMModel::Pointer hfmModel, const MaterialMapping& materialMapping); // Geometries may not hold onto textures while cached - that is for the texture cache // Instead, these methods clear and reset textures from the geometry when caching/loading @@ -104,10 +107,18 @@ protected: void setTextures(); void resetTextures(); - QUrl _textureBaseUrl; - virtual bool isCacheable() const override { return _loaded && _isCacheable; } - bool _isCacheable { true }; + +private: + ModelLoader _modelLoader; + GeometryMappingPair _mappingPair; + QUrl _textureBaseURL; + bool _combineParts; + + GeometryResource::Pointer _geometryResource; + QMetaObject::Connection _connection; + + bool _isCacheable{ true }; }; class GeometryResourceWatcher : public QObject { @@ -158,7 +169,7 @@ public: const QUrl& textureBaseUrl = QUrl()); protected: - friend class GeometryMappingResource; + friend class GeometryResource; virtual QSharedPointer createResource(const QUrl& url) override; QSharedPointer createResourceCopy(const QSharedPointer& resource) override; From 3605b3d560ef4fa56619a351384f305cf1b9e14e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 12 Apr 2019 15:49:34 -0700 Subject: [PATCH 64/74] Patch interface redirect code --- .../src/model-networking/ModelCache.cpp | 15 +-------------- .../src/model-networking/ModelCache.h | 3 +-- libraries/networking/src/ResourceCache.cpp | 1 + 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index b914faaab9..26bd20d967 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -218,7 +218,7 @@ GeometryResource::GeometryResource(const GeometryResource& other) : } void GeometryResource::downloadFinished(const QByteArray& data) { - if (_activeUrl.fileName().toLower().endsWith(".fst")) { + if (_effectiveBaseURL.fileName().toLower().endsWith(".fst")) { PROFILE_ASYNC_BEGIN(resource_parse_geometry, "GeometryResource::downloadFinished", _url.toString(), { { "url", _url.toString() } }); // store parsed contents of FST file @@ -291,19 +291,6 @@ void GeometryResource::downloadFinished(const QByteArray& data) { } } -bool GeometryResource::handleFailedRequest(ResourceRequest::Result result) { - if (_shouldFailOnRedirect && result == ResourceRequest::Result::RedirectFail) { - auto newPath = _request->getRelativePathUrl(); - if (newPath.fileName().toLower().endsWith(".fst")) { - _activeUrl = newPath; - _shouldFailOnRedirect = false; - makeRequest(); - return true; - } - } - return Resource::handleFailedRequest(result); -} - void GeometryResource::onGeometryMappingLoaded(bool success) { if (success && _geometryResource) { _hfmModel = _geometryResource->_hfmModel; diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 034a00912a..f9ae2dccd6 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -80,7 +80,7 @@ class GeometryResource : public Resource, public Geometry { public: using Pointer = QSharedPointer; - GeometryResource(const QUrl& url, const ModelLoader& modelLoader) : Resource(url), _modelLoader(modelLoader) { _shouldFailOnRedirect = !url.fileName().toLower().endsWith(".fst"); } + GeometryResource(const QUrl& url, const ModelLoader& modelLoader) : Resource(url), _modelLoader(modelLoader) {} GeometryResource(const GeometryResource& other); QString getType() const override { return "Geometry"; } @@ -88,7 +88,6 @@ public: virtual void deleter() override; virtual void downloadFinished(const QByteArray& data) override; - bool handleFailedRequest(ResourceRequest::Result result) override; void setExtra(void* extra) override; virtual bool areTexturesLoaded() const override { return isLoaded() && Geometry::areTexturesLoaded(); } diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index d5abb27a27..746c28a306 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -577,6 +577,7 @@ Resource::Resource(const Resource& other) : Resource::Resource(const QUrl& url) : _url(url), _activeUrl(url), + _effectiveBaseURL(url), _requestID(++requestID) { init(); } From 329a76d4d67000372b0dd8ed83cba9b8af33cc9d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 12 Apr 2019 17:51:03 -0700 Subject: [PATCH 65/74] Fix unix warning --- libraries/networking/src/ResourceCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 746c28a306..44d3d1ee4d 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -576,8 +576,8 @@ Resource::Resource(const Resource& other) : Resource::Resource(const QUrl& url) : _url(url), - _activeUrl(url), _effectiveBaseURL(url), + _activeUrl(url), _requestID(++requestID) { init(); } From 77c5ea5fa8ef93abbad02cd74c6347d3e150fa45 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 15 Apr 2019 19:08:44 -0700 Subject: [PATCH 66/74] Fix Asset Server reporting bad status for textures --- assignment-client/src/assets/AssetServer.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 4805d2fe4c..297a622c25 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -146,7 +146,6 @@ std::pair AssetServer::getAssetStatus(const A } BakedAssetType type = assetTypeForFilename(path); - if (type == BakedAssetType::Undefined) { return { AssetUtils::Irrelevant, "" }; } @@ -155,6 +154,12 @@ std::pair AssetServer::getAssetStatus(const A AssetMeta meta; std::tie(loaded, meta) = readMetaFile(hash); + // We create a meta file for Skyboxes at runtime when they get requested + // Otherwise, textures don't get baked by themselves. + if (type == BakedAssetType::Texture && !loaded) { + return { AssetUtils::Irrelevant, "" }; + } + QString bakedFilename = bakedFilenameForAssetType(type); auto bakedPath = getBakeMapping(hash, bakedFilename); if (loaded && !meta.redirectTarget.isEmpty()) { @@ -240,6 +245,8 @@ bool AssetServer::needsToBeBaked(const AssetUtils::AssetPath& path, const AssetU return false; } + // We create a meta file for Skyboxes at runtime when they get requested + // Otherwise, textures don't get baked by themselves. if (type == BakedAssetType::Texture && !loaded) { return false; } From 86b63410989314ae69651d2d3c2ad3571f882cb6 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 16 Apr 2019 19:40:59 -0700 Subject: [PATCH 67/74] Add error reporting + Make temp dir erase safer --- assignment-client/src/assets/AssetServer.cpp | 91 ++++++++++++------- .../src/assets/BakeAssetTask.cpp | 54 +++++------ libraries/shared/src/PathUtils.cpp | 24 +++++ libraries/shared/src/PathUtils.h | 1 + 4 files changed, 102 insertions(+), 68 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 297a622c25..502cf15aa2 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -1314,27 +1314,57 @@ void AssetServer::handleFailedBake(QString originalAssetHash, QString assetPath, void AssetServer::handleCompletedBake(QString originalAssetHash, QString originalAssetPath, QString bakedTempOutputDir) { + auto reportCompletion = [this, originalAssetPath, originalAssetHash](bool errorCompletingBake, + QString errorReason, + QString redirectTarget) { + auto type = assetTypeForFilename(originalAssetPath); + auto currentTypeVersion = currentBakeVersionForAssetType(type); + + AssetMeta meta; + meta.bakeVersion = currentTypeVersion; + meta.failedLastBake = errorCompletingBake; + meta.redirectTarget = redirectTarget; + + if (errorCompletingBake) { + qWarning() << "Could not complete bake for" << originalAssetHash; + meta.lastBakeErrors = errorReason; + } + + writeMetaFile(originalAssetHash, meta); + + _pendingBakes.remove(originalAssetHash); + }; + bool errorCompletingBake { false }; QString errorReason; + QString redirectTarget; qDebug() << "Completing bake for " << originalAssetHash; - - + // Find the directory containing the baked content QDir outputDir(bakedTempOutputDir); + QString outputDirName = outputDir.dirName(); auto directories = outputDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - assert(directories.size() == 1); QString bakedDirectoryPath; for (const auto& dirName : directories) { outputDir.cd(dirName); if (outputDir.exists("baked") && outputDir.exists("original")) { bakedDirectoryPath = outputDir.filePath("baked"); + break; } outputDir.cdUp(); } + if (bakedDirectoryPath.isEmpty()) { + errorCompletingBake = true; + errorReason = "Failed to find baking output"; - assert(!bakedDirectoryPath.isEmpty()); + // Cleanup temporary output directory + PathUtils::deleteMyTemporaryDir(outputDirName); + reportCompletion(errorCompletingBake, errorReason, redirectTarget); + return; + } + // Compile list of all the baked files QDirIterator it(bakedDirectoryPath, QDirIterator::Subdirectories); QVector bakedFilePaths; while (it.hasNext()) { @@ -1343,9 +1373,17 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina bakedFilePaths.push_back(it.filePath()); } } + if (bakedFilePaths.isEmpty()) { + errorCompletingBake = true; + errorReason = "Baking output has no files"; + + // Cleanup temporary output directory + PathUtils::deleteMyTemporaryDir(outputDirName); + reportCompletion(errorCompletingBake, errorReason, redirectTarget); + return; + } QDir bakedDirectory(bakedDirectoryPath); - QString redirectTarget; for (auto& filePath : bakedFilePaths) { // figure out the hash for the contents of this file @@ -1359,7 +1397,7 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina qDebug() << "Failed to open baked file: " << filePath; // stop handling this bake, we couldn't open one of the files for reading errorCompletingBake = true; - errorReason = "Failed to finalize bake"; + errorReason = "Could not open baked file " + file.fileName(); break; } @@ -1368,7 +1406,7 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina if (!hasher.addData(&file)) { // stop handling this bake, couldn't hash the contents of the file errorCompletingBake = true; - errorReason = "Failed to finalize bake"; + errorReason = "Could not hash data for " + file.fileName(); break; } @@ -1388,13 +1426,15 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina // setup the mapping for this bake file auto relativeFilePath = bakedDirectory.relativeFilePath(filePath); - qDebug() << "Relative file path is: " << relativeFilePath; QString bakeMapping = getBakeMapping(originalAssetHash, relativeFilePath); // Check if this is the file we should redirect to when someone asks for the original asset if ((relativeFilePath.endsWith(".baked.fst", Qt::CaseInsensitive) && originalAssetPath.endsWith(".fbx")) || (relativeFilePath.endsWith(".texmeta.json", Qt::CaseInsensitive) && !originalAssetPath.endsWith(".fbx"))) { + if (!redirectTarget.isEmpty()) { + qWarning() << "Found multiple baked redirect target for" << originalAssetPath; + } redirectTarget = bakeMapping; } @@ -1403,41 +1443,22 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina qDebug() << "Failed to set mapping"; // stop handling this bake, couldn't add a mapping for this bake file errorCompletingBake = true; - errorReason = "Failed to finalize bake"; + errorReason = "Failed to set mapping for baked file " + file.fileName(); break; } qDebug() << "Added" << bakeMapping << "for bake file" << bakedFileHash << "from bake of" << originalAssetHash; } - for (auto& filePath : bakedFilePaths) { - QFile file(filePath); - if (!file.remove()) { - qWarning() << "Failed to remove temporary file:" << filePath; - } - } - if (!QDir(bakedTempOutputDir).rmdir(".")) { - qWarning() << "Failed to remove temporary directory:" << bakedTempOutputDir; + + if (redirectTarget.isEmpty()) { + errorCompletingBake = true; + errorReason = "Could not find root file for baked output"; } - auto type = assetTypeForFilename(originalAssetPath); - auto currentTypeVersion = currentBakeVersionForAssetType(type); - - assert(!redirectTarget.isEmpty()); - - AssetMeta meta; - meta.bakeVersion = currentTypeVersion; - meta.failedLastBake = errorCompletingBake; - meta.redirectTarget = redirectTarget; - - if (errorCompletingBake) { - qWarning() << "Could not complete bake for" << originalAssetHash; - meta.lastBakeErrors = errorReason; - } - - writeMetaFile(originalAssetHash, meta); - - _pendingBakes.remove(originalAssetHash); + // Cleanup temporary output directory + PathUtils::deleteMyTemporaryDir(outputDirName); + reportCompletion(errorCompletingBake, errorReason, redirectTarget); } void AssetServer::handleAbortedBake(QString originalAssetHash, QString assetPath) { diff --git a/assignment-client/src/assets/BakeAssetTask.cpp b/assignment-client/src/assets/BakeAssetTask.cpp index 7ca87fe4e3..99fff4f180 100644 --- a/assignment-client/src/assets/BakeAssetTask.cpp +++ b/assignment-client/src/assets/BakeAssetTask.cpp @@ -36,21 +36,6 @@ BakeAssetTask::BakeAssetTask(const AssetUtils::AssetHash& assetHash, const Asset }); } -void cleanupTempFiles(QString tempOutputDir, std::vector files) { - for (const auto& filename : files) { - QFile f { filename }; - if (!f.remove()) { - qDebug() << "Failed to remove:" << filename; - } - } - if (!tempOutputDir.isEmpty()) { - QDir dir { tempOutputDir }; - if (!dir.rmdir(".")) { - qDebug() << "Failed to remove temporary directory:" << tempOutputDir; - } - } -}; - void BakeAssetTask::run() { if (_isBaking.exchange(true)) { qWarning() << "Tried to start bake asset task while already baking"; @@ -59,11 +44,24 @@ void BakeAssetTask::run() { // Make a new temporary directory for the Oven to work in QString tempOutputDir = PathUtils::generateTemporaryDir(); + QString tempOutputDirName = QDir(tempOutputDir).dirName(); + if (tempOutputDir.isEmpty()) { + QString errors = "Could not create temporary working directory"; + emit bakeFailed(_assetHash, _assetPath, errors); + PathUtils::deleteMyTemporaryDir(tempOutputDirName); + return; + } // Copy file to bake the temporary dir and give a name the oven can work with auto assetName = _assetPath.split("/").last(); auto tempAssetPath = tempOutputDir + "/" + assetName; - QFile::copy(_filePath, tempAssetPath); + auto sucess = QFile::copy(_filePath, tempAssetPath); + if (!sucess) { + QString errors = "Couldn't copy file to bake to temporary directory"; + emit bakeFailed(_assetHash, _assetPath, errors); + PathUtils::deleteMyTemporaryDir(tempOutputDirName); + return; + } auto base = QFileInfo(QCoreApplication::applicationFilePath()).absoluteDir(); QString path = base.absolutePath() + "/oven"; @@ -79,30 +77,23 @@ void BakeAssetTask::run() { QEventLoop loop; connect(_ovenProcess.get(), static_cast(&QProcess::finished), - this, [&loop, this, tempOutputDir, tempAssetPath](int exitCode, QProcess::ExitStatus exitStatus) { + this, [&loop, this, tempOutputDir, tempAssetPath, tempOutputDirName](int exitCode, QProcess::ExitStatus exitStatus) { qDebug() << "Baking process finished: " << exitCode << exitStatus; if (exitStatus == QProcess::CrashExit) { + PathUtils::deleteMyTemporaryDir(tempOutputDirName); if (_wasAborted) { emit bakeAborted(_assetHash, _assetPath); } else { QString errors = "Fatal error occurred while baking"; emit bakeFailed(_assetHash, _assetPath, errors); } - if (!QDir(tempOutputDir).rmdir(".")) { - qWarning() << "Failed to remove temporary directory:" << tempOutputDir; - } } else if (exitCode == OVEN_STATUS_CODE_SUCCESS) { - // Remove temp copy of the original asset - QFile::remove(tempAssetPath); - emit bakeComplete(_assetHash, _assetPath, tempOutputDir); } else if (exitStatus == QProcess::NormalExit && exitCode == OVEN_STATUS_CODE_ABORT) { _wasAborted.store(true); + PathUtils::deleteMyTemporaryDir(tempOutputDirName); emit bakeAborted(_assetHash, _assetPath); - if (!QDir(tempOutputDir).rmdir(".")) { - qWarning() << "Failed to remove temporary directory:" << tempOutputDir; - } } else { QString errors; if (exitCode == OVEN_STATUS_CODE_FAIL) { @@ -116,10 +107,8 @@ void BakeAssetTask::run() { errors = "Unknown error occurred while baking"; } } + PathUtils::deleteMyTemporaryDir(tempOutputDirName); emit bakeFailed(_assetHash, _assetPath, errors); - if (!QDir(tempOutputDir).rmdir(".")) { - qWarning() << "Failed to remove temporary directory:" << tempOutputDir; - } } loop.quit(); @@ -128,12 +117,11 @@ void BakeAssetTask::run() { qDebug() << "Starting oven for " << _assetPath; _ovenProcess->start(path, args, QIODevice::ReadOnly); qDebug() << "Running:" << path << args; - if (!_ovenProcess->waitForStarted(-1)) { + if (!_ovenProcess->waitForStarted()) { + PathUtils::deleteMyTemporaryDir(tempOutputDirName); + QString errors = "Oven process failed to start"; emit bakeFailed(_assetHash, _assetPath, errors); - if (!QDir(tempOutputDir).rmdir(".")) { - qWarning() << "Failed to remove temporary directory:" << tempOutputDir; - } return; } diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp index 60b426e46d..be60533406 100644 --- a/libraries/shared/src/PathUtils.cpp +++ b/libraries/shared/src/PathUtils.cpp @@ -185,6 +185,30 @@ QString PathUtils::generateTemporaryDir() { return ""; } +bool PathUtils::deleteMyTemporaryDir(QString dirName) { + QDir rootTempDir = QDir::tempPath(); + + QString appName = qApp->applicationName(); + QRegularExpression re { "^" + QRegularExpression::escape(appName) + "\\-(?\\d+)\\-(?\\d+)$" }; + + auto match = re.match(dirName); + auto pid = match.capturedRef("pid").toLongLong(); + + if (match.hasMatch() && rootTempDir.exists(dirName) && pid == qApp->applicationPid()) { + auto absoluteDirPath = QDir(rootTempDir.absoluteFilePath(dirName)); + + bool success = absoluteDirPath.removeRecursively(); + if (success) { + qDebug() << " Removing temporary directory: " << absoluteDirPath.absolutePath(); + } else { + qDebug() << " Failed to remove temporary directory: " << absoluteDirPath.absolutePath(); + } + return success; + } + + return false; +} + // Delete all temporary directories for an application int PathUtils::removeTemporaryApplicationDirs(QString appName) { if (appName.isNull()) { diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h index 0096cb6c90..cac5c58ca4 100644 --- a/libraries/shared/src/PathUtils.h +++ b/libraries/shared/src/PathUtils.h @@ -56,6 +56,7 @@ public: static QString getAppLocalDataFilePath(const QString& filename); static QString generateTemporaryDir(); + static bool deleteMyTemporaryDir(QString dirName); static int removeTemporaryApplicationDirs(QString appName = QString::null); From 2c3dd153dd5e9a54707e876e82e569df67439272 Mon Sep 17 00:00:00 2001 From: Clement Date: Wed, 17 Apr 2019 12:57:15 -0700 Subject: [PATCH 68/74] Fix typo --- assignment-client/src/assets/BakeAssetTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/assets/BakeAssetTask.cpp b/assignment-client/src/assets/BakeAssetTask.cpp index 99fff4f180..7c845f9b38 100644 --- a/assignment-client/src/assets/BakeAssetTask.cpp +++ b/assignment-client/src/assets/BakeAssetTask.cpp @@ -55,8 +55,8 @@ void BakeAssetTask::run() { // Copy file to bake the temporary dir and give a name the oven can work with auto assetName = _assetPath.split("/").last(); auto tempAssetPath = tempOutputDir + "/" + assetName; - auto sucess = QFile::copy(_filePath, tempAssetPath); - if (!sucess) { + auto success = QFile::copy(_filePath, tempAssetPath); + if (!success) { QString errors = "Couldn't copy file to bake to temporary directory"; emit bakeFailed(_assetHash, _assetPath, errors); PathUtils::deleteMyTemporaryDir(tempOutputDirName); From 464e5924d62875ad475317525a6cf60735c7b15b Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Tue, 23 Apr 2019 16:50:54 -0700 Subject: [PATCH 69/74] changing method name to reflect recent change in code --- .../resources/qml/hifi/commerce/marketplace/Marketplace.qml | 2 +- interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml index 5f8cc2eefb..65453ba21d 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml @@ -952,7 +952,7 @@ Rectangle { text: "LOG IN" onClicked: { - sendToScript({method: 'needsLogIn_loginClicked'}); + sendToScript({method: 'marketplace_loginClicked'}); } } diff --git a/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml b/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml index 0a1593161a..e17196b492 100644 --- a/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml +++ b/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml @@ -137,7 +137,7 @@ Item { width: parent.width/2 - anchors.leftMargin*2; text: "Cancel" onClicked: { - sendToScript({method: 'needsLogIn_cancelClicked'}); + sendToScript({method: 'passphrasePopup_cancelClicked'}); } } @@ -155,7 +155,7 @@ Item { width: parent.width/2 - anchors.rightMargin*2; text: "Log In" onClicked: { - sendToScript({method: 'needsLogIn_loginClicked'}); + sendToScript({method: 'marketplace_loginClicked'}); } } } From 084759a91853575cdfe61bbafaf9d485dc9dcd55 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 24 Apr 2019 16:32:39 -0700 Subject: [PATCH 70/74] send update after changing entity --- interface/src/avatar/MyAvatar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 25c7a788b3..0680c22774 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1630,7 +1630,9 @@ void MyAvatar::handleChangedAvatarEntityData() { if (!skip) { sanitizeAvatarEntityProperties(properties); entityTree->withWriteLock([&] { - entityTree->updateEntity(id, properties); + if (entityTree->updateEntity(id, properties)) { + packetSender->queueEditAvatarEntityMessage(entityTree, id); + } }); } } From 31b3f0e8f1faa8f9e4a2d89c2375607deaed2fb3 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 23 Apr 2019 17:34:46 -0700 Subject: [PATCH 71/74] possible fix for openUrl exploit --- .../qml/LoginDialog/CompleteProfileBody.qml | 2 +- .../qml/LoginDialog/LinkAccountBody.qml | 2 +- .../resources/qml/LoginDialog/SignUpBody.qml | 2 +- .../qml/LoginDialog/UsernameCollisionBody.qml | 2 +- interface/src/Application.cpp | 40 ++++++++++++------- interface/src/Application.h | 4 +- .../scripting/WindowScriptingInterface.cpp | 7 +++- .../src/scripting/WindowScriptingInterface.h | 7 ++-- interface/src/ui/LoginDialog.cpp | 4 -- interface/src/ui/LoginDialog.h | 2 - libraries/ui/src/FileDialogHelper.cpp | 10 ++++- 11 files changed, 50 insertions(+), 32 deletions(-) diff --git a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml index 17d6a7d3b3..f90a7d8561 100644 --- a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml +++ b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml @@ -398,7 +398,7 @@ Item { lineHeight: 1 lineHeightMode: Text.ProportionalHeight - onLinkActivated: loginDialog.openUrl(link); + onLinkActivated: Window.openUrl(link); Component.onCompleted: { if (termsTextMetrics.width > root.bannerWidth) { diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 4dd05f594d..04ffe72a57 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -363,7 +363,7 @@ Item { linkColor: hifi.colors.blueAccent onLinkActivated: { Tablet.playSound(TabletEnums.ButtonClick); - loginDialog.openUrl(link); + Window.openUrl(link); lightboxPopup.titleText = "Can't Access Account"; lightboxPopup.bodyText = lightboxPopup.cantAccessBodyText; lightboxPopup.button2text = "CLOSE"; diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index 69ac2f5a6c..f1e0cfe685 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -411,7 +411,7 @@ Item { lineHeight: 1 lineHeightMode: Text.ProportionalHeight - onLinkActivated: loginDialog.openUrl(link); + onLinkActivated: Window.openUrl(link); Component.onCompleted: { if (termsTextMetrics.width > root.bannerWidth) { diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml index d450b1e7bc..d2fd1dfe35 100644 --- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -234,7 +234,7 @@ Item { lineHeight: 1 lineHeightMode: Text.ProportionalHeight - onLinkActivated: loginDialog.openUrl(link); + onLinkActivated: Window.openUrl(link); Component.onCompleted: { if (termsTextMetrics.width > root.bannerWidth) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7ba45da1fd..39994c53ab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2443,6 +2443,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->preloadSounds(); DependencyManager::get()->createKeyboard(); + QDesktopServices::setUrlHandler("file", this, "showUrlHandler"); + QDesktopServices::setUrlHandler("", this, "showUrlHandler"); + auto drives = QDir::drives(); + for (auto drive : drives) { + QDesktopServices::setUrlHandler(QUrl(drive.absolutePath()).scheme(), this, "showUrlHandler"); + } + _pendingIdleEvent = false; _graphicsEngine.startup(); @@ -8280,19 +8287,6 @@ void Application::packageModel() { ModelPackager::package(); } -void Application::openUrl(const QUrl& url) const { - if (!url.isEmpty()) { - if (url.scheme() == URL_SCHEME_HIFI) { - DependencyManager::get()->handleLookupString(url.toString()); - } else if (url.scheme() == URL_SCHEME_HIFIAPP) { - DependencyManager::get()->openSystemApp(url.path()); - } else { - // address manager did not handle - ask QDesktopServices to handle - QDesktopServices::openUrl(url); - } - } -} - void Application::loadDialog() { ModalDialogListener* dlg = OffscreenUi::getOpenFileNameAsync(_glWidget, tr("Open Script"), getPreviousScriptLocation(), @@ -9161,7 +9155,7 @@ void Application::readArgumentsFromLocalSocket() const { // If we received a message, try to open it as a URL if (message.length() > 0) { - qApp->openUrl(QString::fromUtf8(message)); + DependencyManager::get()->openUrl(QString::fromUtf8(message)); } } @@ -9278,6 +9272,24 @@ QString Application::getGraphicsCardType() { return GPUIdent::getInstance()->getName(); } +void Application::showUrlHandler(const QUrl& url) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "showUrlHandler", Q_ARG(const QUrl&, url)); + return; + } + + ModalDialogListener* dlg = OffscreenUi::asyncQuestion("Confirm openUrl", "Do you recognize this path or code and want to open or execute it: " + url.toDisplayString()); + QObject::connect(dlg, &ModalDialogListener::response, this, [=](QVariant answer) { + QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr); + if (QMessageBox::Yes == static_cast(answer.toInt())) { + // Unset the handler, open the URL, and the reset the handler + QDesktopServices::unsetUrlHandler(url.scheme()); + QDesktopServices::openUrl(url); + QDesktopServices::setUrlHandler(url.scheme(), this, "showUrlHandler"); + } + }); +} + #if defined(Q_OS_ANDROID) void Application::beforeEnterBackground() { auto nodeList = DependencyManager::get(); diff --git a/interface/src/Application.h b/interface/src/Application.h index e0e8821037..0ce01b47da 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -404,8 +404,6 @@ public slots: static void packageModel(); - void openUrl(const QUrl& url) const; - void resetSensors(bool andReload = false); void setActiveFaceTracker() const; @@ -472,6 +470,8 @@ public slots: QString getGraphicsCardType(); + void showUrlHandler(const QUrl& url); + private slots: void onDesktopRootItemCreated(QQuickItem* qmlContext); void onDesktopRootContextCreated(QQmlContext* qmlContext); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 0f3d859093..2c1311924f 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -27,6 +27,7 @@ #include "MainWindow.h" #include "Menu.h" #include "OffscreenUi.h" +#include "commerce/QmlCommerce.h" static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation"; @@ -134,15 +135,17 @@ void WindowScriptingInterface::disconnectedFromDomain() { void WindowScriptingInterface::openUrl(const QUrl& url) { if (!url.isEmpty()) { - if (url.scheme() == URL_SCHEME_HIFI) { + auto scheme = url.scheme(); + if (scheme == URL_SCHEME_HIFI) { DependencyManager::get()->handleLookupString(url.toString()); + } else if (scheme == URL_SCHEME_HIFIAPP) { + DependencyManager::get()->openSystemApp(url.path()); } else { #if defined(Q_OS_ANDROID) QMap args; args["url"] = url.toString(); AndroidHelper::instance().requestActivity("WebView", true, args); #else - // address manager did not handle - ask QDesktopServices to handle QDesktopServices::openUrl(url); #endif } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index baff6444e1..77b586ec70 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -535,9 +535,10 @@ public slots: int openMessageBox(QString title, QString text, int buttons, int defaultButton); /**jsdoc - * Open a URL in the Interface window or other application, depending on the URL's scheme. If the URL starts with - * hifi:// then that URL is navigated to in Interface, otherwise the URL is opened in the application the OS - * associates with the URL's scheme (e.g., a Web browser for http://). + * Open a URL in the Interface window or other application, depending on the URL's scheme. The following schemes are supported: + * hifi (navigate to the URL in Interface), hifiapp (open a system app in Interface). Other schemes will either be handled by the OS + * (e.g. http, https, mailto) or will create a confirmation dialog asking the user to confirm that they want to try to open + * the URL. * @function Window.openUrl * @param {string} url - The URL to open. */ diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index b4f504822f..50acdeaa1e 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -279,10 +279,6 @@ void LoginDialog::createAccountFromSteam(QString username) { } } -void LoginDialog::openUrl(const QString& url) const { - QDesktopServices::openUrl(QUrl(url)); -} - void LoginDialog::linkCompleted(QNetworkReply* reply) { emit handleLinkCompleted(); } diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index e2fa8adc61..7c659a9320 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -80,8 +80,6 @@ protected slots: Q_INVOKABLE void signup(const QString& email, const QString& username, const QString& password); - Q_INVOKABLE void openUrl(const QString& url) const; - Q_INVOKABLE bool getLoginDialogPoppedUp() const; }; diff --git a/libraries/ui/src/FileDialogHelper.cpp b/libraries/ui/src/FileDialogHelper.cpp index 6d14adf1db..e6a48da01b 100644 --- a/libraries/ui/src/FileDialogHelper.cpp +++ b/libraries/ui/src/FileDialogHelper.cpp @@ -111,7 +111,15 @@ QStringList FileDialogHelper::drives() { } void FileDialogHelper::openDirectory(const QString& path) { - QDesktopServices::openUrl(path); + QString dirPath = path; + const QString FILE_SCHEME = "file://"; + if (dirPath.startsWith(FILE_SCHEME)) { + dirPath.remove(0, FILE_SCHEME.length()); + } + QFileInfo fileInfo(dirPath); + if (fileInfo.isDir()) { + QDesktopServices::openUrl(path); + } } QList FileDialogHelper::urlToList(const QUrl& url) { From c63ee8d4f623a4451874f686929e19e2bb03edf8 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 25 Apr 2019 09:21:06 -0700 Subject: [PATCH 72/74] Tiny logical error in wallet creation --- interface/src/commerce/Wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index e1e872ac24..ea2de73db3 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -126,7 +126,7 @@ namespace { } QFile file(filename); - if (!file.open(QIODevice::WriteOnly)) { + if (file.open(QIODevice::WriteOnly)) { const char* bio_data; long bio_size = BIO_get_mem_data(bio, &bio_data); From 6b33f4e02739ad062e85859cbc6309effb8c495c Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 25 Apr 2019 10:31:05 -0700 Subject: [PATCH 73/74] Don't call function if flow is not active and made it thread safe --- interface/src/avatar/MyAvatar.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 25c7a788b3..92c2e68c92 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -5811,12 +5811,19 @@ void MyAvatar::releaseGrab(const QUuid& grabID) { } void MyAvatar::addAvatarHandsToFlow(const std::shared_ptr& otherAvatar) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "addAvatarHandsToFlow", + Q_ARG(const std::shared_ptr&, otherAvatar)); + return; + } auto &flow = _skeletonModel->getRig().getFlow(); - for (auto &handJointName : HAND_COLLISION_JOINTS) { - int jointIndex = otherAvatar->getJointIndex(handJointName); - if (jointIndex != -1) { - glm::vec3 position = otherAvatar->getJointPosition(jointIndex); - flow.setOthersCollision(otherAvatar->getID(), jointIndex, position); + if (otherAvatar != nullptr && flow.getActive()) { + for (auto &handJointName : HAND_COLLISION_JOINTS) { + int jointIndex = otherAvatar->getJointIndex(handJointName); + if (jointIndex != -1) { + glm::vec3 position = otherAvatar->getJointPosition(jointIndex); + flow.setOthersCollision(otherAvatar->getID(), jointIndex, position); + } } } } From 0e4ea4aff2109b24be8dee9f56dbcbd8f57bd272 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 25 Apr 2019 12:24:02 -0700 Subject: [PATCH 74/74] fix openDirectory --- interface/src/Application.cpp | 21 +++++++++++++++++++++ interface/src/Application.h | 2 ++ libraries/ui/src/FileDialogHelper.cpp | 11 +++-------- libraries/ui/src/FileDialogHelper.h | 3 +++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 39994c53ab..6a6bc08692 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2443,6 +2443,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->preloadSounds(); DependencyManager::get()->createKeyboard(); + FileDialogHelper::setOpenDirectoryOperator([this](const QString& path) { openDirectory(path); }); QDesktopServices::setUrlHandler("file", this, "showUrlHandler"); QDesktopServices::setUrlHandler("", this, "showUrlHandler"); auto drives = QDir::drives(); @@ -9272,6 +9273,26 @@ QString Application::getGraphicsCardType() { return GPUIdent::getInstance()->getName(); } +void Application::openDirectory(const QString& path) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "openDirectory", Q_ARG(const QString&, path)); + return; + } + + QString dirPath = path; + const QString FILE_SCHEME = "file:///"; + if (dirPath.startsWith(FILE_SCHEME)) { + dirPath.remove(0, FILE_SCHEME.length()); + } + QFileInfo fileInfo(dirPath); + if (fileInfo.isDir()) { + auto scheme = QUrl(path).scheme(); + QDesktopServices::unsetUrlHandler(scheme); + QDesktopServices::openUrl(path); + QDesktopServices::setUrlHandler(scheme, this, "showUrlHandler"); + } +} + void Application::showUrlHandler(const QUrl& url) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "showUrlHandler", Q_ARG(const QUrl&, url)); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0ce01b47da..d2c59343ed 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -345,6 +345,8 @@ public: void toggleAwayMode(); #endif + void openDirectory(const QString& path); + signals: void svoImportRequested(const QString& url); diff --git a/libraries/ui/src/FileDialogHelper.cpp b/libraries/ui/src/FileDialogHelper.cpp index e6a48da01b..6d16a1ec21 100644 --- a/libraries/ui/src/FileDialogHelper.cpp +++ b/libraries/ui/src/FileDialogHelper.cpp @@ -17,6 +17,7 @@ #include #include +std::function FileDialogHelper::_openDirectoryOperator = nullptr; QUrl FileDialogHelper::home() { return pathToUrl(QStandardPaths::standardLocations(QStandardPaths::HomeLocation)[0]); @@ -111,14 +112,8 @@ QStringList FileDialogHelper::drives() { } void FileDialogHelper::openDirectory(const QString& path) { - QString dirPath = path; - const QString FILE_SCHEME = "file://"; - if (dirPath.startsWith(FILE_SCHEME)) { - dirPath.remove(0, FILE_SCHEME.length()); - } - QFileInfo fileInfo(dirPath); - if (fileInfo.isDir()) { - QDesktopServices::openUrl(path); + if (_openDirectoryOperator) { + _openDirectoryOperator(path); } } diff --git a/libraries/ui/src/FileDialogHelper.h b/libraries/ui/src/FileDialogHelper.h index 12fd60daac..4685c3af6f 100644 --- a/libraries/ui/src/FileDialogHelper.h +++ b/libraries/ui/src/FileDialogHelper.h @@ -16,6 +16,7 @@ #include #include +#include class FileDialogHelper : public QObject { Q_OBJECT @@ -62,6 +63,7 @@ public: Q_INVOKABLE QUrl saveHelper(const QString& saveText, const QUrl& currentFolder, const QStringList& selectionFilters); Q_INVOKABLE QList urlToList(const QUrl& url); + static void setOpenDirectoryOperator(std::function openDirectoryOperator) { _openDirectoryOperator = openDirectoryOperator; } Q_INVOKABLE void openDirectory(const QString& path); Q_INVOKABLE void monitorDirectory(const QString& path); @@ -72,6 +74,7 @@ signals: private: QFileSystemWatcher _fsWatcher; QString _fsWatcherPath; + static std::function _openDirectoryOperator; };