From 17404863e7e3971f7b4e21d62c939f3f2af62c9b Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 15 Nov 2018 17:42:51 -0800 Subject: [PATCH 01/42] entity list reordering WIP --- scripts/system/html/css/edit-style.css | 4 ++ scripts/system/html/js/entityList.js | 97 ++++++++++++++++++++------ 2 files changed, 81 insertions(+), 20 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 3a291bf27b..a00dc4d57c 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1383,6 +1383,10 @@ input[type=button]#export { cursor: col-resize; } +#entity-table .dragging { + background-color: #b3ecff; +} + #entity-table td { box-sizing: border-box; } diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 00c50169a6..6f12dd1e7c 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -21,6 +21,8 @@ const MAX_LENGTH_RADIUS = 9; const MINIMUM_COLUMN_WIDTH = 24; const SCROLLBAR_WIDTH = 20; const RESIZER_WIDTH = 10; +const DELTA_X_MOVE_COLUMNS_THRESHOLD = 2; +const DELTA_X_COLUMN_SWAP_POSITION = 5; const COLUMNS = { type: { @@ -177,10 +179,12 @@ let isFilterInView = false; let columns = []; let columnsByID = {}; -let currentResizeEl = null; -let startResizeEvent = null; +let lastResizeEvent = null; let resizeColumnIndex = 0; -let startThClick = null; +let elTargetTh = null; +let targetColumnIndex = 0; +let lastColumnSwapPosition = -1; +let initialThEvent = null; let elEntityTable, elEntityTableHeader, @@ -319,7 +323,7 @@ function loaded() { let thID = "entity-" + columnID; let elTh = document.createElement("th"); elTh.setAttribute("id", thID); - elTh.setAttribute("data-resizable-column-id", thID); + elTh.setAttribute("columnIndex", columnIndex); if (columnData.glyph) { let elGlyph = document.createElement("span"); elGlyph.className = "glyph"; @@ -328,14 +332,10 @@ function loaded() { } else { elTh.innerText = columnData.columnHeader; } - elTh.onmousedown = function() { - startThClick = this; - }; - elTh.onmouseup = function() { - if (startThClick === this) { - setSortColumn(columnID); - } - startThClick = null; + elTh.onmousedown = function(event) { + elTargetTh = event.target; + initialThEvent = event; + targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); }; let elResizer = document.createElement("span"); @@ -1030,7 +1030,7 @@ function loaded() { } function onStartResize(event) { - startResizeEvent = event; + lastResizeEvent = event; resizeColumnIndex = parseInt(this.getAttribute("columnIndex")); event.stopPropagation(); } @@ -1074,8 +1074,33 @@ function loaded() { entityList.refresh(); } - document.onmousemove = function(ev) { - if (startResizeEvent) { + function swapColumns(columnAIndex, columnBIndex) { + let columnA = columns[columnAIndex]; + let columnB = columns[columnBIndex]; + let columnATh = columns[columnAIndex].elTh; + let columnBTh = columns[columnBIndex].elTh; + let columnThParent = columnATh.parentNode; + columnThParent.removeChild(columnBTh); + columnThParent.insertBefore(columnBTh, columnATh); + columnATh.setAttribute("columnIndex", columnBIndex); + columnBTh.setAttribute("columnIndex", columnAIndex); + columnA.elResizer.setAttribute("columnIndex", columnBIndex); + columnB.elResizer.setAttribute("columnIndex", columnAIndex); + + for (let i = 0; i < visibleEntities.length; ++i) { + let elRow = visibleEntities[i].elRow; + let columnACell = elRow.childNodes[columnAIndex]; + let columnBCell = elRow.childNodes[columnBIndex]; + elRow.removeChild(columnBCell); + elRow.insertBefore(columnBCell, columnACell); + } + + columns[columnAIndex] = columnB; + columns[columnBIndex] = columnA; + } + + document.onmousemove = function(event) { + if (lastResizeEvent) { startTh = null; let column = columns[resizeColumnIndex]; @@ -1087,7 +1112,7 @@ function loaded() { } let fullWidth = elEntityTableBody.offsetWidth; - let dx = ev.clientX - startResizeEvent.clientX; + let dx = event.clientX - lastResizeEvent.clientX; let dPct = dx / fullWidth; let newColWidth = column.width + dPct; @@ -1097,14 +1122,46 @@ function loaded() { column.width += dPct; nextColumn.width -= dPct; updateColumnWidths(); - startResizeEvent = ev; + lastResizeEvent = event; + } + } else if (elTargetTh) { + let dxFromInitial = event.clientX - initialThEvent.clientX; + if (Math.abs(dxFromInitial) >= DELTA_X_MOVE_COLUMNS_THRESHOLD) { + elTargetTh.className = "dragging"; + } + if (targetColumnIndex < columns.length - 1) { + let nextColumnIndex = targetColumnIndex + 1; + let nextColumnTh = columns[nextColumnIndex].elTh; + let nextColumnStartX = nextColumnTh.getBoundingClientRect().left; + if (event.clientX >= nextColumnStartX && event.clientX - lastColumnSwapPosition >= DELTA_X_COLUMN_SWAP_POSITION) { + swapColumns(targetColumnIndex, nextColumnIndex); + targetColumnIndex = nextColumnIndex; + lastColumnSwapPosition = event.clientX; + } + } + if (targetColumnIndex >= 1) { + let prevColumnIndex = targetColumnIndex - 1; + let prevColumnTh = columns[prevColumnIndex].elTh; + let prevColumnEndX = prevColumnTh.getBoundingClientRect().right; + if (event.clientX <= prevColumnEndX && event.clientX - lastColumnSwapPosition >= DELTA_X_COLUMN_SWAP_POSITION) { + swapColumns(prevColumnIndex, targetColumnIndex); + targetColumnIndex = prevColumnIndex; + } } } } - document.onmouseup = function(ev) { - startResizeEvent = null; - ev.stopPropagation(); + document.onmouseup = function(event) { + if (elTargetTh) { + if (elTargetTh.className !== "dragging" && elTargetTh === event.target) { + let columnID = columns[targetColumnIndex].columnID; + setSortColumn(columnID); + } + elTargetTh.className = ""; + } + lastResizeEvent = null; + elTargetTh = null; + initialThEvent = null; } function setSpaceMode(spaceMode) { From eb00435353ae2b7925a8fc41680ae91b354f75c4 Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 16 Nov 2018 10:35:50 -0800 Subject: [PATCH 02/42] removed whitespace --- libraries/animation/src/Rig.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 128ac05b81..baa8ac94ce 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -363,7 +363,6 @@ void Rig::reset(const HFMModel& hfmModel) { _animSkeleton = std::make_shared(hfmModel); - _internalPoseSet._relativePoses.clear(); _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); From cbe5814c64347ecfdcf8ca1770d6fabfccf6e924 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 16 Nov 2018 14:53:53 -0800 Subject: [PATCH 03/42] shader compilation prototype --- interface/src/Application.cpp | 44 +------------- interface/src/Application.h | 2 + interface/src/Application_render.cpp | 60 ++++++++++++------- .../display-plugins/OpenGLDisplayPlugin.cpp | 15 +++++ .../src/display-plugins/OpenGLDisplayPlugin.h | 3 + .../gpu-gl-common/src/gpu/gl/GLShader.cpp | 1 + libraries/plugins/src/plugins/DisplayPlugin.h | 4 ++ 7 files changed, 65 insertions(+), 64 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 969a05a792..6d13305af7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2382,6 +2382,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo checkLoginTimer->start(); } #endif + + const QString SPLASH_SKYBOX { "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" }; + _splashScreen->parse(SPLASH_SKYBOX); } void Application::updateVerboseLogging() { @@ -2862,8 +2865,6 @@ void Application::initializeGL() { DependencyManager::get()->setGPUContext(_gpuContext); } -static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" }; - void Application::initializeDisplayPlugins() { auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); Setting::Handle activeDisplayPluginSetting{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME, displayPlugins.at(0)->getName() }; @@ -2899,45 +2900,6 @@ void Application::initializeDisplayPlugins() { // Submit a default frame to render until the engine starts up updateRenderArgs(0.0f); - -#define ENABLE_SPLASH_FRAME 0 -#if ENABLE_SPLASH_FRAME - { - QMutexLocker viewLocker(&_renderArgsMutex); - - if (_appRenderArgs._isStereo) { - _gpuContext->enableStereo(true); - _gpuContext->setStereoProjections(_appRenderArgs._eyeProjections); - _gpuContext->setStereoViews(_appRenderArgs._eyeOffsets); - } - - // Frame resources - auto framebufferCache = DependencyManager::get(); - gpu::FramebufferPointer finalFramebuffer = framebufferCache->getFramebuffer(); - std::shared_ptr procedural = std::make_shared(); - procedural->parse(SPLASH_SKYBOX); - - _gpuContext->beginFrame(_appRenderArgs._view, _appRenderArgs._headPose); - gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { - batch.resetStages(); - batch.enableStereo(false); - batch.setFramebuffer(finalFramebuffer); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 0, 0, 1 }); - batch.enableSkybox(true); - batch.enableStereo(_appRenderArgs._isStereo); - batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); - procedural->render(batch, _appRenderArgs._renderArgs.getViewFrustum()); - }); - auto frame = _gpuContext->endFrame(); - frame->frameIndex = 0; - frame->framebuffer = finalFramebuffer; - frame->pose = _appRenderArgs._headPose; - frame->framebufferRecycler = [framebufferCache, procedural](const gpu::FramebufferPointer& framebuffer) { - framebufferCache->releaseFramebuffer(framebuffer); - }; - _displayPlugin->submitFrame(frame); - } -#endif } void Application::initializeRenderEngine() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 9b8aac425a..fb1c916c36 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -793,5 +793,7 @@ private: bool _showTrackedObjects { false }; bool _prevShowTrackedObjects { false }; + + std::shared_ptr _splashScreen { std::make_shared() }; }; #endif // hifi_Application_h diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index a87caeb9a8..47cde80ab3 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -62,6 +62,7 @@ void Application::paintGL() { glm::mat4 HMDSensorPose; glm::mat4 eyeToWorld; glm::mat4 sensorToWorld; + ViewFrustum viewFrustum; bool isStereo; glm::mat4 stereoEyeOffsets[2]; @@ -84,6 +85,7 @@ void Application::paintGL() { stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; }); + viewFrustum = _appRenderArgs._renderArgs.getViewFrustum(); } { @@ -94,21 +96,12 @@ void Application::paintGL() { gpu::doInBatch("Application_render::gpuContextReset", _gpuContext, [&](gpu::Batch& batch) { batch.resetStages(); }); - } - - { - PROFILE_RANGE(render, "/renderOverlay"); - PerformanceTimer perfTimer("renderOverlay"); - // NOTE: There is no batch associated with this renderArgs - // the ApplicationOverlay class assumes it's viewport is setup to be the device size - renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize()); - _applicationOverlay.renderOverlay(&renderArgs); - } - - { - PROFILE_RANGE(render, "/updateCompositor"); - getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); + if (isStereo) { + renderArgs._context->enableStereo(true); + renderArgs._context->setStereoProjections(stereoEyeProjections); + renderArgs._context->setStereoViews(stereoEyeOffsets); + } } gpu::FramebufferPointer finalFramebuffer; @@ -122,17 +115,38 @@ void Application::paintGL() { finalFramebuffer = framebufferCache->getFramebuffer(); } - { - if (isStereo) { - renderArgs._context->enableStereo(true); - renderArgs._context->setStereoProjections(stereoEyeProjections); - renderArgs._context->setStereoViews(stereoEyeOffsets); + if (!displayPlugin->areAllProgramsLoaded()) { + gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setFramebuffer(finalFramebuffer); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 0, 0, 1 }); + batch.enableSkybox(true); + batch.enableStereo(isStereo); + batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); + _splashScreen->render(batch, viewFrustum); + }); + } else { + { + PROFILE_RANGE(render, "/renderOverlay"); + PerformanceTimer perfTimer("renderOverlay"); + // NOTE: There is no batch associated with this renderArgs + // the ApplicationOverlay class assumes it's viewport is setup to be the device size + renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize()); + _applicationOverlay.renderOverlay(&renderArgs); } - renderArgs._hudOperator = displayPlugin->getHUDOperator(); - renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); - renderArgs._blitFramebuffer = finalFramebuffer; - runRenderFrame(&renderArgs); + { + PROFILE_RANGE(render, "/updateCompositor"); + getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); + } + + { + PROFILE_RANGE(render, "/runRenderFrame"); + renderArgs._hudOperator = displayPlugin->getHUDOperator(); + renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); + renderArgs._blitFramebuffer = finalFramebuffer; + runRenderFrame(&renderArgs); + } } auto frame = _gpuContext->endFrame(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 190d4d4104..f562efbe22 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -637,6 +638,17 @@ void OpenGLDisplayPlugin::present() { auto frameId = (uint64_t)presentCount(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId) uint64_t startPresent = usecTimestampNow(); + + if (!_allProgramsLoaded) { + const auto& programIDs = shader::allPrograms(); + if (_currentLoadingProgramIndex < programIDs.size()) { + auto shader = gpu::Shader::createProgram(programIDs.at(_currentLoadingProgramIndex++)); + gpu::gl::GLShader::sync(*getGLBackend(), *shader); + } else { + _allProgramsLoaded = true; + } + } + { PROFILE_RANGE_EX(render, "updateFrameData", 0xff00ff00, frameId) updateFrameData(); @@ -829,6 +841,9 @@ void OpenGLDisplayPlugin::render(std::function f) { _gpuContext->executeBatch(batch); } +OpenGLDisplayPlugin::OpenGLDisplayPlugin() : DisplayPlugin() { + _allProgramsLoaded = false; +} OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 1cc060161b..1e3983d366 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -38,6 +38,7 @@ protected: using Lock = std::unique_lock; using Condition = std::condition_variable; public: + OpenGLDisplayPlugin(); ~OpenGLDisplayPlugin(); // These must be final to ensure proper ordering of operations // between the main thread and the presentation thread @@ -180,5 +181,7 @@ protected: // be serialized through this mutex mutable Mutex _presentMutex; float _hudAlpha{ 1.0f }; + + size_t _currentLoadingProgramIndex { 0 }; }; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLShader.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLShader.cpp index 44d2bd6ca0..cf123a3f66 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLShader.cpp @@ -37,6 +37,7 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, const Shader: if (object) { return object; } + PROFILE_RANGE(render, "/GLShader::sync"); // need to have a gpu object? if (shader.isProgram()) { GLShader* tempObject = backend.compileBackendProgram(shader, handler); diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index ad49ceafe6..e925309042 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -217,6 +217,8 @@ public: static const QString& MENU_PATH(); + bool areAllProgramsLoaded() { return _allProgramsLoaded; } + signals: void recommendedFramebufferSizeChanged(const QSize& size); void resetSensorsRequested(); @@ -233,6 +235,8 @@ protected: float _renderResolutionScale { 1.0f }; + std::atomic _allProgramsLoaded { true }; + private: QMutex _presentMutex; QWaitCondition _presentCondition; From a0f79f988194a74f19e82e104241572da7ff7d30 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Nov 2018 17:14:30 -0800 Subject: [PATCH 04/42] entity list reordering columns --- scripts/system/html/js/entityList.js | 68 ++++++++++++++++++---------- scripts/system/html/js/listView.js | 4 -- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index e1581b7877..963611f059 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -110,8 +110,8 @@ const COLUMNS = { }; const COMPARE_ASCENDING = function(a, b) { - let va = a[currentSortColumn]; - let vb = b[currentSortColumn]; + let va = a[currentSortColumnID]; + let vb = b[currentSortColumnID]; if (va < vb) { return -1; @@ -171,7 +171,7 @@ let entityList = null; // The ListView */ let entityListContextMenu = null; -let currentSortColumn = 'type'; +let currentSortColumnID = 'type'; let currentSortOrder = ASCENDING_SORT; let elSortOrders = {}; let typeFilters = []; @@ -182,6 +182,7 @@ let columnsByID = {}; let lastResizeEvent = null; let resizeColumnIndex = 0; let elTargetTh = null; +let elTargetSpan = null; let targetColumnIndex = 0; let lastColumnSwapPosition = -1; let initialThEvent = null; @@ -226,10 +227,6 @@ const PROFILE = !ENABLE_PROFILING ? PROFILE_NOOP : function(name, fn, args) { console.log("PROFILE-Web " + profileIndent + "(" + name + ") End " + delta + "ms"); }; -debugPrint = function (message) { - console.log(message); -}; - function loaded() { openEventBridge(function() { elEntityTable = document.getElementById("entity-table"); @@ -320,10 +317,11 @@ function loaded() { for (let columnID in COLUMNS) { let columnData = COLUMNS[columnID]; - let thID = "entity-" + columnID; let elTh = document.createElement("th"); + let thID = "entity-" + columnID; elTh.setAttribute("id", thID); elTh.setAttribute("columnIndex", columnIndex); + elTh.setAttribute("columnID", columnID); if (columnData.glyph) { let elGlyph = document.createElement("span"); elGlyph.className = "glyph"; @@ -333,15 +331,19 @@ function loaded() { elTh.innerText = columnData.columnHeader; } elTh.onmousedown = function(event) { - elTargetTh = event.target; + if (event.target.nodeName === 'TH') { + elTargetTh = event.target; + targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); + lastColumnSwapPosition = event.clientX; + } else if (event.target.nodeName === 'SPAN') { + elTargetSpan = event.target; + } initialThEvent = event; - targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); }; let elResizer = document.createElement("span"); elResizer.className = "resizer"; elResizer.innerHTML = " "; - elResizer.setAttribute("columnIndex", columnIndex); elResizer.onmousedown = onStartResize; elTh.appendChild(elResizer); @@ -699,13 +701,13 @@ function loaded() { refreshNoEntitiesMessage(); } - function setSortColumn(column) { + function setSortColumn(columnID) { PROFILE("set-sort-column", function() { - if (currentSortColumn === column) { + if (currentSortColumnID === columnID) { currentSortOrder *= -1; } else { - elSortOrders[currentSortColumn].innerHTML = ""; - currentSortColumn = column; + elSortOrders[currentSortColumnID].innerHTML = ""; + currentSortColumnID = columnID; currentSortOrder = ASCENDING_SORT; } refreshSortOrder(); @@ -714,7 +716,7 @@ function loaded() { } function refreshSortOrder() { - elSortOrders[currentSortColumn].innerHTML = currentSortOrder === ASCENDING_SORT ? ASCENDING_STRING : DESCENDING_STRING; + elSortOrders[currentSortColumnID].innerHTML = currentSortOrder === ASCENDING_SORT ? ASCENDING_STRING : DESCENDING_STRING; } function refreshEntities() { @@ -1031,7 +1033,7 @@ function loaded() { function onStartResize(event) { lastResizeEvent = event; - resizeColumnIndex = parseInt(this.getAttribute("columnIndex")); + resizeColumnIndex = parseInt(this.parentNode.getAttribute("columnIndex")); event.stopPropagation(); } @@ -1089,14 +1091,18 @@ function loaded() { for (let i = 0; i < visibleEntities.length; ++i) { let elRow = visibleEntities[i].elRow; - let columnACell = elRow.childNodes[columnAIndex]; - let columnBCell = elRow.childNodes[columnBIndex]; - elRow.removeChild(columnBCell); - elRow.insertBefore(columnBCell, columnACell); + if (elRow) { + let columnACell = elRow.childNodes[columnAIndex]; + let columnBCell = elRow.childNodes[columnBIndex]; + elRow.removeChild(columnBCell); + elRow.insertBefore(columnBCell, columnACell); + } } columns[columnAIndex] = columnB; columns[columnBIndex] = columnA; + + updateColumnWidths(); } document.onmousemove = function(event) { @@ -1143,24 +1149,38 @@ function loaded() { let prevColumnIndex = targetColumnIndex - 1; let prevColumnTh = columns[prevColumnIndex].elTh; let prevColumnEndX = prevColumnTh.getBoundingClientRect().right; - if (event.clientX <= prevColumnEndX && event.clientX - lastColumnSwapPosition >= DELTA_X_COLUMN_SWAP_POSITION) { + if (event.clientX <= prevColumnEndX && lastColumnSwapPosition - event.clientX >= DELTA_X_COLUMN_SWAP_POSITION) { swapColumns(prevColumnIndex, targetColumnIndex); - targetColumnIndex = prevColumnIndex; + targetColumnIndex = prevColumnIndex; + lastColumnSwapPosition = event.clientX; } } + } else if (elTargetSpan) { + let dxFromInitial = event.clientX - initialThEvent.clientX; + if (Math.abs(dxFromInitial) >= DELTA_X_MOVE_COLUMNS_THRESHOLD) { + elTargetTh = elTargetSpan.parentNode; + elTargetTh.className = "dragging"; + targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); + lastColumnSwapPosition = event.clientX; + elTargetSpan = null; + } } } document.onmouseup = function(event) { if (elTargetTh) { if (elTargetTh.className !== "dragging" && elTargetTh === event.target) { - let columnID = columns[targetColumnIndex].columnID; + let columnID = elTargetTh.getAttribute("columnID"); setSortColumn(columnID); } elTargetTh.className = ""; + } else if (elTargetSpan) { + let columnID = elTargetSpan.parentNode.getAttribute("columnID"); + setSortColumn(columnID); } lastResizeEvent = null; elTargetTh = null; + elTargetSpan = null; initialThEvent = null; } diff --git a/scripts/system/html/js/listView.js b/scripts/system/html/js/listView.js index f775a4cb24..77e1ba99b1 100644 --- a/scripts/system/html/js/listView.js +++ b/scripts/system/html/js/listView.js @@ -9,10 +9,6 @@ const SCROLL_ROWS = 2; // number of rows used as scrolling buffer, each time we pass this number of rows we scroll const FIRST_ROW_INDEX = 2; // the first elRow element's index in the child nodes of the table body -debugPrint = function (message) { - console.log(message); -}; - function ListView(elTableBody, elTableScroll, elTableHeaderRow, createRowFunction, updateRowFunction, clearRowFunction, WINDOW_NONVARIABLE_HEIGHT) { this.elTableBody = elTableBody; From fd9c05ce8055d72bbc5540f38d0f2e88744b8437 Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 16 Nov 2018 17:39:46 -0800 Subject: [PATCH 05/42] joint mapping. adding to fbx reader and avatar classes to get non standard names to map to hifi --- .../src/avatars-renderer/Avatar.cpp | 15 +++++++++++++++ libraries/fbx/src/FBXReader.cpp | 18 ++++++++++++++++++ libraries/fbx/src/FSTReader.h | 1 + libraries/hfm/src/hfm/HFM.h | 1 + 4 files changed, 35 insertions(+) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index fceb146470..4b730fccda 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1437,6 +1437,21 @@ int Avatar::getJointIndex(const QString& name) const { withValidJointIndicesCache([&]() { if (_modelJointIndicesCache.contains(name)) { result = _modelJointIndicesCache[name] - 1; + if (_skeletonModel && _skeletonModel->isActive()) { + qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]; + qCDebug(avatars_renderer) << "joint indices cache " << name << " " << _modelJointIndicesCache[name]; + if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { + qCDebug(avatars_renderer) << "joint alternate name " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]]; + } + } + } else { + // doesn't contain name. + qCDebug(avatars_renderer) << "name is not here"; + if (_skeletonModel && _skeletonModel->isActive()) { + if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { + qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]];; + } + } } }); return result; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index dd10cd30b3..343f7e6c6d 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -417,6 +417,21 @@ QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) { return filepath.mid(filepath.lastIndexOf('/') + 1); } +QMap getJointNameMapping(const QVariantHash& mapping) { + static const QString JOINT_NAME_MAPPING_FIELD = "jointMap"; + QMap fbxToHifiJointNameMap; + if (!mapping.isEmpty() && mapping.contains(JOINT_NAME_MAPPING_FIELD) && mapping[JOINT_NAME_MAPPING_FIELD].type() == QVariant::Hash) { + auto jointNames = mapping[JOINT_NAME_MAPPING_FIELD].toHash(); + for (auto itr = jointNames.begin(); itr != jointNames.end(); itr++) { + qCDebug(modelformat) << "found a joint mapping field key " << itr.key() << " value " << itr.value().toString(); + fbxToHifiJointNameMap.insert(itr.key(), itr.value().toString()); + qCDebug(modelformat) << "the mapped key (Head) has a value of " << fbxToHifiJointNameMap[itr.key()]; + } + + } + return fbxToHifiJointNameMap; +} + QMap getJointRotationOffsets(const QVariantHash& mapping) { QMap jointRotationOffsets; static const QString JOINT_ROTATION_OFFSET_FIELD = "jointRotationOffset"; @@ -1830,6 +1845,9 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& qCDebug(modelformat) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; } + hfmModel.fbxToHifiJointNameMapping.clear(); + hfmModel.fbxToHifiJointNameMapping = getJointNameMapping(mapping); + return hfmModelPtr; } diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index 4a8574f0cf..00244877b3 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -29,6 +29,7 @@ static const QString JOINT_FIELD = "joint"; static const QString FREE_JOINT_FIELD = "freeJoint"; static const QString BLENDSHAPE_FIELD = "bs"; static const QString SCRIPT_FIELD = "script"; +static const QString JOINT_NAME_MAPPING_FIELD = "jointMap"; class FSTReader { public: diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 05e48b6534..b33417666f 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -313,6 +313,7 @@ public: QList blendshapeChannelNames; QMap jointRotationOffsets; + QMap fbxToHifiJointNameMapping; }; }; From 0fccb4c73c048a381b2024bc31eeeebee8750786 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 16 Nov 2018 18:30:30 -0800 Subject: [PATCH 06/42] move to batch, try to use static --- interface/src/Application_render.cpp | 2 -- .../display-plugins/OpenGLDisplayPlugin.cpp | 23 +++++++++++-------- .../src/display-plugins/OpenGLDisplayPlugin.h | 6 +++-- .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 7 ++++++ .../gpu-gl-common/src/gpu/gl/GLBackend.h | 2 ++ libraries/gpu/src/gpu/Batch.cpp | 6 +++++ libraries/gpu/src/gpu/Batch.h | 4 ++++ libraries/plugins/src/plugins/DisplayPlugin.h | 4 +--- 8 files changed, 37 insertions(+), 17 deletions(-) diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 47cde80ab3..8d9cdc980a 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -117,9 +117,7 @@ void Application::paintGL() { if (!displayPlugin->areAllProgramsLoaded()) { gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { - batch.enableStereo(false); batch.setFramebuffer(finalFramebuffer); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 0, 0, 1 }); batch.enableSkybox(true); batch.enableStereo(isStereo); batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index f562efbe22..45e0bbc2a6 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -634,18 +633,26 @@ void OpenGLDisplayPlugin::internalPresent() { _presentRate.increment(); } +std::atomic OpenGLDisplayPlugin::_allProgramsLoaded { false }; +unsigned int OpenGLDisplayPlugin::_currentLoadingProgramIndex { 0 }; + +bool OpenGLDisplayPlugin::areAllProgramsLoaded() const { + return OpenGLDisplayPlugin::_allProgramsLoaded.load(); +} + void OpenGLDisplayPlugin::present() { auto frameId = (uint64_t)presentCount(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId) uint64_t startPresent = usecTimestampNow(); - if (!_allProgramsLoaded) { + if (!OpenGLDisplayPlugin::_allProgramsLoaded.load()) { const auto& programIDs = shader::allPrograms(); - if (_currentLoadingProgramIndex < programIDs.size()) { - auto shader = gpu::Shader::createProgram(programIDs.at(_currentLoadingProgramIndex++)); - gpu::gl::GLShader::sync(*getGLBackend(), *shader); + if (OpenGLDisplayPlugin::_currentLoadingProgramIndex < programIDs.size()) { + gpu::doInBatch("createAndSyncProgram", _gpuContext, [&programIDs](gpu::Batch& batch) { + batch.createAndSyncProgram(programIDs.at(OpenGLDisplayPlugin::_currentLoadingProgramIndex++)); + }); } else { - _allProgramsLoaded = true; + OpenGLDisplayPlugin::_allProgramsLoaded.store(true); } } @@ -841,10 +848,6 @@ void OpenGLDisplayPlugin::render(std::function f) { _gpuContext->executeBatch(batch); } -OpenGLDisplayPlugin::OpenGLDisplayPlugin() : DisplayPlugin() { - _allProgramsLoaded = false; -} - OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 1e3983d366..acb12aa69a 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -38,7 +38,6 @@ protected: using Lock = std::unique_lock; using Condition = std::condition_variable; public: - OpenGLDisplayPlugin(); ~OpenGLDisplayPlugin(); // These must be final to ensure proper ordering of operations // between the main thread and the presentation thread @@ -84,6 +83,8 @@ public: void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override; + bool areAllProgramsLoaded() const override; + protected: friend class PresentThread; @@ -182,6 +183,7 @@ protected: mutable Mutex _presentMutex; float _hudAlpha{ 1.0f }; - size_t _currentLoadingProgramIndex { 0 }; + static std::atomic _allProgramsLoaded; + static unsigned int _currentLoadingProgramIndex; }; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index c1ce05c18b..415c5135d9 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -102,6 +102,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_pushProfileRange), (&::gpu::gl::GLBackend::do_popProfileRange), + + (&::gpu::gl::GLBackend::do_createAndSyncProgram), }; #define GL_GET_INTEGER(NAME) glGetIntegerv(GL_##NAME, &const_cast(NAME)); @@ -706,6 +708,11 @@ void GLBackend::do_glColor4f(const Batch& batch, size_t paramOffset) { (void)CHECK_GL_ERROR(); } +void GLBackend::do_createAndSyncProgram(const Batch& batch, size_t paramOffset) { + auto shader = gpu::Shader::createProgram(batch._params[paramOffset + 0]._uint); + gpu::gl::GLShader::sync(*this, *shader); +} + void GLBackend::releaseBuffer(GLuint id, Size size) const { Lock lock(_trashMutex); _currentFrameTrash.buffersTrash.push_back({ id, size }); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 37dde5b08e..0a2c1b92ff 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -380,6 +380,8 @@ public: virtual void do_setStateBlendFactor(const Batch& batch, size_t paramOffset) final; virtual void do_setStateScissorRect(const Batch& batch, size_t paramOffset) final; + virtual void do_createAndSyncProgram(const Batch& batch, size_t paramOffset) final; + virtual GLuint getFramebufferID(const FramebufferPointer& framebuffer) = 0; virtual GLuint getTextureID(const TexturePointer& texture) final; virtual GLuint getBufferID(const Buffer& buffer) = 0; diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index e3ea210ecb..43c1c69287 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -760,3 +760,9 @@ void Batch::flush() { buffer->flush(); } } + +void Batch::createAndSyncProgram(unsigned int programID) { + ADD_COMMAND(createAndSyncProgram); + + _params.emplace_back(programID); +} \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 96a45d3111..aff6cf5ddd 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -289,6 +289,8 @@ public: void _glColor4f(float red, float green, float blue, float alpha); + void createAndSyncProgram(unsigned int programID); + // Maybe useful but shoudln't be public. Please convince me otherwise // Well porting to gles i need it... void runLambda(std::function f); @@ -368,6 +370,8 @@ public: COMMAND_pushProfileRange, COMMAND_popProfileRange, + COMMAND_createAndSyncProgram, + NUM_COMMANDS, }; typedef std::vector Commands; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index e925309042..e9fbd71689 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -217,7 +217,7 @@ public: static const QString& MENU_PATH(); - bool areAllProgramsLoaded() { return _allProgramsLoaded; } + virtual bool areAllProgramsLoaded() const { return true; } signals: void recommendedFramebufferSizeChanged(const QSize& size); @@ -235,8 +235,6 @@ protected: float _renderResolutionScale { 1.0f }; - std::atomic _allProgramsLoaded { true }; - private: QMutex _presentMutex; QWaitCondition _presentCondition; From 372f4390e8f5c9cca94da1fbee648ee75f051cfb Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 19 Nov 2018 19:14:07 -0500 Subject: [PATCH 07/42] replicate default skybox --- interface/resources/shaders/splashSkybox.frag | 71 ++++++++----------- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/interface/resources/shaders/splashSkybox.frag b/interface/resources/shaders/splashSkybox.frag index 38c89b4d26..244dad3356 100644 --- a/interface/resources/shaders/splashSkybox.frag +++ b/interface/resources/shaders/splashSkybox.frag @@ -1,47 +1,32 @@ -const vec3 COLOR = vec3(0x00, 0xD8, 0x02) / vec3(0xFF); -const float CUTOFF = 0.65; -const float NOISE_MULT = 8.0; -const float NOISE_POWER = 1.0; +// Replicate the default skybox texture -float noise4D(vec4 p) { - return fract(sin(dot(p ,vec4(12.9898,78.233,126.7235, 593.2241))) * 43758.5453); -} - -float worley4D(vec4 p) { - float r = 3.0; - vec4 f = floor(p); - vec4 x = fract(p); - for(int i = -1; i<=1; i++) - { - for(int j = -1; j<=1; j++) - { - for(int k = -1; k<=1; k++) - { - for (int l = -1; l <= 1; l++) { - vec4 q = vec4(float(i),float(j),float(k), float(l)); - vec4 v = q + vec4(noise4D((q+f)*1.11), noise4D((q+f)*1.14), noise4D((q+f)*1.17), noise4D((q+f)*1.20)) - x; - float d = dot(v, v); - r = min(r, d); - } - } - } - } - return sqrt(r); -} - - -vec3 mainColor(vec3 direction) { - float n = worley4D(vec4(direction * NOISE_MULT, iGlobalTime / 3.0)); - n = 1.0 - n; - n = pow(n, NOISE_POWER); - if (n < CUTOFF) { - return vec3(0.0); - } - - n = (n - CUTOFF) / (1.0 - CUTOFF); - return COLOR * (1.0 - n); -} +const int NUM_COLORS = 5; +const vec3 WHITISH = vec3(0.471, 0.725, 0.825); +const vec3 GREENISH = vec3(0.157, 0.529, 0.588); +const vec3 COLORS[NUM_COLORS] = vec3[]( + GREENISH, + GREENISH, + WHITISH, + WHITISH, + vec3(0.6, 0.275, 0.706) // purple +); +const float PI = 3.14159265359; +const vec3 BLACK = vec3(0.0); +const vec3 SPACE_BLUE = vec3(0.0, 0.118, 0.392); +const float HORIZONTAL_OFFSET = 3.75; vec3 getSkyboxColor() { - return mainColor(normalize(_normal)); + vec2 horizontal = vec2(_normal.x, _normal.z); + horizontal = normalize(horizontal); + float theta = atan(horizontal.y, horizontal.x); + theta = 0.5 * (theta / PI + 1.0); + float index = theta * NUM_COLORS; + index = mod(index + HORIZONTAL_OFFSET, NUM_COLORS); + int index1 = int(index) % NUM_COLORS; + int index2 = (index1 + 1) % NUM_COLORS; + vec3 horizonColor = mix(COLORS[index1], COLORS[index2], index - index1); + horizonColor = mix(horizonColor, SPACE_BLUE, smoothstep(0.0, 0.08, _normal.y)); + horizonColor = mix(horizonColor, BLACK, smoothstep(0.04, 0.15, _normal.y)); + horizonColor = mix(BLACK, horizonColor, smoothstep(-0.01, 0.0, _normal.y)); + return pow(horizonColor, vec3(0.4545));; } From 1fd03102c5c690f38745e83e4a229b7441ca5b09 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 19 Nov 2018 17:40:43 -0800 Subject: [PATCH 08/42] debugging name mapping code --- libraries/animation/src/AnimSkeleton.cpp | 33 +++++++++++++++---- libraries/animation/src/AnimSkeleton.h | 4 ++- libraries/animation/src/Rig.cpp | 5 +++ .../src/avatars-renderer/Avatar.cpp | 12 ++++--- libraries/fbx/src/FBXReader.cpp | 2 +- 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 91ca2359b4..908b4eb1d3 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -23,6 +23,8 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { for (auto& joint : hfmModel.joints) { joints.push_back(joint); } + + _fbxToHifiJointNameMapping = hfmModel.fbxToHifiJointNameMapping; buildSkeletonFromJoints(joints, hfmModel.jointRotationOffsets); // we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose @@ -59,7 +61,16 @@ AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap AnimSkeleton::getChildrenOfJoint(int jointIndex) const { return result; } -const QString& AnimSkeleton::getJointName(int jointIndex) const { - return _joints[jointIndex].name; +const QString AnimSkeleton::getJointName(int jointIndex) const { + + QString jointName = _joints[jointIndex].name; + QMapIterator i(_fbxToHifiJointNameMapping); + while (i.hasNext()) { + i.next(); + if (i.value() == _joints[jointIndex].name) { + jointName = i.key(); + break; + } + } + return jointName; //;_joints[jointIndex].name; } AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& relativePoses) const { @@ -245,9 +266,9 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _nonMirroredIndices.clear(); _mirrorMap.reserve(_jointsSize); for (int i = 0; i < _jointsSize; i++) { - if (_joints[i].name != "Hips" && _joints[i].name != "Spine" && - _joints[i].name != "Spine1" && _joints[i].name != "Spine2" && - _joints[i].name != "Neck" && _joints[i].name != "Head" && + if (_joints[i].name != "Hips" && _joints[i].name != _fbxToHifiJointNameMapping["Hips"] && _joints[i].name != "Spine" && _joints[i].name != _fbxToHifiJointNameMapping["Spine"] && + _joints[i].name != "Spine1" && _joints[i].name != _fbxToHifiJointNameMapping["Spine1"] && _joints[i].name != "Spine2" && _joints[i].name != _fbxToHifiJointNameMapping["Spine2"] && + _joints[i].name != "Neck" && _joints[i].name != _fbxToHifiJointNameMapping["Neck"] && _joints[i].name != "Head" && _joints[i].name != _fbxToHifiJointNameMapping["Head"] && !((_joints[i].name.startsWith("Left") || _joints[i].name.startsWith("Right")) && _joints[i].name != "LeftEye" && _joints[i].name != "RightEye")) { // HACK: we don't want to mirror some joints so we remember their indices @@ -327,7 +348,7 @@ std::vector AnimSkeleton::lookUpJointIndices(const std::vector& jo for (auto& name : jointNames) { int index = nameToJointIndex(name); if (index == -1) { - qWarning(animation) << "AnimSkeleton::lookUpJointIndices(): could not find bone with named " << name; + qWarning(animation) << "AnimSkeleton::lookUpJointIndices(): could not find bone with name " << name; } result.push_back(index); } diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index ab89eb643d..bcbfe628c7 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -27,7 +27,7 @@ public: explicit AnimSkeleton(const std::vector& joints, const QMap jointOffsets); int nameToJointIndex(const QString& jointName) const; - const QString& getJointName(int jointIndex) const; + const QString getJointName(int jointIndex) const; int getNumJoints() const; int getChainDepth(int jointIndex) const; @@ -64,6 +64,7 @@ public: std::vector lookUpJointIndices(const std::vector& jointNames) const; const HFMCluster getClusterBindMatricesOriginalValues(const int meshIndex, const int clusterIndex) const { return _clusterBindMatrixOriginalValues[meshIndex][clusterIndex]; } + const QMap getFBXToHifiJointNameMapping() const { return _fbxToHifiJointNameMapping; } protected: void buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets); @@ -79,6 +80,7 @@ protected: std::vector _mirrorMap; QHash _jointIndicesByName; std::vector> _clusterBindMatrixOriginalValues; + QMap _fbxToHifiJointNameMapping; // no copies AnimSkeleton(const AnimSkeleton&) = delete; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index baa8ac94ce..0c30a7696f 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -420,7 +420,12 @@ static const uint32_t MAX_JOINT_NAME_WARNING_COUNT = 100; int Rig::indexOfJoint(const QString& jointName) const { if (_animSkeleton) { + int result = _animSkeleton->nameToJointIndex(jointName); + if (_animSkeleton->getFBXToHifiJointNameMapping().contains(jointName)) { + qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << _animSkeleton->getFBXToHifiJointNameMapping()[jointName] << " " << _animSkeleton->nameToJointIndex(_animSkeleton->getFBXToHifiJointNameMapping()[jointName]); + result = _animSkeleton->nameToJointIndex(jointName); + } // This is a content error, so we should issue a warning. if (result < 0 && _jointNameWarningCount < MAX_JOINT_NAME_WARNING_COUNT) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 4b730fccda..e5435a9a8c 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1438,18 +1438,20 @@ int Avatar::getJointIndex(const QString& name) const { if (_modelJointIndicesCache.contains(name)) { result = _modelJointIndicesCache[name] - 1; if (_skeletonModel && _skeletonModel->isActive()) { - qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]; - qCDebug(avatars_renderer) << "joint indices cache " << name << " " << _modelJointIndicesCache[name]; + // qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]; + // qCDebug(avatars_renderer) << "joint indices cache " << name << " " << _modelJointIndicesCache[name]; if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { - qCDebug(avatars_renderer) << "joint alternate name " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]]; + // qCDebug(avatars_renderer) << "joint alternate name " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]]; } } } else { // doesn't contain name. qCDebug(avatars_renderer) << "name is not here"; if (_skeletonModel && _skeletonModel->isActive()) { - if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { - qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]];; + + if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name])) { + result = _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name]] - 1; + qCDebug(avatars_renderer) << "joint " << name << " remapped to " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name] << result; } } } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 343f7e6c6d..2e43573ec2 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -425,7 +425,7 @@ QMap getJointNameMapping(const QVariantHash& mapping) { for (auto itr = jointNames.begin(); itr != jointNames.end(); itr++) { qCDebug(modelformat) << "found a joint mapping field key " << itr.key() << " value " << itr.value().toString(); fbxToHifiJointNameMap.insert(itr.key(), itr.value().toString()); - qCDebug(modelformat) << "the mapped key (Head) has a value of " << fbxToHifiJointNameMap[itr.key()]; + qCDebug(modelformat) << "the mapped key " << itr.key() << " has a value of " << fbxToHifiJointNameMap[itr.key()]; } } From a94fec75b47cf1372797521424c7057fe5322373 Mon Sep 17 00:00:00 2001 From: David Back Date: Mon, 19 Nov 2018 17:59:42 -0800 Subject: [PATCH 09/42] prevent drag drop onto edit --- scripts/system/html/entityList.html | 1 + scripts/system/html/entityProperties.html | 1 + scripts/system/html/gridControls.html | 1 + scripts/system/html/js/entityList.js | 3 ++- scripts/system/html/js/entityProperties.js | 1 + scripts/system/html/js/gridControls.js | 1 + scripts/system/html/js/utils.js | 23 ++++++++++++++++++++++ 7 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 scripts/system/html/js/utils.js diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index 6915a45f19..f9948bc8b0 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -18,6 +18,7 @@ + diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 01395368b0..a8bcabbfea 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -23,6 +23,7 @@ + diff --git a/scripts/system/html/gridControls.html b/scripts/system/html/gridControls.html index 4be002619a..8d6ee34bc0 100644 --- a/scripts/system/html/gridControls.html +++ b/scripts/system/html/gridControls.html @@ -16,6 +16,7 @@ + diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 84ad59df36..eb3e9ed882 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -1286,8 +1286,9 @@ function loaded() { }); augmentSpinButtons(); + disableDragDrop(); - document.addEventListener("contextmenu", function (event) { + document.addEventListener("contextmenu", function(event) { entityListContextMenu.close(); // Disable default right-click context menu which is not visible in the HMD and makes it seem like the app has locked diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index d3e0751732..6dc563b102 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -3479,6 +3479,7 @@ function loaded() { }); augmentSpinButtons(); + disableDragDrop(); // Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked document.addEventListener("contextmenu", function(event) { diff --git a/scripts/system/html/js/gridControls.js b/scripts/system/html/js/gridControls.js index b2d5988938..c2183130e9 100644 --- a/scripts/system/html/js/gridControls.js +++ b/scripts/system/html/js/gridControls.js @@ -108,6 +108,7 @@ function loaded() { }); augmentSpinButtons(); + disableDragDrop(); EventBridge.emitWebEvent(JSON.stringify({ type: 'init' })); }); diff --git a/scripts/system/html/js/utils.js b/scripts/system/html/js/utils.js new file mode 100644 index 0000000000..fe96e8b79e --- /dev/null +++ b/scripts/system/html/js/utils.js @@ -0,0 +1,23 @@ +// +// utils.js +// +// Created by David Back on 19 Nov 2018 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +function disableDragDrop() { + document.addEventListener("drop", function(event) { + event.preventDefault(); + event.dataTransfer.effectAllowed = "none"; + event.dataTransfer.dropEffect = "none"; + }, false); + + document.addEventListener("dragover", function(event) { + event.preventDefault(); + event.dataTransfer.effectAllowed = "none"; + event.dataTransfer.dropEffect = "none"; + }, false); +} From b0aa1b2af28bf573ba27c07793f45d3c54512c25 Mon Sep 17 00:00:00 2001 From: birarda Date: Tue, 20 Nov 2018 11:54:57 -0800 Subject: [PATCH 10/42] make domain settings maps keyed case insensitively --- .../resources/web/js/base-settings.js | 8 ++-- domain-server/src/DomainServer.cpp | 38 ++++++++++++------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/domain-server/resources/web/js/base-settings.js b/domain-server/resources/web/js/base-settings.js index fd404aff20..bd96f636a8 100644 --- a/domain-server/resources/web/js/base-settings.js +++ b/domain-server/resources/web/js/base-settings.js @@ -364,7 +364,7 @@ function validateInputs() { if (keyVal.length === 0) { empty = true - markParentRowInvalid(input); + markParentRowInvalid(input) return; } @@ -373,11 +373,13 @@ function validateInputs() { _.each(otherKeys, function(otherKeyCell) { var keyInput = $(otherKeyCell).children('input'); + var lowerNewValue = keyVal.toLowerCase(); + if (keyInput.length) { - if ($(keyInput).val() == keyVal) { + if ($(keyInput).val().toLowerCase() == lowerNewValue) { duplicateKey = true; } - } else if ($(otherKeyCell).html() == keyVal) { + } else if ($(otherKeyCell).html().toLowerCase() == lowerNewValue) { duplicateKey = true; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 69f16af8b3..258038b8f1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -3172,24 +3172,34 @@ void DomainServer::processPathQueryPacket(QSharedPointer messag const QString PATH_VIEWPOINT_KEY = "viewpoint"; const QString INDEX_PATH = "/"; - // check out paths in the _configMap to see if we have a match - auto keypath = QString(PATHS_SETTINGS_KEYPATH_FORMAT).arg(SETTINGS_PATHS_KEY).arg(pathQuery); - QVariant pathMatch = _settingsManager.valueForKeyPath(keypath); + QString responseViewpoint; - if (pathMatch.isValid() || pathQuery == INDEX_PATH) { + // check out paths in the _configMap to see if we have a match + auto pathsVariant = _settingsManager.valueForKeyPath(SETTINGS_PATHS_KEY); + + auto lowerPathQuery = pathQuery.toLower(); + + if (pathsVariant.canConvert()) { + auto pathsMap = pathsVariant.toMap(); + + // enumerate the paths and look case-insensitively for a matching one + for (auto it = pathsMap.constKeyValueBegin(); it != pathsMap.constKeyValueEnd(); ++it) { + if ((*it).first.toLower() == lowerPathQuery) { + responseViewpoint = (*it).second.toMap()[PATH_VIEWPOINT_KEY].toString().toLower(); + break; + } + } + } + + if (responseViewpoint.isEmpty() && pathQuery == INDEX_PATH) { + const QString DEFAULT_INDEX_PATH = "/0,0,0/0,0,0,1"; + responseViewpoint = DEFAULT_INDEX_PATH; + } + + if (!responseViewpoint.isEmpty()) { // we got a match, respond with the resulting viewpoint auto nodeList = DependencyManager::get(); - QString responseViewpoint; - - // if we didn't match the path BUT this is for the index path then send back our default - if (pathMatch.isValid()) { - responseViewpoint = pathMatch.toMap()[PATH_VIEWPOINT_KEY].toString(); - } else { - const QString DEFAULT_INDEX_PATH = "/0,0,0/0,0,0,1"; - responseViewpoint = DEFAULT_INDEX_PATH; - } - if (!responseViewpoint.isEmpty()) { QByteArray viewpointUTF8 = responseViewpoint.toUtf8(); From 572cdcd008f4758debd3c80ea8abb79fcd27c9b3 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 20 Nov 2018 17:09:37 -0800 Subject: [PATCH 11/42] remapping is now able to work remains to clean up code and check for gotchas from old fst code --- libraries/animation/src/AnimSkeleton.cpp | 102 +++++++++++++++--- libraries/animation/src/AnimSkeleton.h | 3 + libraries/animation/src/Rig.cpp | 2 +- .../src/avatars-renderer/Avatar.cpp | 4 +- .../src/avatars-renderer/SkeletonModel.cpp | 1 + libraries/fbx/src/FBXReader.cpp | 28 ++--- 6 files changed, 110 insertions(+), 30 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 908b4eb1d3..6e71ef0184 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -54,6 +54,7 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { } _clusterBindMatrixOriginalValues.push_back(dummyClustersList); } + //dump(false); } AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap jointOffsets) { @@ -64,16 +65,18 @@ int AnimSkeleton::nameToJointIndex(const QString& jointName) const { auto itr = _jointIndicesByName.find(jointName); - if (getFBXToHifiJointNameMapping().contains(jointName)) { - qCDebug(animation) << "failing joint name is " << jointName; + if (_fbxToHifiJointNameMapping.contains(jointName)) { + //qCDebug(animation) << "failing joint name is " << jointName; itr = _jointIndicesByName.find(_fbxToHifiJointNameMapping[jointName]); - qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << - _fbxToHifiJointNameMapping[jointName] << " " << itr.value(); + //qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << + //_fbxToHifiJointNameMapping[jointName] << " " << itr.value(); } if (_jointIndicesByName.end() != itr) { + //qCDebug(animation) << "returning " << itr.value() << " for " << jointName; return itr.value(); } + //qCDebug(animation) << "returning -1 " << " for " << jointName; return -1; } @@ -142,6 +145,7 @@ const QString AnimSkeleton::getJointName(int jointIndex) const { break; } } + //qCDebug(animation) << "reverse lookup: returning " << jointName << " for " << jointIndex; return jointName; //;_joints[jointIndex].name; } @@ -215,6 +219,81 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { } } +bool AnimSkeleton::checkNonMirrored(QString jointName) const { + + //bool isNonMirrored = false; + QMapIterator i(_fbxToHifiJointNameMapping); + while (i.hasNext()) { + i.next(); + if (i.value() == jointName) { + // check for left right in the key + if (i.key() != "Hips" && i.key() != "Spine" && + i.key() != "Spine1" && i.key() != "Spine2" && + i.key() != "Neck" && i.key() != "Head" && + !((i.key().startsWith("Left") || i.key().startsWith("Right")) && + i.key() != "LeftEye" && i.key() != "RightEye")) { + //return true + return true; + } else { + return false; + } + } + } + // check the unmapped name + if (jointName != "Hips" && jointName != "Spine" && + jointName != "Spine1" && jointName != "Spine2" && + jointName != "Neck" && jointName != "Head" && + !((jointName.startsWith("Left") || jointName.startsWith("Right")) && + jointName != "LeftEye" && jointName != "RightEye")) { + //return true + return true; + } else { + return false; + } + +} + +int AnimSkeleton::containsLeft(QString jointName) const { + QMapIterator i(_fbxToHifiJointNameMapping); + int mirrorJointIndex = -1; + while (i.hasNext()) { + i.next(); + if (i.value() == jointName) { + // check for left right in the key + if (i.key().startsWith("Left")) { + QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + //return true + } + } + } + if (jointName.startsWith("Left")) { + QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } + return mirrorJointIndex; +} + +int AnimSkeleton::containsRight(QString jointName) const { + QMapIterator i(_fbxToHifiJointNameMapping); + int mirrorJointIndex = -1; + while (i.hasNext()) { + i.next(); + if (i.value() == jointName) { + // check for left right in the key + if (i.key().startsWith("Right")) { + QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } + } + } + if (jointName.startsWith("Right")) { + QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } + return mirrorJointIndex; +} + void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets) { _joints = joints; @@ -266,22 +345,15 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _nonMirroredIndices.clear(); _mirrorMap.reserve(_jointsSize); for (int i = 0; i < _jointsSize; i++) { - if (_joints[i].name != "Hips" && _joints[i].name != _fbxToHifiJointNameMapping["Hips"] && _joints[i].name != "Spine" && _joints[i].name != _fbxToHifiJointNameMapping["Spine"] && - _joints[i].name != "Spine1" && _joints[i].name != _fbxToHifiJointNameMapping["Spine1"] && _joints[i].name != "Spine2" && _joints[i].name != _fbxToHifiJointNameMapping["Spine2"] && - _joints[i].name != "Neck" && _joints[i].name != _fbxToHifiJointNameMapping["Neck"] && _joints[i].name != "Head" && _joints[i].name != _fbxToHifiJointNameMapping["Head"] && - !((_joints[i].name.startsWith("Left") || _joints[i].name.startsWith("Right")) && - _joints[i].name != "LeftEye" && _joints[i].name != "RightEye")) { + if (checkNonMirrored(_joints[i].name)) { // HACK: we don't want to mirror some joints so we remember their indices // so we can restore them after a future mirror operation _nonMirroredIndices.push_back(i); } int mirrorJointIndex = -1; - if (_joints[i].name.startsWith("Left")) { - QString mirrorJointName = QString(_joints[i].name).replace(0, 4, "Right"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } else if (_joints[i].name.startsWith("Right")) { - QString mirrorJointName = QString(_joints[i].name).replace(0, 5, "Left"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); + mirrorJointIndex = containsLeft(_joints[i].name); + if (mirrorJointIndex > -1) { + mirrorJointIndex = containsRight(_joints[i].name); } if (mirrorJointIndex >= 0) { _mirrorMap.push_back(mirrorJointIndex); diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index bcbfe628c7..5581976d74 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -56,6 +56,9 @@ public: void saveNonMirroredPoses(const AnimPoseVec& poses) const; void restoreNonMirroredPoses(AnimPoseVec& poses) const; + bool checkNonMirrored(QString jointName) const; + int containsLeft(QString jointName) const; + int containsRight(QString jointName) const; void mirrorRelativePoses(AnimPoseVec& poses) const; void mirrorAbsolutePoses(AnimPoseVec& poses) const; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 0c30a7696f..1675ea8e90 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -423,7 +423,7 @@ int Rig::indexOfJoint(const QString& jointName) const { int result = _animSkeleton->nameToJointIndex(jointName); if (_animSkeleton->getFBXToHifiJointNameMapping().contains(jointName)) { - qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << _animSkeleton->getFBXToHifiJointNameMapping()[jointName] << " " << _animSkeleton->nameToJointIndex(_animSkeleton->getFBXToHifiJointNameMapping()[jointName]); + //qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << _animSkeleton->getFBXToHifiJointNameMapping()[jointName] << " " << _animSkeleton->nameToJointIndex(_animSkeleton->getFBXToHifiJointNameMapping()[jointName]); result = _animSkeleton->nameToJointIndex(jointName); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index e5435a9a8c..14e97a5bf9 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1446,12 +1446,12 @@ int Avatar::getJointIndex(const QString& name) const { } } else { // doesn't contain name. - qCDebug(avatars_renderer) << "name is not here"; + //qCDebug(avatars_renderer) << "name is not here"; if (_skeletonModel && _skeletonModel->isActive()) { if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name])) { result = _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name]] - 1; - qCDebug(avatars_renderer) << "joint " << name << " remapped to " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name] << result; + // qCDebug(avatars_renderer) << "joint " << name << " remapped to " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name] << result; } } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index 36e37dd3d4..a97ba4bf4b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -317,6 +317,7 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco } glm::vec3 SkeletonModel::getDefaultEyeModelPosition() const { + //qCDebug(avatars_renderer) << "default eye model position " << _defaultEyeModelPosition; return _owningAvatar->getModelScale() * _defaultEyeModelPosition; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2e43573ec2..3ddcd75255 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -485,7 +485,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& QString jointNeckName = processID(getString(joints.value("jointNeck", "jointNeck"))); QString jointRootName = processID(getString(joints.value("jointRoot", "jointRoot"))); QString jointLeanName = processID(getString(joints.value("jointLean", "jointLean"))); - QString jointHeadName = processID(getString(joints.value("jointHead", "jointHead"))); + QString jointHeadName = "Head";// processID(getString(joints.value("jointHead", "jointHead"))); QString jointLeftHandName = processID(getString(joints.value("jointLeftHand", "jointLeftHand"))); QString jointRightHandName = processID(getString(joints.value("jointRightHand", "jointRightHand"))); QString jointEyeLeftID; @@ -534,6 +534,8 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& HFMModel& hfmModel = *hfmModelPtr; hfmModel.originalURL = url; + hfmModel.fbxToHifiJointNameMapping.clear(); + hfmModel.fbxToHifiJointNameMapping = getJointNameMapping(mapping); float unitScaleFactor = 1.0f; glm::vec3 ambientColor; @@ -602,34 +604,34 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& hifiGlobalNodeID = id; } - if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") { + if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye" || (hfmModel.fbxToHifiJointNameMapping.contains(jointEyeLeftName) && (name == hfmModel.fbxToHifiJointNameMapping[jointEyeLeftName]))) { jointEyeLeftID = getID(object.properties); - } else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye") { + } else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye" || (hfmModel.fbxToHifiJointNameMapping.contains(jointEyeRightName) && (name == hfmModel.fbxToHifiJointNameMapping[jointEyeRightName]))) { jointEyeRightID = getID(object.properties); - } else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck") { + } else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck" || (hfmModel.fbxToHifiJointNameMapping.contains(jointNeckName) && (name == hfmModel.fbxToHifiJointNameMapping[jointNeckName]))) { jointNeckID = getID(object.properties); - } else if (name == jointRootName) { + } else if (name == jointRootName || (hfmModel.fbxToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRootName]))) { jointRootID = getID(object.properties); } else if (name == jointLeanName) { jointLeanID = getID(object.properties); - } else if (name == jointHeadName) { + } else if ((name == jointHeadName) || (hfmModel.fbxToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.fbxToHifiJointNameMapping[jointHeadName]))) { jointHeadID = getID(object.properties); - } else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand") { + } else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand" || (hfmModel.fbxToHifiJointNameMapping.contains(jointLeftHandName) && (name == hfmModel.fbxToHifiJointNameMapping[jointLeftHandName]))) { jointLeftHandID = getID(object.properties); - } else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand") { + } else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand" || (hfmModel.fbxToHifiJointNameMapping.contains(jointRightHandName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRightHandName]))) { jointRightHandID = getID(object.properties); - } else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End") { + } else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End" || (hfmModel.fbxToHifiJointNameMapping.contains("LeftToe") && (name == hfmModel.fbxToHifiJointNameMapping["LeftToe"]))) { jointLeftToeID = getID(object.properties); - } else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End") { + } else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End" || (hfmModel.fbxToHifiJointNameMapping.contains("RightToe") && (name == hfmModel.fbxToHifiJointNameMapping["RightToe"]))) { jointRightToeID = getID(object.properties); } @@ -1839,14 +1841,16 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& QString jointName = itr.key(); glm::quat rotationOffset = itr.value(); int jointIndex = hfmModel.getJointIndex(jointName); + if (hfmModel.fbxToHifiJointNameMapping.contains(jointName)) { + jointIndex = hfmModel.getJointIndex(hfmModel.fbxToHifiJointNameMapping[jointName]); + } if (jointIndex != -1) { hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); } qCDebug(modelformat) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; } - hfmModel.fbxToHifiJointNameMapping.clear(); - hfmModel.fbxToHifiJointNameMapping = getJointNameMapping(mapping); + return hfmModelPtr; } From a4883649760c15a6ff148720e3f49874c6277c6f Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 20 Nov 2018 17:14:35 -0800 Subject: [PATCH 12/42] fixed mirroring helper functions contains left and contains right --- libraries/animation/src/AnimSkeleton.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 6e71ef0184..e928658366 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -268,7 +268,7 @@ int AnimSkeleton::containsLeft(QString jointName) const { } } if (jointName.startsWith("Left")) { - QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); + QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); mirrorJointIndex = nameToJointIndex(mirrorJointName); } return mirrorJointIndex; @@ -288,7 +288,7 @@ int AnimSkeleton::containsRight(QString jointName) const { } } if (jointName.startsWith("Right")) { - QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); + QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); mirrorJointIndex = nameToJointIndex(mirrorJointName); } return mirrorJointIndex; From 746c5ed621a0206fea789fc6d58242995ddf6b1c Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 21 Nov 2018 15:46:54 -0800 Subject: [PATCH 13/42] we can now handle missing joints and extra joints --- libraries/animation/src/AnimSkeleton.cpp | 3 ++- libraries/fbx/src/FBXReader.cpp | 22 +++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index e928658366..c5fb20d99b 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -27,6 +27,7 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { _fbxToHifiJointNameMapping = hfmModel.fbxToHifiJointNameMapping; buildSkeletonFromJoints(joints, hfmModel.jointRotationOffsets); + // we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose // when we are dealing with a joint offset in the model for (int i = 0; i < (int)hfmModel.meshes.size(); i++) { @@ -352,7 +353,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, } int mirrorJointIndex = -1; mirrorJointIndex = containsLeft(_joints[i].name); - if (mirrorJointIndex > -1) { + if (!(mirrorJointIndex > -1)) { mirrorJointIndex = containsRight(_joints[i].name); } if (mirrorJointIndex >= 0) { diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 3ddcd75255..abf84d96b1 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -480,14 +480,14 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& std::map lights; QVariantHash joints = mapping.value("joint").toHash(); - QString jointEyeLeftName = processID(getString(joints.value("jointEyeLeft", "jointEyeLeft"))); - QString jointEyeRightName = processID(getString(joints.value("jointEyeRight", "jointEyeRight"))); - QString jointNeckName = processID(getString(joints.value("jointNeck", "jointNeck"))); - QString jointRootName = processID(getString(joints.value("jointRoot", "jointRoot"))); + QString jointEyeLeftName = "EyeLeft"; //processID(getString(joints.value("jointEyeLeft", "jointEyeLeft"))); + QString jointEyeRightName = "EyeRight"; // processID(getString(joints.value("jointEyeRight", "jointEyeRight"))); + QString jointNeckName = "Neck"; //processID(getString(joints.value("jointNeck", "jointNeck"))); + QString jointRootName = "Hips"; //processID(getString(joints.value("jointRoot", "jointRoot"))); QString jointLeanName = processID(getString(joints.value("jointLean", "jointLean"))); QString jointHeadName = "Head";// processID(getString(joints.value("jointHead", "jointHead"))); - QString jointLeftHandName = processID(getString(joints.value("jointLeftHand", "jointLeftHand"))); - QString jointRightHandName = processID(getString(joints.value("jointRightHand", "jointRightHand"))); + QString jointLeftHandName = "LeftHand"; //processID(getString(joints.value("jointLeftHand", "jointLeftHand"))); + QString jointRightHandName = "RightHand"; // processID(getString(joints.value("jointRightHand", "jointRightHand"))); QString jointEyeLeftID; QString jointEyeRightID; QString jointNeckID; @@ -1845,7 +1845,15 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& jointIndex = hfmModel.getJointIndex(hfmModel.fbxToHifiJointNameMapping[jointName]); } if (jointIndex != -1) { - hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); + //if (jointIndex == 18) { + // glm::quat spine3LocalOffset(0.94232035f, 0.000000014995882f, 0.33471236f, 0.000000058068572f); + // glm::quat spine3AbsoluteOffset = spine3LocalOffset * hfmModel.jointRotationOffsets[16]; + // hfmModel.jointRotationOffsets.insert(jointIndex, spine3AbsoluteOffset); + // qCDebug(modelformat) << "Joint Rotation Offset added for spine3 : " << spine3AbsoluteOffset; + //} else { + hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); + //} + } qCDebug(modelformat) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; } From 26fc53ef7808c86db8b7aab6fa7970c241dad536 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 26 Nov 2018 11:08:59 -0800 Subject: [PATCH 14/42] cleaned up whitespace and removed debug prints --- libraries/animation/src/AnimSkeleton.cpp | 40 +++++++++---------- libraries/animation/src/Rig.cpp | 1 - .../src/avatars-renderer/Avatar.cpp | 12 +----- .../src/avatars-renderer/SkeletonModel.cpp | 1 - libraries/fbx/src/FBXReader.cpp | 28 ++++--------- 5 files changed, 27 insertions(+), 55 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index c5fb20d99b..110dd5f92a 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -65,19 +65,14 @@ AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap AnimSkeleton::getChildrenOfJoint(int jointIndex) const { } const QString AnimSkeleton::getJointName(int jointIndex) const { - + QString jointName = _joints[jointIndex].name; QMapIterator i(_fbxToHifiJointNameMapping); while (i.hasNext()) { @@ -146,8 +141,7 @@ const QString AnimSkeleton::getJointName(int jointIndex) const { break; } } - //qCDebug(animation) << "reverse lookup: returning " << jointName << " for " << jointIndex; - return jointName; //;_joints[jointIndex].name; + return jointName; } AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& relativePoses) const { @@ -222,7 +216,6 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { bool AnimSkeleton::checkNonMirrored(QString jointName) const { - //bool isNonMirrored = false; QMapIterator i(_fbxToHifiJointNameMapping); while (i.hasNext()) { i.next(); @@ -264,14 +257,15 @@ int AnimSkeleton::containsLeft(QString jointName) const { if (i.key().startsWith("Left")) { QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); mirrorJointIndex = nameToJointIndex(mirrorJointName); - //return true } } } - if (jointName.startsWith("Left")) { - QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } + if (mirrorJointIndex < 0) { + if (jointName.startsWith("Left")) { + QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } + } return mirrorJointIndex; } @@ -285,12 +279,14 @@ int AnimSkeleton::containsRight(QString jointName) const { if (i.key().startsWith("Right")) { QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); mirrorJointIndex = nameToJointIndex(mirrorJointName); - } + } } } - if (jointName.startsWith("Right")) { - QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); + if (mirrorJointIndex < 0) { + if (jointName.startsWith("Right")) { + QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } } return mirrorJointIndex; } @@ -353,7 +349,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, } int mirrorJointIndex = -1; mirrorJointIndex = containsLeft(_joints[i].name); - if (!(mirrorJointIndex > -1)) { + if (mirrorJointIndex < 0) { mirrorJointIndex = containsRight(_joints[i].name); } if (mirrorJointIndex >= 0) { diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 1675ea8e90..5e2610e37e 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -423,7 +423,6 @@ int Rig::indexOfJoint(const QString& jointName) const { int result = _animSkeleton->nameToJointIndex(jointName); if (_animSkeleton->getFBXToHifiJointNameMapping().contains(jointName)) { - //qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << _animSkeleton->getFBXToHifiJointNameMapping()[jointName] << " " << _animSkeleton->nameToJointIndex(_animSkeleton->getFBXToHifiJointNameMapping()[jointName]); result = _animSkeleton->nameToJointIndex(jointName); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 14e97a5bf9..f3017049a7 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1437,21 +1437,11 @@ int Avatar::getJointIndex(const QString& name) const { withValidJointIndicesCache([&]() { if (_modelJointIndicesCache.contains(name)) { result = _modelJointIndicesCache[name] - 1; - if (_skeletonModel && _skeletonModel->isActive()) { - // qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]; - // qCDebug(avatars_renderer) << "joint indices cache " << name << " " << _modelJointIndicesCache[name]; - if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { - // qCDebug(avatars_renderer) << "joint alternate name " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]]; - } - } } else { - // doesn't contain name. - //qCDebug(avatars_renderer) << "name is not here"; + // doesn't contain name. check the fbx-to-hifi joint name mapping if (_skeletonModel && _skeletonModel->isActive()) { - if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name])) { result = _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name]] - 1; - // qCDebug(avatars_renderer) << "joint " << name << " remapped to " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name] << result; } } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index a97ba4bf4b..36e37dd3d4 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -317,7 +317,6 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco } glm::vec3 SkeletonModel::getDefaultEyeModelPosition() const { - //qCDebug(avatars_renderer) << "default eye model position " << _defaultEyeModelPosition; return _owningAvatar->getModelScale() * _defaultEyeModelPosition; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index abf84d96b1..35aabca123 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -423,11 +423,9 @@ QMap getJointNameMapping(const QVariantHash& mapping) { if (!mapping.isEmpty() && mapping.contains(JOINT_NAME_MAPPING_FIELD) && mapping[JOINT_NAME_MAPPING_FIELD].type() == QVariant::Hash) { auto jointNames = mapping[JOINT_NAME_MAPPING_FIELD].toHash(); for (auto itr = jointNames.begin(); itr != jointNames.end(); itr++) { - qCDebug(modelformat) << "found a joint mapping field key " << itr.key() << " value " << itr.value().toString(); fbxToHifiJointNameMap.insert(itr.key(), itr.value().toString()); qCDebug(modelformat) << "the mapped key " << itr.key() << " has a value of " << fbxToHifiJointNameMap[itr.key()]; } - } return fbxToHifiJointNameMap; } @@ -480,14 +478,14 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& std::map lights; QVariantHash joints = mapping.value("joint").toHash(); - QString jointEyeLeftName = "EyeLeft"; //processID(getString(joints.value("jointEyeLeft", "jointEyeLeft"))); - QString jointEyeRightName = "EyeRight"; // processID(getString(joints.value("jointEyeRight", "jointEyeRight"))); - QString jointNeckName = "Neck"; //processID(getString(joints.value("jointNeck", "jointNeck"))); - QString jointRootName = "Hips"; //processID(getString(joints.value("jointRoot", "jointRoot"))); + QString jointEyeLeftName = "EyeLeft"; + QString jointEyeRightName = "EyeRight"; + QString jointNeckName = "Neck"; + QString jointRootName = "Hips"; QString jointLeanName = processID(getString(joints.value("jointLean", "jointLean"))); - QString jointHeadName = "Head";// processID(getString(joints.value("jointHead", "jointHead"))); - QString jointLeftHandName = "LeftHand"; //processID(getString(joints.value("jointLeftHand", "jointLeftHand"))); - QString jointRightHandName = "RightHand"; // processID(getString(joints.value("jointRightHand", "jointRightHand"))); + QString jointHeadName = "Head"; + QString jointLeftHandName = "LeftHand"; + QString jointRightHandName = "RightHand"; QString jointEyeLeftID; QString jointEyeRightID; QString jointNeckID; @@ -1845,21 +1843,11 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& jointIndex = hfmModel.getJointIndex(hfmModel.fbxToHifiJointNameMapping[jointName]); } if (jointIndex != -1) { - //if (jointIndex == 18) { - // glm::quat spine3LocalOffset(0.94232035f, 0.000000014995882f, 0.33471236f, 0.000000058068572f); - // glm::quat spine3AbsoluteOffset = spine3LocalOffset * hfmModel.jointRotationOffsets[16]; - // hfmModel.jointRotationOffsets.insert(jointIndex, spine3AbsoluteOffset); - // qCDebug(modelformat) << "Joint Rotation Offset added for spine3 : " << spine3AbsoluteOffset; - //} else { - hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); - //} - + hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); } qCDebug(modelformat) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; } - - return hfmModelPtr; } From fb7b503ce94ce8da1aaea43dc21d7b5905662ae3 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 26 Nov 2018 13:48:00 -0800 Subject: [PATCH 15/42] removed unnecessary iteration of the joint name mapping in AnimSkeleton.cpp --- libraries/animation/src/AnimSkeleton.cpp | 54 ++++-------------------- 1 file changed, 8 insertions(+), 46 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 110dd5f92a..c5e6241555 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -27,7 +27,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { _fbxToHifiJointNameMapping = hfmModel.fbxToHifiJointNameMapping; buildSkeletonFromJoints(joints, hfmModel.jointRotationOffsets); - // we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose // when we are dealing with a joint offset in the model for (int i = 0; i < (int)hfmModel.meshes.size(); i++) { @@ -133,13 +132,8 @@ std::vector AnimSkeleton::getChildrenOfJoint(int jointIndex) const { const QString AnimSkeleton::getJointName(int jointIndex) const { QString jointName = _joints[jointIndex].name; - QMapIterator i(_fbxToHifiJointNameMapping); - while (i.hasNext()) { - i.next(); - if (i.value() == _joints[jointIndex].name) { - jointName = i.key(); - break; - } + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(_joints[jointIndex].name))) { + jointName = _fbxToHifiJointNameMapping.key(_joints[jointIndex].name); } return jointName; } @@ -216,22 +210,8 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { bool AnimSkeleton::checkNonMirrored(QString jointName) const { - QMapIterator i(_fbxToHifiJointNameMapping); - while (i.hasNext()) { - i.next(); - if (i.value() == jointName) { - // check for left right in the key - if (i.key() != "Hips" && i.key() != "Spine" && - i.key() != "Spine1" && i.key() != "Spine2" && - i.key() != "Neck" && i.key() != "Head" && - !((i.key().startsWith("Left") || i.key().startsWith("Right")) && - i.key() != "LeftEye" && i.key() != "RightEye")) { - //return true - return true; - } else { - return false; - } - } + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); } // check the unmapped name if (jointName != "Hips" && jointName != "Spine" && @@ -239,26 +219,16 @@ bool AnimSkeleton::checkNonMirrored(QString jointName) const { jointName != "Neck" && jointName != "Head" && !((jointName.startsWith("Left") || jointName.startsWith("Right")) && jointName != "LeftEye" && jointName != "RightEye")) { - //return true return true; } else { return false; } - } int AnimSkeleton::containsLeft(QString jointName) const { - QMapIterator i(_fbxToHifiJointNameMapping); int mirrorJointIndex = -1; - while (i.hasNext()) { - i.next(); - if (i.value() == jointName) { - // check for left right in the key - if (i.key().startsWith("Left")) { - QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } - } + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); } if (mirrorJointIndex < 0) { if (jointName.startsWith("Left")) { @@ -270,17 +240,9 @@ int AnimSkeleton::containsLeft(QString jointName) const { } int AnimSkeleton::containsRight(QString jointName) const { - QMapIterator i(_fbxToHifiJointNameMapping); int mirrorJointIndex = -1; - while (i.hasNext()) { - i.next(); - if (i.value() == jointName) { - // check for left right in the key - if (i.key().startsWith("Right")) { - QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } - } + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); } if (mirrorJointIndex < 0) { if (jointName.startsWith("Right")) { From e193dcbc602597f823006a3d2704ac6e838a8c4b Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 27 Nov 2018 18:59:58 +0100 Subject: [PATCH 16/42] - add missing start/middle/finish tooltips - style updates --- .../system/assets/data/createAppTooltips.json | 64 +++++++++++++++++-- scripts/system/html/css/edit-style.css | 5 +- scripts/system/html/js/entityProperties.js | 11 +++- 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/scripts/system/assets/data/createAppTooltips.json b/scripts/system/assets/data/createAppTooltips.json index 720d4537ee..b3df0fa13b 100644 --- a/scripts/system/assets/data/createAppTooltips.json +++ b/scripts/system/assets/data/createAppTooltips.json @@ -193,22 +193,52 @@ "emitterShouldTrail": { "tooltip": "If enabled, then particles are \"left behind\" as the emitter moves, otherwise they are not." }, + "particleRadiusTriple": { + "tooltip": "The size of each particle.", + "jsPropertyName": "particleRadius" + }, "particleRadius": { "tooltip": "The size of each particle." }, + "radiusStart": { + "tooltip": "The start size of each particle." + }, + "radiusFinish": { + "tooltip": "The finish size of each particle." + }, "radiusSpread": { "tooltip": "The spread in size that each particle is given, resulting in a variety of sizes." }, + "particleColorTriple": { + "tooltip": "The color of each particle.", + "jsPropertyName": "color" + }, "particleColor": { "tooltip": "The color of each particle.", "jsPropertyName": "color" }, + "colorStart": { + "tooltip": "The start color of each particle." + }, + "colorFinish": { + "tooltip": "The finish color of each particle." + }, "colorSpread": { "tooltip": "The spread in color that each particle is given, resulting in a variety of colors." }, + "particleAlphaTriple": { + "tooltip": "The alpha of each particle.", + "jsPropertyName": "alpha" + }, "alpha": { "tooltip": "The alpha of each particle." }, + "alphaStart": { + "tooltip": "The start alpha of each particle." + }, + "alphaFinish": { + "tooltip": "The finish alpha of each particle." + }, "alphaSpread": { "tooltip": "The spread in alpha that each particle is given, resulting in a variety of alphas." }, @@ -218,20 +248,44 @@ "accelerationSpread": { "tooltip": "The spread in accelerations that each particle is given, resulting in a variety of accelerations." }, + "particleSpinTriple": { + "tooltip": "The spin of each particle.", + "jsPropertyName": "particleSpin" + }, "particleSpin": { - "tooltip": "The spin of each particle in the system." + "tooltip": "The spin of each particle." + }, + "spinStart": { + "tooltip": "The start spin of each particle." + }, + "spinFinish": { + "tooltip": "The finish spin of each particle." }, "spinSpread": { "tooltip": "The spread in spin that each particle is given, resulting in a variety of spins." }, "rotateWithEntity": { - "tooltip": "If enabled, each particle will spin relative to the roation of the entity as a whole." + "tooltip": "If enabled, each particle will spin relative to the rotation of the entity as a whole." + }, + "particlePolarTriple": { + "tooltip": "The angle range in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis.", + "skipJSProperty": true }, "polarStart": { - "tooltip": "The angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + "tooltip": "The start angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + }, + "polarFinish": { + "tooltip": "The finish angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + }, + "particleAzimuthTriple": { + "tooltip": "The angle range in deg at which particles are emitted. Starts in the entity's -x direction, and rotates around its z axis.", + "skipJSProperty": true }, "azimuthStart": { - "tooltip": "The angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + "tooltip": "The start angle in deg at which particles are emitted. Starts in the entity's -x direction, and rotates around its z axis." + }, + "azimuthFinish": { + "tooltip": "The finish angle in deg at which particles are emitted. Starts in the entity's -x direction, and rotates around its z axis." }, "lightColor": { "tooltip": "The color of the light emitted.", @@ -352,7 +406,7 @@ "tooltip": "The URL of a sound to play when the entity collides with something else." }, "grab.grabbable": { - "tooltip": "If enabled, this entity will allow grabbing input and will be moveable." + "tooltip": "If enabled, this entity will allow grabbing input and will be movable." }, "grab.triggerable": { "tooltip": "If enabled, the collider on this entity is used for triggering events." diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 5b5c9e057c..8c21965152 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -599,6 +599,7 @@ div.section[collapsed="true"], div.section[collapsed="true"] > .section-header { .triple-label { text-transform: uppercase; padding: 6px 0; + cursor: default; } .triple-item { @@ -1507,6 +1508,7 @@ input.rename-entity { } .create-app-tooltip { + z-index: 100; position: absolute; background: #6a6a6a; border: 1px solid black; @@ -1644,6 +1646,7 @@ input.number-slider { font-family: Raleway-Light; font-size: 14px; margin: 6px 0; + cursor: default; } #property-name, #property-id { @@ -1656,7 +1659,7 @@ input.number-slider { } #placeholder-property-type { - min-width: 0px; + min-width: 0; } .collapse-icon { diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 78e3cd4dc8..60b9c04fbd 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -720,6 +720,7 @@ const GROUPS = [ { type: "triple", label: "Size", + propertyID: "particleRadiusTriple", properties: [ { label: "Start", @@ -771,6 +772,7 @@ const GROUPS = [ { type: "triple", label: "Color", + propertyID: "particleColorTriple", properties: [ { label: "Start", @@ -807,6 +809,7 @@ const GROUPS = [ { type: "triple", label: "Alpha", + propertyID: "particleAlphaTriple", properties: [ { label: "Start", @@ -883,6 +886,7 @@ const GROUPS = [ { type: "triple", label: "Alpha", + propertyID: "particleSpinTriple", properties: [ { label: "Start", @@ -947,6 +951,7 @@ const GROUPS = [ { type: "triple", label: "Horizontal Angle", + propertyID: "particlePolarTriple", properties: [ { label: "Start", @@ -975,6 +980,7 @@ const GROUPS = [ { type: "triple", label: "Vertical Angle", + propertyID: "particleAzimuthTriple", properties: [ { label: "Start", @@ -2886,7 +2892,10 @@ function loaded() { let propertyElementID = "property-" + propertyID; propertyElementID = propertyElementID.replace('.', '-'); - elWrapper.appendChild(createElementFromHTML(`
${innerPropertyData.label}
`)); + let elLabel = createElementFromHTML(`
${innerPropertyData.label}
`); + createAppTooltip.registerTooltipElement(elLabel, propertyID); + + elWrapper.appendChild(elLabel); elProperty.appendChild(elWrapper); let property = createProperty(innerPropertyData, propertyElementID, propertyName, propertyID, elWrapper.childNodes[0]); From ec19d2f119d49093d03a57d4c378d1c00ccb4eab Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 21 Nov 2018 15:31:47 -0800 Subject: [PATCH 17/42] Fix Create tooltips getting pushed down for tall rows --- scripts/system/html/js/entityProperties.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 60b9c04fbd..7f269aa7ed 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -2858,23 +2858,20 @@ function loaded() { elGroup.appendChild(elContainer); } - elLabel = document.createElement('label'); - elLabel.setAttribute("for", propertyElementID); + let labelText = propertyData.label !== undefined ? propertyData.label : ""; + let className = ''; if (propertyData.indentedLabel || propertyData.showPropertyRule !== undefined) { - let elSpan = document.createElement('span'); - elSpan.className = 'indented'; - elSpan.innerText = propertyData.label !== undefined ? propertyData.label : ""; - elLabel.appendChild(elSpan); - } else { - elLabel.innerText = propertyData.label !== undefined ? propertyData.label : ""; + className = 'indented'; } + elLabel = createElementFromHTML( + ``); elContainer.appendChild(elLabel); } else { elContainer = document.getElementById(propertyData.replaceID); } if (elLabel) { - createAppTooltip.registerTooltipElement(elLabel, propertyID); + createAppTooltip.registerTooltipElement(elLabel.childNodes[0], propertyID); } let elProperty = createElementFromHTML('
'); From 579e2dd2eeed15b0a7ae74cf7249a914c87bcf28 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 27 Nov 2018 14:10:20 -0800 Subject: [PATCH 18/42] removed unnecessary mirror joint code and cleaned up whitespace in rig.cpp --- libraries/animation/src/AnimSkeleton.cpp | 65 ++++++------------------ libraries/animation/src/AnimSkeleton.h | 4 -- libraries/animation/src/Rig.cpp | 5 +- 3 files changed, 16 insertions(+), 58 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index c5e6241555..b124f55641 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -54,7 +54,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { } _clusterBindMatrixOriginalValues.push_back(dummyClustersList); } - //dump(false); } AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap jointOffsets) { @@ -208,51 +207,6 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { } } -bool AnimSkeleton::checkNonMirrored(QString jointName) const { - - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - // check the unmapped name - if (jointName != "Hips" && jointName != "Spine" && - jointName != "Spine1" && jointName != "Spine2" && - jointName != "Neck" && jointName != "Head" && - !((jointName.startsWith("Left") || jointName.startsWith("Right")) && - jointName != "LeftEye" && jointName != "RightEye")) { - return true; - } else { - return false; - } -} - -int AnimSkeleton::containsLeft(QString jointName) const { - int mirrorJointIndex = -1; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - if (mirrorJointIndex < 0) { - if (jointName.startsWith("Left")) { - QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } - } - return mirrorJointIndex; -} - -int AnimSkeleton::containsRight(QString jointName) const { - int mirrorJointIndex = -1; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - if (mirrorJointIndex < 0) { - if (jointName.startsWith("Right")) { - QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } - } - return mirrorJointIndex; -} - void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets) { _joints = joints; @@ -304,15 +258,26 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _nonMirroredIndices.clear(); _mirrorMap.reserve(_jointsSize); for (int i = 0; i < _jointsSize; i++) { - if (checkNonMirrored(_joints[i].name)) { + QString jointName = _joints[i].name; + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); + } + if (jointName != "Hips" && jointName != "Spine" && + jointName != "Spine1" && jointName != "Spine2" && + jointName != "Neck" && jointName != "Head" && + !((jointName.startsWith("Left") || jointName.startsWith("Right")) && + jointName != "LeftEye" && jointName != "RightEye")) { // HACK: we don't want to mirror some joints so we remember their indices // so we can restore them after a future mirror operation _nonMirroredIndices.push_back(i); } int mirrorJointIndex = -1; - mirrorJointIndex = containsLeft(_joints[i].name); - if (mirrorJointIndex < 0) { - mirrorJointIndex = containsRight(_joints[i].name); + if (jointName.startsWith("Left")) { + QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } else if (jointName.startsWith("Right")) { + QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); } if (mirrorJointIndex >= 0) { _mirrorMap.push_back(mirrorJointIndex); diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index 5581976d74..50b5d25c63 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -56,9 +56,6 @@ public: void saveNonMirroredPoses(const AnimPoseVec& poses) const; void restoreNonMirroredPoses(AnimPoseVec& poses) const; - bool checkNonMirrored(QString jointName) const; - int containsLeft(QString jointName) const; - int containsRight(QString jointName) const; void mirrorRelativePoses(AnimPoseVec& poses) const; void mirrorAbsolutePoses(AnimPoseVec& poses) const; @@ -67,7 +64,6 @@ public: std::vector lookUpJointIndices(const std::vector& jointNames) const; const HFMCluster getClusterBindMatricesOriginalValues(const int meshIndex, const int clusterIndex) const { return _clusterBindMatrixOriginalValues[meshIndex][clusterIndex]; } - const QMap getFBXToHifiJointNameMapping() const { return _fbxToHifiJointNameMapping; } protected: void buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 5e2610e37e..128ac05b81 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -363,6 +363,7 @@ void Rig::reset(const HFMModel& hfmModel) { _animSkeleton = std::make_shared(hfmModel); + _internalPoseSet._relativePoses.clear(); _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); @@ -420,11 +421,7 @@ static const uint32_t MAX_JOINT_NAME_WARNING_COUNT = 100; int Rig::indexOfJoint(const QString& jointName) const { if (_animSkeleton) { - int result = _animSkeleton->nameToJointIndex(jointName); - if (_animSkeleton->getFBXToHifiJointNameMapping().contains(jointName)) { - result = _animSkeleton->nameToJointIndex(jointName); - } // This is a content error, so we should issue a warning. if (result < 0 && _jointNameWarningCount < MAX_JOINT_NAME_WARNING_COUNT) { From 1f354f813c2553566913e1c514dafb749278a438 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 27 Nov 2018 14:38:02 -0800 Subject: [PATCH 19/42] rework shader pre-compilation --- interface/src/Application.cpp | 7 ++++ interface/src/Application.h | 2 ++ interface/src/Application_render.cpp | 2 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 21 ++---------- .../src/display-plugins/OpenGLDisplayPlugin.h | 5 --- .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 11 +++---- .../gpu-gl-common/src/gpu/gl/GLBackend.h | 4 +-- libraries/gpu/src/gpu/Batch.cpp | 6 ---- libraries/gpu/src/gpu/Batch.h | 4 --- libraries/gpu/src/gpu/Context.cpp | 33 +++++++++++++++++++ libraries/gpu/src/gpu/Context.h | 21 ++++++++++++ libraries/gpu/src/gpu/null/NullBackend.h | 2 ++ libraries/plugins/src/plugins/DisplayPlugin.h | 2 -- 13 files changed, 75 insertions(+), 45 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d13305af7..8e311e5487 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2862,6 +2862,13 @@ void Application::initializeGL() { _glWidget->makeCurrent(); _gpuContext = std::make_shared(); + static std::once_flag once; + std::call_once(once, [&] { + _gpuContext->pushProgramsToSync(shader::allPrograms(), [this] { + _programsCompiled.store(true); + }, 1); + }); + DependencyManager::get()->setGPUContext(_gpuContext); } diff --git a/interface/src/Application.h b/interface/src/Application.h index fb1c916c36..c234cd757c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -795,5 +795,7 @@ private: bool _prevShowTrackedObjects { false }; std::shared_ptr _splashScreen { std::make_shared() }; + std::atomic _programsCompiled { false }; + }; #endif // hifi_Application_h diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 8d9cdc980a..046cd3b617 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -115,7 +115,7 @@ void Application::paintGL() { finalFramebuffer = framebufferCache->getFramebuffer(); } - if (!displayPlugin->areAllProgramsLoaded()) { + if (!_programsCompiled.load()) { gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { batch.setFramebuffer(finalFramebuffer); batch.enableSkybox(true); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 45e0bbc2a6..aafc1a28a5 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -525,6 +525,9 @@ void OpenGLDisplayPlugin::updateFrameData() { if (_newFrameQueue.size() > 1) { _droppedFrameRate.increment(_newFrameQueue.size() - 1); } + + _gpuContext->processProgramsToSync(); + while (!_newFrameQueue.empty()) { _currentFrame = _newFrameQueue.front(); _newFrameQueue.pop(); @@ -633,29 +636,11 @@ void OpenGLDisplayPlugin::internalPresent() { _presentRate.increment(); } -std::atomic OpenGLDisplayPlugin::_allProgramsLoaded { false }; -unsigned int OpenGLDisplayPlugin::_currentLoadingProgramIndex { 0 }; - -bool OpenGLDisplayPlugin::areAllProgramsLoaded() const { - return OpenGLDisplayPlugin::_allProgramsLoaded.load(); -} - void OpenGLDisplayPlugin::present() { auto frameId = (uint64_t)presentCount(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId) uint64_t startPresent = usecTimestampNow(); - if (!OpenGLDisplayPlugin::_allProgramsLoaded.load()) { - const auto& programIDs = shader::allPrograms(); - if (OpenGLDisplayPlugin::_currentLoadingProgramIndex < programIDs.size()) { - gpu::doInBatch("createAndSyncProgram", _gpuContext, [&programIDs](gpu::Batch& batch) { - batch.createAndSyncProgram(programIDs.at(OpenGLDisplayPlugin::_currentLoadingProgramIndex++)); - }); - } else { - OpenGLDisplayPlugin::_allProgramsLoaded.store(true); - } - } - { PROFILE_RANGE_EX(render, "updateFrameData", 0xff00ff00, frameId) updateFrameData(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index acb12aa69a..1cc060161b 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -83,8 +83,6 @@ public: void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override; - bool areAllProgramsLoaded() const override; - protected: friend class PresentThread; @@ -182,8 +180,5 @@ protected: // be serialized through this mutex mutable Mutex _presentMutex; float _hudAlpha{ 1.0f }; - - static std::atomic _allProgramsLoaded; - static unsigned int _currentLoadingProgramIndex; }; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index 415c5135d9..295b9becb8 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -102,8 +102,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_pushProfileRange), (&::gpu::gl::GLBackend::do_popProfileRange), - - (&::gpu::gl::GLBackend::do_createAndSyncProgram), }; #define GL_GET_INTEGER(NAME) glGetIntegerv(GL_##NAME, &const_cast(NAME)); @@ -708,11 +706,6 @@ void GLBackend::do_glColor4f(const Batch& batch, size_t paramOffset) { (void)CHECK_GL_ERROR(); } -void GLBackend::do_createAndSyncProgram(const Batch& batch, size_t paramOffset) { - auto shader = gpu::Shader::createProgram(batch._params[paramOffset + 0]._uint); - gpu::gl::GLShader::sync(*this, *shader); -} - void GLBackend::releaseBuffer(GLuint id, Size size) const { Lock lock(_trashMutex); _currentFrameTrash.buffersTrash.push_back({ id, size }); @@ -866,3 +859,7 @@ void GLBackend::setCameraCorrection(const Mat4& correction, const Mat4& prevRend _pipeline._cameraCorrectionBuffer._buffer->setSubData(0, _transform._correction); _pipeline._cameraCorrectionBuffer._buffer->flush(); } + +void GLBackend::syncProgram(const gpu::ShaderPointer& program) { + gpu::gl::GLShader::sync(*this, *program); +} \ No newline at end of file diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 0a2c1b92ff..07f7df9277 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -249,6 +249,8 @@ public: // Let's try to avoid to do that as much as possible! void syncCache() final override; + void syncProgram(const gpu::ShaderPointer& program) override; + // This is the ugly "download the pixels to sysmem for taking a snapshot" // Just avoid using it, it's ugly and will break performances virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, @@ -380,8 +382,6 @@ public: virtual void do_setStateBlendFactor(const Batch& batch, size_t paramOffset) final; virtual void do_setStateScissorRect(const Batch& batch, size_t paramOffset) final; - virtual void do_createAndSyncProgram(const Batch& batch, size_t paramOffset) final; - virtual GLuint getFramebufferID(const FramebufferPointer& framebuffer) = 0; virtual GLuint getTextureID(const TexturePointer& texture) final; virtual GLuint getBufferID(const Buffer& buffer) = 0; diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 43c1c69287..a9b062a285 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -759,10 +759,4 @@ void Batch::flush() { } buffer->flush(); } -} - -void Batch::createAndSyncProgram(unsigned int programID) { - ADD_COMMAND(createAndSyncProgram); - - _params.emplace_back(programID); } \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index aff6cf5ddd..96a45d3111 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -289,8 +289,6 @@ public: void _glColor4f(float red, float green, float blue, float alpha); - void createAndSyncProgram(unsigned int programID); - // Maybe useful but shoudln't be public. Please convince me otherwise // Well porting to gles i need it... void runLambda(std::function f); @@ -370,8 +368,6 @@ public: COMMAND_pushProfileRange, COMMAND_popProfileRange, - COMMAND_createAndSyncProgram, - NUM_COMMANDS, }; typedef std::vector Commands; diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index dd0d510509..be55e5ba87 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -335,6 +335,39 @@ Size Context::getTextureResourceIdealGPUMemSize() { return Backend::textureResourceIdealGPUMemSize.getValue(); } +void Context::pushProgramsToSync(const std::vector& programIDs, std::function callback, size_t rate) { + std::vector programs; + for (auto programID : programIDs) { + programs.push_back(gpu::Shader::createProgram(programID)); + } + pushProgramsToSync(programs, callback, rate); +} + +void Context::pushProgramsToSync(const std::vector& programs, std::function callback, size_t rate) { + Lock lock(_programsToSyncMutex); + _programsToSyncQueue.emplace(programs, callback, rate == 0 ? programs.size() : rate); +} + +void Context::processProgramsToSync() { + Lock lock(_programsToSyncMutex); + if (!_programsToSyncQueue.empty()) { + ProgramsToSync programsToSync = _programsToSyncQueue.front(); + int numSynced = 0; + while (_nextProgramToSyncIndex < programsToSync.programs.size() && numSynced < programsToSync.rate) { + auto nextProgram = programsToSync.programs.at(_nextProgramToSyncIndex); + _backend->syncProgram(nextProgram); + _syncedPrograms.push_back(nextProgram); + _nextProgramToSyncIndex++; + numSynced++; + } + + if (_nextProgramToSyncIndex == programsToSync.programs.size()) { + programsToSync.callback(); + _nextProgramToSyncIndex = 0; + _programsToSyncQueue.pop(); + } + } +} BatchPointer Context::acquireBatch(const char* name) { Batch* rawBatch = nullptr; diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 011f980957..3fb90fd2e9 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -13,6 +13,7 @@ #include #include +#include #include @@ -61,6 +62,7 @@ public: virtual void render(const Batch& batch) = 0; virtual void syncCache() = 0; + virtual void syncProgram(const gpu::ShaderPointer& program) = 0; virtual void recycle() const = 0; virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; @@ -245,6 +247,20 @@ public: static Size getTextureResourcePopulatedGPUMemSize(); static Size getTextureResourceIdealGPUMemSize(); + struct ProgramsToSync { + ProgramsToSync(const std::vector& programs, std::function callback, size_t rate) : + programs(programs), callback(callback), rate(rate) {} + + std::vector programs; + std::function callback; + size_t rate; + }; + + void pushProgramsToSync(const std::vector& programIDs, std::function callback, size_t rate = 0); + void pushProgramsToSync(const std::vector& programs, std::function callback, size_t rate = 0); + + void processProgramsToSync(); + protected: Context(const Context& context); @@ -256,6 +272,11 @@ protected: RangeTimerPointer _frameRangeTimer; StereoState _stereo; + std::mutex _programsToSyncMutex; + std::queue _programsToSyncQueue; + gpu::Shaders _syncedPrograms; + size_t _nextProgramToSyncIndex { 0 }; + // Sampled at the end of every frame, the stats of all the counters mutable ContextStats _frameStats; diff --git a/libraries/gpu/src/gpu/null/NullBackend.h b/libraries/gpu/src/gpu/null/NullBackend.h index e227b631c7..f934bcf619 100644 --- a/libraries/gpu/src/gpu/null/NullBackend.h +++ b/libraries/gpu/src/gpu/null/NullBackend.h @@ -43,6 +43,8 @@ public: // Let's try to avoid to do that as much as possible! void syncCache() final { } + void syncProgram(const gpu::ShaderPointer& program) final {} + // This is the ugly "download the pixels to sysmem for taking a snapshot" // Just avoid using it, it's ugly and will break performances virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) final { } diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index e9fbd71689..ad49ceafe6 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -217,8 +217,6 @@ public: static const QString& MENU_PATH(); - virtual bool areAllProgramsLoaded() const { return true; } - signals: void recommendedFramebufferSizeChanged(const QSize& size); void resetSensorsRequested(); From ad777201f60dbb66790ded7d792145bfe82a3e99 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 27 Nov 2018 15:08:50 -0800 Subject: [PATCH 20/42] changed comment and cleaned up variable name in getJointName --- libraries/animation/src/AnimSkeleton.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index b124f55641..36664a41fe 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -65,7 +65,7 @@ int AnimSkeleton::nameToJointIndex(const QString& jointName) const { auto itr = _jointIndicesByName.find(jointName); if (_fbxToHifiJointNameMapping.contains(jointName)) { // if the fbx joint name is different than the hifi standard then look up the - // index from that name. + // index from the fbx joint name. itr = _jointIndicesByName.find(_fbxToHifiJointNameMapping[jointName]); } if (itr != _jointIndicesByName.end()) { @@ -131,8 +131,8 @@ std::vector AnimSkeleton::getChildrenOfJoint(int jointIndex) const { const QString AnimSkeleton::getJointName(int jointIndex) const { QString jointName = _joints[jointIndex].name; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(_joints[jointIndex].name))) { - jointName = _fbxToHifiJointNameMapping.key(_joints[jointIndex].name); + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); } return jointName; } From f7fcf503c21f587a2b0910e38f1aa953442da70a Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 3 Dec 2018 14:50:57 -0800 Subject: [PATCH 21/42] removed joint lean from fbxSerializer. it was unused --- libraries/fbx/src/FBXSerializer.cpp | 6 ------ libraries/fbx/src/GLTFSerializer.cpp | 1 - libraries/hfm/src/hfm/HFM.h | 1 - 3 files changed, 8 deletions(-) diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index c7785003f9..cfdf596b98 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -482,7 +482,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointEyeRightName = "EyeRight"; QString jointNeckName = "Neck"; QString jointRootName = "Hips"; - QString jointLeanName = processID(getString(joints.value("jointLean", "jointLean"))); QString jointHeadName = "Head"; QString jointLeftHandName = "LeftHand"; QString jointRightHandName = "RightHand"; @@ -490,7 +489,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointEyeRightID; QString jointNeckID; QString jointRootID; - QString jointLeanID; QString jointHeadID; QString jointLeftHandID; QString jointRightHandID; @@ -614,9 +612,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr } else if (name == jointRootName || (hfmModel.fbxToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRootName]))) { jointRootID = getID(object.properties); - } else if (name == jointLeanName) { - jointLeanID = getID(object.properties); - } else if ((name == jointHeadName) || (hfmModel.fbxToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.fbxToHifiJointNameMapping[jointHeadName]))) { jointHeadID = getID(object.properties); @@ -1451,7 +1446,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr hfmModel.rightEyeJointIndex = modelIDs.indexOf(jointEyeRightID); hfmModel.neckJointIndex = modelIDs.indexOf(jointNeckID); hfmModel.rootJointIndex = modelIDs.indexOf(jointRootID); - hfmModel.leanJointIndex = modelIDs.indexOf(jointLeanID); hfmModel.headJointIndex = modelIDs.indexOf(jointHeadID); hfmModel.leftHandJointIndex = modelIDs.indexOf(jointLeftHandID); hfmModel.rightHandJointIndex = modelIDs.indexOf(jointRightHandID); diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 28d377c605..5485f46905 100644 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1186,7 +1186,6 @@ void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) { qCDebug(modelformat) << " rightEyeJointIndex =" << hfmModel.rightEyeJointIndex; qCDebug(modelformat) << " neckJointIndex =" << hfmModel.neckJointIndex; qCDebug(modelformat) << " rootJointIndex =" << hfmModel.rootJointIndex; - qCDebug(modelformat) << " leanJointIndex =" << hfmModel.leanJointIndex; qCDebug(modelformat) << " headJointIndex =" << hfmModel.headJointIndex; qCDebug(modelformat) << " leftHandJointIndex" << hfmModel.leftHandJointIndex; qCDebug(modelformat) << " rightHandJointIndex" << hfmModel.rightHandJointIndex; diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index b33417666f..ff1b4fd01b 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -274,7 +274,6 @@ public: int rightEyeJointIndex = -1; int neckJointIndex = -1; int rootJointIndex = -1; - int leanJointIndex = -1; int headJointIndex = -1; int leftHandJointIndex = -1; int rightHandJointIndex = -1; From 9315c546d3ac9cfb611e56d12918290649fbb56c Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 3 Dec 2018 16:26:47 -0800 Subject: [PATCH 22/42] Initial version - move updateJoints() to derived class --- .../src/avatars-renderer/Avatar.cpp | 28 ++++++++++++++++++ .../src/avatars-renderer/Avatar.h | 3 ++ libraries/avatars/src/AvatarData.cpp | 29 ++----------------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index fceb146470..99eb08949b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1894,6 +1894,34 @@ QList Avatar::getSkeleton() { return QList(); } +void Avatar::updateJointMappings() { + { + QWriteLocker writeLock(&_jointDataLock); + _fstJointIndices.clear(); + _fstJointNames.clear(); + _jointData.clear(); + } + + //if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) { + // //// + // // TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead? + // // HTTPResourceRequest::doSend() covers all of the following and + // // then some. It doesn't cover the connect() call, so we may + // // want to add a HTTPResourceRequest::doSend() method that does + // // connects. + // QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + // QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL); + // networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + // networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + // DependencyManager::get()->update( + // _skeletonModelURL, -1, "AvatarData::updateJointMappings"); + // QNetworkReply* networkReply = networkAccessManager.get(networkRequest); + // // + // //// + // connect(networkReply, &QNetworkReply::finished, this, &AvatarData::setJointMappingsFromNetworkReply); + //} +} + void Avatar::addToScene(AvatarSharedPointer myHandle, const render::ScenePointer& scene) { if (scene) { auto nodelist = DependencyManager::get(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 8f70b12122..d577ab35bf 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -516,6 +516,9 @@ protected: mutable QReadWriteLock _modelJointIndicesCacheLock; mutable bool _modelJointsCached { false }; + /// Loads the joint indices, names from the FST file (if any) + virtual void updateJointMappings() override; + glm::vec3 _skeletonOffset; std::vector> _attachmentModels; std::vector _attachmentModelsTexturesLoaded; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d9d4b57c31..a369ea9a24 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2209,33 +2209,8 @@ void AvatarData::sendIdentityPacket() { _identityDataChanged = false; } -void AvatarData::updateJointMappings() { - { - QWriteLocker writeLock(&_jointDataLock); - _fstJointIndices.clear(); - _fstJointNames.clear(); - _jointData.clear(); - } - - if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) { - //// - // TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead? - // HTTPResourceRequest::doSend() covers all of the following and - // then some. It doesn't cover the connect() call, so we may - // want to add a HTTPResourceRequest::doSend() method that does - // connects. - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL); - networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); - networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - DependencyManager::get()->update( - _skeletonModelURL, -1, "AvatarData::updateJointMappings"); - QNetworkReply* networkReply = networkAccessManager.get(networkRequest); - // - //// - connect(networkReply, &QNetworkReply::finished, this, &AvatarData::setJointMappingsFromNetworkReply); - } -} +void AvatarData::updateJointMappings() +{ } static const QString JSON_ATTACHMENT_URL = QStringLiteral("modelUrl"); static const QString JSON_ATTACHMENT_JOINT_NAME = QStringLiteral("jointName"); From eb097af79617216c97806c59d3507e9ccd154d9d Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 3 Dec 2018 17:42:39 -0800 Subject: [PATCH 23/42] Remove all .fst downloads from AvatarData and its derived classes --- .../src/avatars/ScriptableAvatar.cpp | 4 -- .../src/avatars-renderer/Avatar.cpp | 28 ---------- .../src/avatars-renderer/Avatar.h | 3 - libraries/avatars/src/AvatarData.cpp | 56 ------------------- libraries/avatars/src/AvatarData.h | 9 --- 5 files changed, 100 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 51038a782f..392e9960e0 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -77,10 +77,6 @@ static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, } void ScriptableAvatar::update(float deltatime) { - if (_bind.isNull() && !_skeletonFBXURL.isEmpty()) { // AvatarData will parse the .fst, but not get the .fbx skeleton. - _bind = DependencyManager::get()->getAnimation(_skeletonFBXURL); - } - // Run animation if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) { if (!_animSkeleton) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 99eb08949b..fceb146470 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1894,34 +1894,6 @@ QList Avatar::getSkeleton() { return QList(); } -void Avatar::updateJointMappings() { - { - QWriteLocker writeLock(&_jointDataLock); - _fstJointIndices.clear(); - _fstJointNames.clear(); - _jointData.clear(); - } - - //if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) { - // //// - // // TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead? - // // HTTPResourceRequest::doSend() covers all of the following and - // // then some. It doesn't cover the connect() call, so we may - // // want to add a HTTPResourceRequest::doSend() method that does - // // connects. - // QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - // QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL); - // networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); - // networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - // DependencyManager::get()->update( - // _skeletonModelURL, -1, "AvatarData::updateJointMappings"); - // QNetworkReply* networkReply = networkAccessManager.get(networkRequest); - // // - // //// - // connect(networkReply, &QNetworkReply::finished, this, &AvatarData::setJointMappingsFromNetworkReply); - //} -} - void Avatar::addToScene(AvatarSharedPointer myHandle, const render::ScenePointer& scene) { if (scene) { auto nodelist = DependencyManager::get(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index d577ab35bf..8f70b12122 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -516,9 +516,6 @@ protected: mutable QReadWriteLock _modelJointIndicesCacheLock; mutable bool _modelJointsCached { false }; - /// Loads the joint indices, names from the FST file (if any) - virtual void updateJointMappings() override; - glm::vec3 _skeletonOffset; std::vector> _attachmentModels; std::vector _attachmentModelsTexturesLoaded; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index a369ea9a24..420fa125e7 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2000,8 +2000,6 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModelURL = expanded; - updateJointMappings(); - if (_clientTraitsHandler) { _clientTraitsHandler->markTraitUpdated(AvatarTraits::SkeletonModelURL); } @@ -2097,57 +2095,6 @@ void AvatarData::detachAll(const QString& modelURL, const QString& jointName) { setAttachmentData(attachmentData); } -void AvatarData::setJointMappingsFromNetworkReply() { - - QNetworkReply* networkReply = static_cast(sender()); - - // before we process this update, make sure that the skeleton model URL hasn't changed - // since we made the FST request - if (networkReply->url() != _skeletonModelURL) { - qCDebug(avatars) << "Refusing to set joint mappings for FST URL that does not match the current URL"; - return; - } - - { - QWriteLocker writeLock(&_jointDataLock); - QByteArray line; - while (!(line = networkReply->readLine()).isEmpty()) { - line = line.trimmed(); - if (line.startsWith("filename")) { - int filenameIndex = line.indexOf('=') + 1; - if (filenameIndex > 0) { - _skeletonFBXURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed())); - } - } - if (!line.startsWith("jointIndex")) { - continue; - } - int jointNameIndex = line.indexOf('=') + 1; - if (jointNameIndex == 0) { - continue; - } - int secondSeparatorIndex = line.indexOf('=', jointNameIndex); - if (secondSeparatorIndex == -1) { - continue; - } - QString jointName = line.mid(jointNameIndex, secondSeparatorIndex - jointNameIndex).trimmed(); - bool ok; - int jointIndex = line.mid(secondSeparatorIndex + 1).trimmed().toInt(&ok); - if (ok) { - while (_fstJointNames.size() < jointIndex + 1) { - _fstJointNames.append(QString()); - } - _fstJointNames[jointIndex] = jointName; - } - } - for (int i = 0; i < _fstJointNames.size(); i++) { - _fstJointIndices.insert(_fstJointNames.at(i), i + 1); - } - } - - networkReply->deleteLater(); -} - void AvatarData::sendAvatarDataPacket(bool sendAll) { auto nodeList = DependencyManager::get(); @@ -2209,9 +2156,6 @@ void AvatarData::sendIdentityPacket() { _identityDataChanged = false; } -void AvatarData::updateJointMappings() -{ } - static const QString JSON_ATTACHMENT_URL = QStringLiteral("modelUrl"); static const QString JSON_ATTACHMENT_JOINT_NAME = QStringLiteral("jointName"); static const QString JSON_ATTACHMENT_TRANSFORM = QStringLiteral("transform"); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 36c6ed6c50..c3819d0d28 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1269,11 +1269,6 @@ public slots: */ void sendIdentityPacket(); - /**jsdoc - * @function MyAvatar.setJointMappingsFromNetworkReply - */ - void setJointMappingsFromNetworkReply(); - /**jsdoc * @function MyAvatar.setSessionUUID * @param {Uuid} sessionUUID @@ -1376,7 +1371,6 @@ protected: mutable HeadData* _headData { nullptr }; QUrl _skeletonModelURL; - QUrl _skeletonFBXURL; QVector _attachmentData; QVector _oldAttachmentData; QString _displayName; @@ -1390,9 +1384,6 @@ protected: QWeakPointer _owningAvatarMixer; - /// Loads the joint indices, names from the FST file (if any) - virtual void updateJointMappings(); - glm::vec3 _targetVelocity; SimpleMovingAverage _averageBytesReceived; From 7f2e427584c469c47e071da5a7351210a3bca7fc Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Mon, 3 Dec 2018 18:56:45 -0800 Subject: [PATCH 24/42] Added DropAfterDelay strategy to Vive Tracker Calibration Dialog This is a hybrid of None and Drop strategies. Basically, if the puck is out of range for less then 1/2 a second we still use it, however any longer then that and we mark it as invalid. --- .../qml/hifi/tablet/OpenVrConfiguration.qml | 2 +- plugins/openvr/src/ViveControllerManager.cpp | 23 ++++++++++++++++++- plugins/openvr/src/ViveControllerManager.h | 5 +++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml index e18fdea444..4ce9fe7c84 100644 --- a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml +++ b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml @@ -871,7 +871,7 @@ Flickable { editable: true colorScheme: hifi.colorSchemes.dark - model: ["None", "Freeze", "Drop"] + model: ["None", "Freeze", "Drop", "DropAfterDelay"] label: "" onCurrentIndexChanged: { diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index af4f4da18c..ff1f10f8ed 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -138,6 +138,8 @@ static QString outOfRangeDataStrategyToString(ViveControllerManager::OutOfRangeD return "Freeze"; case ViveControllerManager::OutOfRangeDataStrategy::Drop: return "Drop"; + case ViveControllerManager::OutOfRangeDataStrategy::DropAfterDelay: + return "DropAfterDelay"; } } @@ -146,6 +148,8 @@ static ViveControllerManager::OutOfRangeDataStrategy stringToOutOfRangeDataStrat return ViveControllerManager::OutOfRangeDataStrategy::Drop; } else if (string == "Freeze") { return ViveControllerManager::OutOfRangeDataStrategy::Freeze; + } else if (string == "DropAfterDelay") { + return ViveControllerManager::OutOfRangeDataStrategy::DropAfterDelay; } else { return ViveControllerManager::OutOfRangeDataStrategy::None; } @@ -302,7 +306,7 @@ void ViveControllerManager::loadSettings() { if (_inputDevice) { const double DEFAULT_ARM_CIRCUMFERENCE = 0.33; const double DEFAULT_SHOULDER_WIDTH = 0.48; - const QString DEFAULT_OUT_OF_RANGE_STRATEGY = "Drop"; + const QString DEFAULT_OUT_OF_RANGE_STRATEGY = "DropAfterDelay"; _inputDevice->_armCircumference = settings.value("armCircumference", QVariant(DEFAULT_ARM_CIRCUMFERENCE)).toDouble(); _inputDevice->_shoulderWidth = settings.value("shoulderWidth", QVariant(DEFAULT_SHOULDER_WIDTH)).toDouble(); _inputDevice->_outOfRangeDataStrategy = stringToOutOfRangeDataStrategy(settings.value("outOfRangeDataStrategy", QVariant(DEFAULT_OUT_OF_RANGE_STRATEGY)).toString()); @@ -516,6 +520,7 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid && poseIndex <= controller::TRACKED_OBJECT_15) { + uint64_t now = usecTimestampNow(); controller::Pose pose; switch (_outOfRangeDataStrategy) { case OutOfRangeDataStrategy::Drop: @@ -544,6 +549,22 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde _nextSimPoseData.angularVelocities[deviceIndex] = _lastSimPoseData.angularVelocities[deviceIndex]; } break; + case OutOfRangeDataStrategy::DropAfterDelay: + const uint64_t DROP_DELAY_TIME = 500 * USECS_PER_MSEC; + + // All Running_OK results are valid. + if (_nextSimPoseData.vrPoses[deviceIndex].eTrackingResult == vr::TrackingResult_Running_OK) { + pose = buildPose(_nextSimPoseData.poses[deviceIndex], _nextSimPoseData.linearVelocities[deviceIndex], _nextSimPoseData.angularVelocities[deviceIndex]); + // update the timer + _simDataRunningOkTimestampMap[deviceIndex] = now; + } else if (now - _simDataRunningOkTimestampMap[deviceIndex] < DROP_DELAY_TIME) { + // report the pose, even though pose is out-of-range + pose = buildPose(_nextSimPoseData.poses[deviceIndex], _nextSimPoseData.linearVelocities[deviceIndex], _nextSimPoseData.angularVelocities[deviceIndex]); + } else { + // this pose has been out-of-range for too long. + pose.valid = false; + } + break; } if (pose.valid) { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 647702ae77..dbd248dc53 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -63,7 +63,8 @@ public: enum class OutOfRangeDataStrategy { None, Freeze, - Drop + Drop, + DropAfterDelay }; private: @@ -205,6 +206,8 @@ private: bool _hmdTrackingEnabled { true }; + std::map _simDataRunningOkTimestampMap; + QString configToString(Config config); friend class ViveControllerManager; }; From f3236e0843299552dae90e535712088a36b81f3e Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 4 Dec 2018 10:45:32 -0800 Subject: [PATCH 25/42] Remove FST joint members from AvatarData --- libraries/avatars/src/AvatarData.cpp | 9 ++------- libraries/avatars/src/AvatarData.h | 11 +---------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 420fa125e7..8705c35630 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1776,16 +1776,11 @@ int AvatarData::getFauxJointIndex(const QString& name) const { int AvatarData::getJointIndex(const QString& name) const { int result = getFauxJointIndex(name); - if (result != -1) { - return result; - } - QReadLocker readLock(&_jointDataLock); - return _fstJointIndices.value(name) - 1; + return result; } QStringList AvatarData::getJointNames() const { - QReadLocker readLock(&_jointDataLock); - return _fstJointNames; + return QStringList(); } glm::quat AvatarData::getOrientationOutbound() const { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index c3819d0d28..49fd49df58 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1377,9 +1377,6 @@ protected: QString _sessionDisplayName { }; bool _lookAtSnappingEnabled { true }; - QHash _fstJointIndices; ///< 1-based, since zero is returned for missing keys - QStringList _fstJointNames; ///< in order of depth-first traversal - quint64 _errorLogExpiry; ///< time in future when to log an error QWeakPointer _owningAvatarMixer; @@ -1487,11 +1484,8 @@ protected: T readLockWithNamedJointIndex(const QString& name, const T& defaultValue, F f) const { int index = getFauxJointIndex(name); QReadLocker readLock(&_jointDataLock); - if (index == -1) { - index = _fstJointIndices.value(name) - 1; - } - // The first conditional is superfluous, but illsutrative + // The first conditional is superfluous, but illustrative if (index == -1 || index < _jointData.size()) { return defaultValue; } @@ -1508,9 +1502,6 @@ protected: void writeLockWithNamedJointIndex(const QString& name, F f) { int index = getFauxJointIndex(name); QWriteLocker writeLock(&_jointDataLock); - if (index == -1) { - index = _fstJointIndices.value(name) - 1; - } if (index == -1) { return; } From edab74caa46dd34d467bb3174f115f44705c1a61 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 4 Dec 2018 16:20:46 -0800 Subject: [PATCH 26/42] mapped the model joint names to hifi compliant joint names in FBX serializer --- libraries/animation/src/AnimSkeleton.cpp | 41 ++++++------------- libraries/animation/src/AnimSkeleton.h | 3 +- .../src/avatars-renderer/Avatar.cpp | 7 ---- libraries/fbx/src/FBXSerializer.cpp | 37 +++++++++-------- libraries/hfm/src/hfm/HFM.h | 2 +- 5 files changed, 34 insertions(+), 56 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 36664a41fe..16c2c1cc7e 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -23,8 +23,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { for (auto& joint : hfmModel.joints) { joints.push_back(joint); } - - _fbxToHifiJointNameMapping = hfmModel.fbxToHifiJointNameMapping; buildSkeletonFromJoints(joints, hfmModel.jointRotationOffsets); // we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose @@ -61,14 +59,8 @@ AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap AnimSkeleton::getChildrenOfJoint(int jointIndex) const { return result; } -const QString AnimSkeleton::getJointName(int jointIndex) const { - - QString jointName = _joints[jointIndex].name; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - return jointName; +const QString& AnimSkeleton::getJointName(int jointIndex) const { + return _joints[jointIndex].name; } AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& relativePoses) const { @@ -258,25 +245,21 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _nonMirroredIndices.clear(); _mirrorMap.reserve(_jointsSize); for (int i = 0; i < _jointsSize; i++) { - QString jointName = _joints[i].name; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - if (jointName != "Hips" && jointName != "Spine" && - jointName != "Spine1" && jointName != "Spine2" && - jointName != "Neck" && jointName != "Head" && - !((jointName.startsWith("Left") || jointName.startsWith("Right")) && - jointName != "LeftEye" && jointName != "RightEye")) { + if (_joints[i].name != "Hips" && _joints[i].name != "Spine" && + _joints[i].name != "Spine1" && _joints[i].name != "Spine2" && + _joints[i].name != "Neck" && _joints[i].name != "Head" && + !((_joints[i].name.startsWith("Left") || _joints[i].name.startsWith("Right")) && + _joints[i].name != "LeftEye" && _joints[i].name != "RightEye")) { // HACK: we don't want to mirror some joints so we remember their indices // so we can restore them after a future mirror operation _nonMirroredIndices.push_back(i); } int mirrorJointIndex = -1; - if (jointName.startsWith("Left")) { - QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); + if (_joints[i].name.startsWith("Left")) { + QString mirrorJointName = QString(_joints[i].name).replace(0, 4, "Right"); mirrorJointIndex = nameToJointIndex(mirrorJointName); - } else if (jointName.startsWith("Right")) { - QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); + } else if (_joints[i].name.startsWith("Right")) { + QString mirrorJointName = QString(_joints[i].name).replace(0, 5, "Left"); mirrorJointIndex = nameToJointIndex(mirrorJointName); } if (mirrorJointIndex >= 0) { diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index 777cb61302..14f39eedbc 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -27,7 +27,7 @@ public: explicit AnimSkeleton(const std::vector& joints, const QMap jointOffsets); int nameToJointIndex(const QString& jointName) const; - const QString getJointName(int jointIndex) const; + const QString& getJointName(int jointIndex) const; int getNumJoints() const; int getChainDepth(int jointIndex) const; @@ -79,7 +79,6 @@ protected: std::vector _mirrorMap; QHash _jointIndicesByName; std::vector> _clusterBindMatrixOriginalValues; - QMap _fbxToHifiJointNameMapping; // no copies AnimSkeleton(const AnimSkeleton&) = delete; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index f3017049a7..fceb146470 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1437,13 +1437,6 @@ int Avatar::getJointIndex(const QString& name) const { withValidJointIndicesCache([&]() { if (_modelJointIndicesCache.contains(name)) { result = _modelJointIndicesCache[name] - 1; - } else { - // doesn't contain name. check the fbx-to-hifi joint name mapping - if (_skeletonModel && _skeletonModel->isActive()) { - if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name])) { - result = _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name]] - 1; - } - } } }); return result; diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index cfdf596b98..1581204819 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -419,15 +419,15 @@ QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) { QMap getJointNameMapping(const QVariantHash& mapping) { static const QString JOINT_NAME_MAPPING_FIELD = "jointMap"; - QMap fbxToHifiJointNameMap; + QMap hfmToHifiJointNameMap; if (!mapping.isEmpty() && mapping.contains(JOINT_NAME_MAPPING_FIELD) && mapping[JOINT_NAME_MAPPING_FIELD].type() == QVariant::Hash) { auto jointNames = mapping[JOINT_NAME_MAPPING_FIELD].toHash(); for (auto itr = jointNames.begin(); itr != jointNames.end(); itr++) { - fbxToHifiJointNameMap.insert(itr.key(), itr.value().toString()); - qCDebug(modelformat) << "the mapped key " << itr.key() << " has a value of " << fbxToHifiJointNameMap[itr.key()]; + hfmToHifiJointNameMap.insert(itr.key(), itr.value().toString()); + qCDebug(modelformat) << "the mapped key " << itr.key() << " has a value of " << hfmToHifiJointNameMap[itr.key()]; } } - return fbxToHifiJointNameMap; + return hfmToHifiJointNameMap; } QMap getJointRotationOffsets(const QVariantHash& mapping) { @@ -530,8 +530,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr HFMModel& hfmModel = *hfmModelPtr; hfmModel.originalURL = url; - hfmModel.fbxToHifiJointNameMapping.clear(); - hfmModel.fbxToHifiJointNameMapping = getJointNameMapping(mapping); + hfmModel.hfmToHifiJointNameMapping.clear(); + hfmModel.hfmToHifiJointNameMapping = getJointNameMapping(mapping); float unitScaleFactor = 1.0f; glm::vec3 ambientColor; @@ -600,31 +600,31 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr hifiGlobalNodeID = id; } - if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye" || (hfmModel.fbxToHifiJointNameMapping.contains(jointEyeLeftName) && (name == hfmModel.fbxToHifiJointNameMapping[jointEyeLeftName]))) { + if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye" || (hfmModel.hfmToHifiJointNameMapping.contains(jointEyeLeftName) && (name == hfmModel.hfmToHifiJointNameMapping[jointEyeLeftName]))) { jointEyeLeftID = getID(object.properties); - } else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye" || (hfmModel.fbxToHifiJointNameMapping.contains(jointEyeRightName) && (name == hfmModel.fbxToHifiJointNameMapping[jointEyeRightName]))) { + } else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye" || (hfmModel.hfmToHifiJointNameMapping.contains(jointEyeRightName) && (name == hfmModel.hfmToHifiJointNameMapping[jointEyeRightName]))) { jointEyeRightID = getID(object.properties); - } else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck" || (hfmModel.fbxToHifiJointNameMapping.contains(jointNeckName) && (name == hfmModel.fbxToHifiJointNameMapping[jointNeckName]))) { + } else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck" || (hfmModel.hfmToHifiJointNameMapping.contains(jointNeckName) && (name == hfmModel.hfmToHifiJointNameMapping[jointNeckName]))) { jointNeckID = getID(object.properties); - } else if (name == jointRootName || (hfmModel.fbxToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRootName]))) { + } else if (name == jointRootName || (hfmModel.hfmToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.hfmToHifiJointNameMapping[jointRootName]))) { jointRootID = getID(object.properties); - } else if ((name == jointHeadName) || (hfmModel.fbxToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.fbxToHifiJointNameMapping[jointHeadName]))) { + } else if ((name == jointHeadName) || (hfmModel.hfmToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.hfmToHifiJointNameMapping[jointHeadName]))) { jointHeadID = getID(object.properties); - } else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand" || (hfmModel.fbxToHifiJointNameMapping.contains(jointLeftHandName) && (name == hfmModel.fbxToHifiJointNameMapping[jointLeftHandName]))) { + } else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand" || (hfmModel.hfmToHifiJointNameMapping.contains(jointLeftHandName) && (name == hfmModel.hfmToHifiJointNameMapping[jointLeftHandName]))) { jointLeftHandID = getID(object.properties); - } else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand" || (hfmModel.fbxToHifiJointNameMapping.contains(jointRightHandName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRightHandName]))) { + } else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand" || (hfmModel.hfmToHifiJointNameMapping.contains(jointRightHandName) && (name == hfmModel.hfmToHifiJointNameMapping[jointRightHandName]))) { jointRightHandID = getID(object.properties); - } else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End" || (hfmModel.fbxToHifiJointNameMapping.contains("LeftToe") && (name == hfmModel.fbxToHifiJointNameMapping["LeftToe"]))) { + } else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End" || (hfmModel.hfmToHifiJointNameMapping.contains("LeftToe") && (name == hfmModel.hfmToHifiJointNameMapping["LeftToe"]))) { jointLeftToeID = getID(object.properties); - } else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End" || (hfmModel.fbxToHifiJointNameMapping.contains("RightToe") && (name == hfmModel.fbxToHifiJointNameMapping["RightToe"]))) { + } else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End" || (hfmModel.hfmToHifiJointNameMapping.contains("RightToe") && (name == hfmModel.hfmToHifiJointNameMapping["RightToe"]))) { jointRightToeID = getID(object.properties); } @@ -1398,6 +1398,9 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr } joint.inverseBindRotation = joint.inverseDefaultRotation; joint.name = fbxModel.name; + if (hfmModel.hfmToHifiJointNameMapping.contains(hfmModel.hfmToHifiJointNameMapping.key(joint.name))) { + joint.name = hfmModel.hfmToHifiJointNameMapping.key(fbxModel.name); + } foreach (const QString& childID, _connectionChildMap.values(modelID)) { QString type = typeFlags.value(childID); @@ -1833,8 +1836,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointName = itr.key(); glm::quat rotationOffset = itr.value(); int jointIndex = hfmModel.getJointIndex(jointName); - if (hfmModel.fbxToHifiJointNameMapping.contains(jointName)) { - jointIndex = hfmModel.getJointIndex(hfmModel.fbxToHifiJointNameMapping[jointName]); + if (hfmModel.hfmToHifiJointNameMapping.contains(jointName)) { + jointIndex = hfmModel.getJointIndex(hfmModel.hfmToHifiJointNameMapping[jointName]); } if (jointIndex != -1) { hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index ff1b4fd01b..3cc12724d5 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -312,7 +312,7 @@ public: QList blendshapeChannelNames; QMap jointRotationOffsets; - QMap fbxToHifiJointNameMapping; + QMap hfmToHifiJointNameMapping; }; }; From 7723261cb9aea50c7f59b713b239d1bf857daf6e Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 3 Dec 2018 16:51:14 -0800 Subject: [PATCH 27/42] Remove deferred script loading logic --- libraries/script-engine/src/ScriptEngine.cpp | 115 ------------------- libraries/script-engine/src/ScriptEngine.h | 3 - 2 files changed, 118 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 455fd93f4b..6f98dd2864 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2061,68 +2061,6 @@ bool ScriptEngine::hasEntityScriptDetails(const EntityItemID& entityID) const { return _entityScripts.contains(entityID); } -const static EntityItemID BAD_SCRIPT_UUID_PLACEHOLDER { "{20170224-dead-face-0000-cee000021114}" }; - -void ScriptEngine::processDeferredEntityLoads(const QString& entityScript, const EntityItemID& leaderID) { - QList retryLoads; - QMutableListIterator i(_deferredEntityLoads); - while (i.hasNext()) { - auto retry = i.next(); - if (retry.entityScript == entityScript) { - retryLoads << retry; - i.remove(); - } - } - foreach(DeferredLoadEntity retry, retryLoads) { - // check whether entity was since been deleted - - EntityScriptDetails details; - if (!getEntityScriptDetails(retry.entityID, details)) { - qCDebug(scriptengine) << "processDeferredEntityLoads -- entity details gone (entity deleted?)" - << retry.entityID; - continue; - } - - // check whether entity has since been unloaded or otherwise errored-out - if (details.status != EntityScriptStatus::PENDING) { - qCDebug(scriptengine) << "processDeferredEntityLoads -- entity status no longer PENDING; " - << retry.entityID << details.status; - continue; - } - - // propagate leader's failure reasons to the pending entity - EntityScriptDetails leaderDetails; - { - QWriteLocker locker { &_entityScriptsLock }; - leaderDetails = _entityScripts[leaderID]; - } - if (leaderDetails.status != EntityScriptStatus::RUNNING) { - qCDebug(scriptengine) << QString("... pending load of %1 cancelled (leader: %2 status: %3)") - .arg(retry.entityID.toString()).arg(leaderID.toString()).arg(leaderDetails.status); - - auto extraDetail = QString("\n(propagated from %1)").arg(leaderID.toString()); - if (leaderDetails.status == EntityScriptStatus::ERROR_LOADING_SCRIPT || - leaderDetails.status == EntityScriptStatus::ERROR_RUNNING_SCRIPT) { - // propagate same error so User doesn't have to hunt down stampede's leader - updateEntityScriptStatus(retry.entityID, leaderDetails.status, leaderDetails.errorInfo + extraDetail); - } else { - // the leader Entity somehow ended up in some other state (rapid-fire delete or unload could cause) - updateEntityScriptStatus(retry.entityID, EntityScriptStatus::ERROR_LOADING_SCRIPT, - "A previous Entity failed to load using this script URL; reload to try again." + extraDetail); - } - continue; - } - - if (_occupiedScriptURLs.contains(retry.entityScript)) { - qCWarning(scriptengine) << "--- SHOULD NOT HAPPEN -- recursive call into processDeferredEntityLoads" << retry.entityScript; - continue; - } - - // if we made it here then the leading entity was successful so proceed with normal load - loadEntityScript(retry.entityID, retry.entityScript, false); - } -} - void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "loadEntityScript", @@ -2147,40 +2085,6 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& updateEntityScriptStatus(entityID, EntityScriptStatus::PENDING, "...pending..."); } - // This "occupied" approach allows multiple Entities to boot from the same script URL while still taking - // full advantage of cacheable require modules. This only affects Entities literally coming in back-to-back - // before the first one has time to finish loading. - if (_occupiedScriptURLs.contains(entityScript)) { - auto currentEntityID = _occupiedScriptURLs[entityScript]; - if (currentEntityID == BAD_SCRIPT_UUID_PLACEHOLDER) { - if (forceRedownload) { - // script was previously marked unusable, but we're reloading so reset it - _occupiedScriptURLs.remove(entityScript); - } else { - // since not reloading, assume that the exact same input would produce the exact same output again - // note: this state gets reset with "reload all scripts," leaving/returning to a Domain, clear cache, etc. -#ifdef DEBUG_ENTITY_STATES - qCDebug(scriptengine) << QString("loadEntityScript.cancelled entity: %1 (previous script failure)") - .arg(entityID.toString()); -#endif - updateEntityScriptStatus(entityID, EntityScriptStatus::ERROR_LOADING_SCRIPT, - "A previous Entity failed to load using this script URL; reload to try again."); - return; - } - } else { - // another entity is busy loading from this script URL so wait for them to finish -#ifdef DEBUG_ENTITY_STATES - qCDebug(scriptengine) << QString("loadEntityScript.deferring[%0] entity: %1 (waiting on %2 )") - .arg(_deferredEntityLoads.size()).arg(entityID.toString()).arg(currentEntityID.toString()); -#endif - _deferredEntityLoads.push_back({ entityID, entityScript }); - return; - } - } - - // the scriptURL slot is available; flag as in-use - _occupiedScriptURLs[entityScript] = entityID; - #ifdef DEBUG_ENTITY_STATES { EntityScriptDetails details; @@ -2223,10 +2127,6 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& qCDebug(scriptengine) << "loadEntityScript.contentAvailable -- aborting"; #endif } - // recheck whether us since may have been set to BAD_SCRIPT_UUID_PLACEHOLDER in entityScriptContentAvailable - if (_occupiedScriptURLs.contains(entityScript) && _occupiedScriptURLs[entityScript] == entityID) { - _occupiedScriptURLs.remove(entityScript); - } }); }, forceRedownload); } @@ -2301,13 +2201,6 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co newDetails.errorInfo = errorInfo; newDetails.status = status; setEntityScriptDetails(entityID, newDetails); - -#ifdef DEBUG_ENTITY_STATES - qCDebug(scriptengine) << "entityScriptContentAvailable -- flagging as BAD_SCRIPT_UUID_PLACEHOLDER"; -#endif - // flag the original entityScript as unusuable - _occupiedScriptURLs[entityScript] = BAD_SCRIPT_UUID_PLACEHOLDER; - processDeferredEntityLoads(entityScript, entityID); }; // NETWORK / FILESYSTEM ERRORS @@ -2441,9 +2334,6 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co callEntityScriptMethod(entityID, "preload"); emit entityScriptPreloadFinished(entityID); - - _occupiedScriptURLs.remove(entityScript); - processDeferredEntityLoads(entityScript, entityID); } /**jsdoc @@ -2499,10 +2389,6 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldR } stopAllTimersForEntityScript(entityID); - { - // FIXME: shouldn't have to do this here, but currently something seems to be firing unloads moments after firing initial load requests - processDeferredEntityLoads(scriptText, entityID); - } } } @@ -2532,7 +2418,6 @@ void ScriptEngine::unloadAllEntityScripts() { _entityScripts.clear(); } emit entityScriptDetailsUpdated(); - _occupiedScriptURLs.clear(); #ifdef DEBUG_ENGINE_STATE _debugDump( diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index fe8396bc50..8fe50aee78 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -747,7 +747,6 @@ protected: void updateEntityScriptStatus(const EntityItemID& entityID, const EntityScriptStatus& status, const QString& errorInfo = QString()); void setEntityScriptDetails(const EntityItemID& entityID, const EntityScriptDetails& details); void setParentURL(const QString& parentURL) { _parentURL = parentURL; } - void processDeferredEntityLoads(const QString& entityScript, const EntityItemID& leaderID); QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); void stopTimer(QTimer* timer); @@ -783,8 +782,6 @@ protected: QSet _includedURLs; mutable QReadWriteLock _entityScriptsLock { QReadWriteLock::Recursive }; QHash _entityScripts; - QHash _occupiedScriptURLs; - QList _deferredEntityLoads; EntityScriptContentAvailableMap _contentAvailableQueue; bool _isThreaded { false }; From 16144b663036cbce530f77091a4ab8217f22450f Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 5 Dec 2018 17:14:40 -0800 Subject: [PATCH 28/42] Move the previously deleted FST reader down to the ScriptableAvatar class --- .../src/avatars/ScriptableAvatar.cpp | 96 +++++++++++++++++++ .../src/avatars/ScriptableAvatar.h | 32 +++++++ 2 files changed, 128 insertions(+) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 392e9960e0..29a66b44fc 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -19,6 +19,9 @@ #include #include #include +#include +#include + ScriptableAvatar::ScriptableAvatar() { _clientTraitsHandler = std::unique_ptr(new ClientTraitsHandler(this)); @@ -62,11 +65,28 @@ AnimationDetails ScriptableAvatar::getAnimationDetails() { return _animationDetails; } +int ScriptableAvatar::getJointIndex(const QString& name) const { + // Faux joints: + int result = AvatarData::getJointIndex(name); + if (result != -1) { + return result; + } + QReadLocker readLock(&_jointDataLock); + return _fstJointIndices.value(name) - 1; +} + +QStringList ScriptableAvatar::getJointNames() const { + QReadLocker readLock(&_jointDataLock); + return _fstJointNames; + return QStringList(); +} + void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _bind.reset(); _animSkeleton.reset(); AvatarData::setSkeletonModelURL(skeletonModelURL); + updateJointMappings(); } static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, const glm::vec3 translation) { @@ -142,6 +162,82 @@ void ScriptableAvatar::update(float deltatime) { _clientTraitsHandler->sendChangedTraitsToMixer(); } +void ScriptableAvatar::updateJointMappings() { + { + QWriteLocker writeLock(&_jointDataLock); + _fstJointIndices.clear(); + _fstJointNames.clear(); + _jointData.clear(); + } + + if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) { + //// + // TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead? + // HTTPResourceRequest::doSend() covers all of the following and + // then some. It doesn't cover the connect() call, so we may + // want to add a HTTPResourceRequest::doSend() method that does + // connects. + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL); + networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + DependencyManager::get()->update( + _skeletonModelURL, -1, "AvatarData::updateJointMappings"); + QNetworkReply* networkReply = networkAccessManager.get(networkRequest); + // + //// + connect(networkReply, &QNetworkReply::finished, this, &ScriptableAvatar::setJointMappingsFromNetworkReply); + } +} + +void ScriptableAvatar::setJointMappingsFromNetworkReply() { + QNetworkReply* networkReply = static_cast(sender()); + // before we process this update, make sure that the skeleton model URL hasn't changed + // since we made the FST request + if (networkReply->url() != _skeletonModelURL) { + qCDebug(avatars) << "Refusing to set joint mappings for FST URL that does not match the current URL"; + networkReply->deleteLater(); + return; + } + { + QWriteLocker writeLock(&_jointDataLock); + QByteArray line; + while (!(line = networkReply->readLine()).isEmpty()) { + line = line.trimmed(); + if (line.startsWith("filename")) { + int filenameIndex = line.indexOf('=') + 1; + if (filenameIndex > 0) { + _skeletonFBXURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed())); + } + } + if (!line.startsWith("jointIndex")) { + continue; + } + int jointNameIndex = line.indexOf('=') + 1; + if (jointNameIndex == 0) { + continue; + } + int secondSeparatorIndex = line.indexOf('=', jointNameIndex); + if (secondSeparatorIndex == -1) { + continue; + } + QString jointName = line.mid(jointNameIndex, secondSeparatorIndex - jointNameIndex).trimmed(); + bool ok; + int jointIndex = line.mid(secondSeparatorIndex + 1).trimmed().toInt(&ok); + if (ok) { + while (_fstJointNames.size() < jointIndex + 1) { + _fstJointNames.append(QString()); + } + _fstJointNames[jointIndex] = jointName; + } + } + for (int i = 0; i < _fstJointNames.size(); i++) { + _fstJointIndices.insert(_fstJointNames.at(i), i + 1); + } + } + networkReply->deleteLater(); +} + void ScriptableAvatar::setHasProceduralBlinkFaceMovement(bool hasProceduralBlinkFaceMovement) { _headData->setHasProceduralBlinkFaceMovement(hasProceduralBlinkFaceMovement); } diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 578bd84a8f..66b0b5ae3f 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -153,6 +153,27 @@ public: */ Q_INVOKABLE AnimationDetails getAnimationDetails(); + /**jsdoc + * Get the names of all the joints in the current avatar. + * @function MyAvatar.getJointNames + * @returns {string[]} The joint names. + * @example Report the names of all the joints in your current avatar. + * print(JSON.stringify(MyAvatar.getJointNames())); + */ + Q_INVOKABLE virtual QStringList getJointNames() const override; + + /**jsdoc + * Get the joint index for a named joint. The joint index value is the position of the joint in the array returned by + * {@link MyAvatar.getJointNames} or {@link Avatar.getJointNames}. + * @function MyAvatar.getJointIndex + * @param {string} name - The name of the joint. + * @returns {number} The index of the joint. + * @example Report the index of your avatar's left arm joint. + * print(JSON.stringify(MyAvatar.getJointIndex("LeftArm")); + */ + /// Returns the index of the joint with the specified name, or -1 if not found/unknown. + Q_INVOKABLE virtual int getJointIndex(const QString& name) const override; + virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking = false) override; @@ -167,12 +188,23 @@ public: public slots: void update(float deltatime); + /**jsdoc + * @function MyAvatar.setJointMappingsFromNetworkReply + */ + void setJointMappingsFromNetworkReply(); + private: AnimationPointer _animation; AnimationDetails _animationDetails; QStringList _maskedJoints; AnimationPointer _bind; // a sleazy way to get the skeleton, given the various library/cmake dependencies std::shared_ptr _animSkeleton; + QHash _fstJointIndices; ///< 1-based, since zero is returned for missing keys + QStringList _fstJointNames; ///< in order of depth-first traversal + QUrl _skeletonFBXURL; + + /// Loads the joint indices, names from the FST file (if any) + void updateJointMappings(); }; #endif // hifi_ScriptableAvatar_h From 8620a5a4c3649903a4f50c19684e95f6749f17bb Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 6 Dec 2018 13:07:59 -0800 Subject: [PATCH 29/42] CR changes --- scripts/system/html/js/listView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/js/listView.js b/scripts/system/html/js/listView.js index b19ba7e0cb..eec3f833ad 100644 --- a/scripts/system/html/js/listView.js +++ b/scripts/system/html/js/listView.js @@ -242,7 +242,7 @@ ListView.prototype = { resize: function() { if (!this.elTableBody || !this.elTableScroll) { - debugPrint("ListView.resize - no valid table body or table scroll element"); + console.log("ListView.resize - no valid table body or table scroll element"); return; } this.preResizeFunction(); @@ -284,7 +284,7 @@ ListView.prototype = { initialize: function() { if (!this.elTableBody || !this.elTableScroll) { - debugPrint("ListView.initialize - no valid table body or table scroll element"); + console.log("ListView.initialize - no valid table body or table scroll element"); return; } From 6d40bc9c2f0fdccccf2b76c499469fda98916192 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Nov 2018 19:41:56 +0100 Subject: [PATCH 30/42] userData error message continues popup fix --- scripts/system/html/css/edit-style.css | 24 +++++ scripts/system/html/js/entityProperties.js | 103 +++++++++++++-------- 2 files changed, 86 insertions(+), 41 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 415d8e567f..641b9bb5fe 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1663,3 +1663,27 @@ input.number-slider { .collapse-icon { cursor: pointer; } + +#property-userData-editor.error { + border: 2px solid red; +} + +#property-userData-editorStatus { + color: white; + background-color: red; + padding: 5px; + display: none; + cursor: pointer; +} + +#property-materialData-editor.error { + border: 2px solid red; +} + +#property-materialData-editorStatus { + color: white; + background-color: red; + padding: 5px; + display: none; + cursor: pointer; +} diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index dc304c6803..bc93a1a9b7 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1823,7 +1823,7 @@ function createStringProperty(property, elProperty) { type="text" ${propertyData.placeholder ? 'placeholder="' + propertyData.placeholder + '"' : ''} ${propertyData.readOnly ? 'readonly' : ''}> - `) + `); elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); @@ -2359,31 +2359,41 @@ function saveUserData() { saveJSONUserData(true); } +function setJSONError(property, isError) { + $("#property-"+ property + "-editor").toggleClass('error', isError); + var $propertyUserDataEditorStatus = $("#property-"+ property + "-editorStatus"); + $propertyUserDataEditorStatus.css('display', isError ? 'block' : 'none'); + $propertyUserDataEditorStatus.text(isError ? 'Invalid JSON code - look for red X in your code' : ''); +} + function setUserDataFromEditor(noUpdate) { let json = null; + let errorFound = false; try { json = editor.get(); } catch (e) { - alert('Invalid JSON code - look for red X in your code ', +e); + errorFound = true; } - if (json === null) { + + setJSONError('userData', errorFound); + + if (json !== null) { return; + } + + let text = editor.getText(); + if (noUpdate) { + EventBridge.emitWebEvent( + JSON.stringify({ + id: lastEntityID, + type: "saveUserData", + properties: { + userData: text + } + }) + ); } else { - let text = editor.getText(); - if (noUpdate === true) { - EventBridge.emitWebEvent( - JSON.stringify({ - id: lastEntityID, - type: "saveUserData", - properties: { - userData: text - } - }) - ); - return; - } else { - updateProperty('userData', text, false); - } + updateProperty('userData', text, false); } } @@ -2505,9 +2515,10 @@ function hideUserDataSaved() { function showStaticUserData() { if (editor !== null) { - $('#property-userData-static').show(); - $('#property-userData-static').css('height', $('#property-userData-editor').height()); - $('#property-userData-static').text(editor.getText()); + let $propertyUserDataStatic = $('#property-userData-static'); + $propertyUserDataStatic.show(); + $propertyUserDataStatic.css('height', $('#property-userData-editor').height()); + $propertyUserDataStatic.text(editor.getText()); } } @@ -2528,6 +2539,7 @@ function getEditorJSON() { function deleteJSONEditor() { if (editor !== null) { + setJSONError('userData', false); editor.destroy(); editor = null; } @@ -2578,29 +2590,31 @@ function saveMaterialData() { function setMaterialDataFromEditor(noUpdate) { let json = null; + let errorFound = false; try { json = materialEditor.get(); } catch (e) { - alert('Invalid JSON code - look for red X in your code ', +e); + errorFound = true; } + + setJSONError('materialData', errorFound); + if (json === null) { return; + } + let text = materialEditor.getText(); + if (noUpdate) { + EventBridge.emitWebEvent( + JSON.stringify({ + id: lastEntityID, + type: "saveMaterialData", + properties: { + materialData: text + } + }) + ); } else { - let text = materialEditor.getText(); - if (noUpdate === true) { - EventBridge.emitWebEvent( - JSON.stringify({ - id: lastEntityID, - type: "saveMaterialData", - properties: { - materialData: text - } - }) - ); - return; - } else { - updateProperty('materialData', text, false); - } + updateProperty('materialData', text, false); } } @@ -2667,9 +2681,10 @@ function hideMaterialDataSaved() { function showStaticMaterialData() { if (materialEditor !== null) { - $('#property-materialData-static').show(); - $('#property-materialData-static').css('height', $('#property-materialData-editor').height()); - $('#property-materialData-static').text(materialEditor.getText()); + let $propertyMaterialDataStatic = $('#property-materialData-static'); + $propertyMaterialDataStatic.show(); + $propertyMaterialDataStatic.css('height', $('#property-materialData-editor').height()); + $propertyMaterialDataStatic.text(materialEditor.getText()); } } @@ -2955,7 +2970,7 @@ function loaded() { let elServerScriptError = document.getElementById("property-serverScripts-error"); let elServerScriptStatus = document.getElementById("property-serverScripts-status"); elServerScriptError.value = data.errorInfo; - // If we just set elServerScriptError's diplay to block or none, we still end up with + // If we just set elServerScriptError's display to block or none, we still end up with // it's parent contributing 21px bottom padding even when elServerScriptError is display:none. // So set it's parent to block or none elServerScriptError.parentElement.style.display = data.errorInfo ? "block" : "none"; @@ -3314,12 +3329,15 @@ function loaded() { elStaticUserData.setAttribute("id", userDataElementID + "-static"); let elUserDataEditor = document.createElement('div'); elUserDataEditor.setAttribute("id", userDataElementID + "-editor"); + let elUserDataEditorStatus = document.createElement('div'); + elUserDataEditorStatus.setAttribute("id", userDataElementID + "-editorStatus"); let elUserDataSaved = document.createElement('span'); elUserDataSaved.setAttribute("id", userDataElementID + "-saved"); elUserDataSaved.innerText = "Saved!"; elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elUserDataSaved); elDiv.insertBefore(elStaticUserData, elUserData); elDiv.insertBefore(elUserDataEditor, elUserData); + elDiv.insertBefore(elUserDataEditorStatus, elUserData); // Material Data let materialDataProperty = properties["materialData"]; @@ -3330,12 +3348,15 @@ function loaded() { elStaticMaterialData.setAttribute("id", materialDataElementID + "-static"); let elMaterialDataEditor = document.createElement('div'); elMaterialDataEditor.setAttribute("id", materialDataElementID + "-editor"); + let elMaterialDataEditorStatus = document.createElement('div'); + elMaterialDataEditorStatus.setAttribute("id", materialDataElementID + "-editorStatus"); let elMaterialDataSaved = document.createElement('span'); elMaterialDataSaved.setAttribute("id", materialDataElementID + "-saved"); elMaterialDataSaved.innerText = "Saved!"; elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elMaterialDataSaved); elDiv.insertBefore(elStaticMaterialData, elMaterialData); elDiv.insertBefore(elMaterialDataEditor, elMaterialData); + elDiv.insertBefore(elMaterialDataEditorStatus, elMaterialData); // Special Property Callbacks let elParentMaterialNameString = getPropertyInputElement("materialNameToReplace"); From 2771e2862e15e54b6cfa7edf696ef0e18d2f58f7 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Nov 2018 19:55:34 +0100 Subject: [PATCH 31/42] add missing material data json error clear on delete --- scripts/system/html/js/entityProperties.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index bc93a1a9b7..ed03d62e70 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -2705,6 +2705,7 @@ function getMaterialEditorJSON() { function deleteJSONMaterialEditor() { if (materialEditor !== null) { + setJSONError('materialData', false); materialEditor.destroy(); materialEditor = null; } From 4f2289b347db6342006d41f98fdc89604f7525e1 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 6 Dec 2018 23:42:12 +0100 Subject: [PATCH 32/42] CR fixes --- scripts/system/html/js/entityProperties.js | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index ed03d62e70..6f8f2ef4bc 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1429,13 +1429,13 @@ const TEXTURE_ELEMENTS = { const JSON_EDITOR_ROW_DIV_INDEX = 2; -var elGroups = {}; -var properties = {}; -var colorPickers = {}; -var particlePropertyUpdates = {}; -var selectedEntityProperties; -var lastEntityID = null; -var createAppTooltip = new CreateAppTooltip(); +let elGroups = {}; +let properties = {}; +let colorPickers = {}; +let particlePropertyUpdates = {}; +let selectedEntityProperties; +let lastEntityID = null; +let createAppTooltip = new CreateAppTooltip(); let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL; function createElementFromHTML(htmlString) { @@ -1689,7 +1689,7 @@ function updateProperty(originalPropertyName, propertyValue, isParticleProperty) } } -var particleSyncDebounce = _.debounce(function () { +let particleSyncDebounce = _.debounce(function () { updateProperties(particlePropertyUpdates); particlePropertyUpdates = {}; }, DEBOUNCE_TIMEOUT); @@ -2361,7 +2361,7 @@ function saveUserData() { function setJSONError(property, isError) { $("#property-"+ property + "-editor").toggleClass('error', isError); - var $propertyUserDataEditorStatus = $("#property-"+ property + "-editorStatus"); + let $propertyUserDataEditorStatus = $("#property-"+ property + "-editorStatus"); $propertyUserDataEditorStatus.css('display', isError ? 'block' : 'none'); $propertyUserDataEditorStatus.text(isError ? 'Invalid JSON code - look for red X in your code' : ''); } @@ -2377,7 +2377,7 @@ function setUserDataFromEditor(noUpdate) { setJSONError('userData', errorFound); - if (json !== null) { + if (errorFound) { return; } @@ -2452,7 +2452,7 @@ function multiDataUpdater(groupName, updateKeyPair, userDataElement, defaults, r updateProperties(propertyUpdate, false); } -var editor = null; +let editor = null; function createJSONEditor() { let container = document.getElementById("property-userData-editor"); @@ -2545,7 +2545,7 @@ function deleteJSONEditor() { } } -var savedJSONTimer = null; +let savedJSONTimer = null; function saveJSONUserData(noUpdate) { setUserDataFromEditor(noUpdate); @@ -2599,7 +2599,7 @@ function setMaterialDataFromEditor(noUpdate) { setJSONError('materialData', errorFound); - if (json === null) { + if (errorFound) { return; } let text = materialEditor.getText(); @@ -2618,7 +2618,7 @@ function setMaterialDataFromEditor(noUpdate) { } } -var materialEditor = null; +let materialEditor = null; function createJSONMaterialEditor() { let container = document.getElementById("property-materialData-editor"); @@ -2711,7 +2711,7 @@ function deleteJSONMaterialEditor() { } } -var savedMaterialJSONTimer = null; +let savedMaterialJSONTimer = null; function saveJSONMaterialData(noUpdate) { setMaterialDataFromEditor(noUpdate); From 1a3708c49dca4479429f1ca98cca4f3ad4c601f9 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 6 Dec 2018 16:14:28 -0800 Subject: [PATCH 33/42] better drag drop fix --- scripts/system/html/js/utils.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/js/utils.js b/scripts/system/html/js/utils.js index fe96e8b79e..d61b4d1762 100644 --- a/scripts/system/html/js/utils.js +++ b/scripts/system/html/js/utils.js @@ -11,13 +11,17 @@ function disableDragDrop() { document.addEventListener("drop", function(event) { event.preventDefault(); - event.dataTransfer.effectAllowed = "none"; - event.dataTransfer.dropEffect = "none"; - }, false); + }); document.addEventListener("dragover", function(event) { - event.preventDefault(); event.dataTransfer.effectAllowed = "none"; event.dataTransfer.dropEffect = "none"; + event.preventDefault(); + }); + + document.addEventListener("dragenter", function(event) { + event.dataTransfer.effectAllowed = "none"; + event.dataTransfer.dropEffect = "none"; + event.preventDefault(); }, false); } From ca0133a2a64420731dba8972ced4c46e7668ac2b Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 6 Dec 2018 16:24:06 -0800 Subject: [PATCH 34/42] put the lean joint back in --- libraries/fbx/src/FBXSerializer.cpp | 6 ++++++ libraries/fbx/src/GLTFSerializer.cpp | 1 + libraries/hfm/src/hfm/HFM.h | 1 + 3 files changed, 8 insertions(+) diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index 1581204819..37108ba5d2 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -482,6 +482,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointEyeRightName = "EyeRight"; QString jointNeckName = "Neck"; QString jointRootName = "Hips"; + QString jointLeanName = "Spine"; QString jointHeadName = "Head"; QString jointLeftHandName = "LeftHand"; QString jointRightHandName = "RightHand"; @@ -489,6 +490,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointEyeRightID; QString jointNeckID; QString jointRootID; + QString jointLeanID; QString jointHeadID; QString jointLeftHandID; QString jointRightHandID; @@ -612,6 +614,9 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr } else if (name == jointRootName || (hfmModel.hfmToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.hfmToHifiJointNameMapping[jointRootName]))) { jointRootID = getID(object.properties); + } else if (name == jointLeanName || (hfmModel.hfmToHifiJointNameMapping.contains(jointLeanName) && (name == hfmModel.hfmToHifiJointNameMapping[jointLeanName]))) { + jointLeanID = getID(object.properties); + } else if ((name == jointHeadName) || (hfmModel.hfmToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.hfmToHifiJointNameMapping[jointHeadName]))) { jointHeadID = getID(object.properties); @@ -1449,6 +1454,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr hfmModel.rightEyeJointIndex = modelIDs.indexOf(jointEyeRightID); hfmModel.neckJointIndex = modelIDs.indexOf(jointNeckID); hfmModel.rootJointIndex = modelIDs.indexOf(jointRootID); + hfmModel.leanJointIndex = modelIDs.indexOf(jointLeanID); hfmModel.headJointIndex = modelIDs.indexOf(jointHeadID); hfmModel.leftHandJointIndex = modelIDs.indexOf(jointLeftHandID); hfmModel.rightHandJointIndex = modelIDs.indexOf(jointRightHandID); diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 5485f46905..28d377c605 100644 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1186,6 +1186,7 @@ void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) { qCDebug(modelformat) << " rightEyeJointIndex =" << hfmModel.rightEyeJointIndex; qCDebug(modelformat) << " neckJointIndex =" << hfmModel.neckJointIndex; qCDebug(modelformat) << " rootJointIndex =" << hfmModel.rootJointIndex; + qCDebug(modelformat) << " leanJointIndex =" << hfmModel.leanJointIndex; qCDebug(modelformat) << " headJointIndex =" << hfmModel.headJointIndex; qCDebug(modelformat) << " leftHandJointIndex" << hfmModel.leftHandJointIndex; qCDebug(modelformat) << " rightHandJointIndex" << hfmModel.rightHandJointIndex; diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 3cc12724d5..de58d864b3 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -274,6 +274,7 @@ public: int rightEyeJointIndex = -1; int neckJointIndex = -1; int rootJointIndex = -1; + int leanJointIndex = -1; int headJointIndex = -1; int leftHandJointIndex = -1; int rightHandJointIndex = -1; From f8ae0227c30f269a3fa0f5afcb603b8ecb6e761c Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 6 Dec 2018 20:16:03 -0800 Subject: [PATCH 35/42] added the lean joint back and fixed a name mapping reversal in fbxserializer.cpp --- libraries/fbx/src/FBXSerializer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index 37108ba5d2..67220342b8 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -1418,7 +1418,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr joint.bindTransformFoundInCluster = false; hfmModel.joints.append(joint); - hfmModel.jointIndices.insert(fbxModel.name, hfmModel.joints.size()); + hfmModel.jointIndices.insert(joint.name, hfmModel.joints.size()); QString rotationID = localRotations.value(modelID); AnimationCurve xRotCurve = animationCurves.value(xComponents.value(rotationID)); @@ -1843,7 +1843,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr glm::quat rotationOffset = itr.value(); int jointIndex = hfmModel.getJointIndex(jointName); if (hfmModel.hfmToHifiJointNameMapping.contains(jointName)) { - jointIndex = hfmModel.getJointIndex(hfmModel.hfmToHifiJointNameMapping[jointName]); + jointIndex = hfmModel.getJointIndex(jointName); } if (jointIndex != -1) { hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); From 92117d602c30146b88bcddc2b61a6ae17060c9ea Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 5 Dec 2018 11:20:18 -0800 Subject: [PATCH 36/42] remove cruft --- interface/src/Application_render.cpp | 240 ---------------------- interface/src/graphics/GraphicsEngine.cpp | 4 + 2 files changed, 4 insertions(+), 240 deletions(-) delete mode 100644 interface/src/Application_render.cpp diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp deleted file mode 100644 index ea672e3510..0000000000 --- a/interface/src/Application_render.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// -// Application_render.cpp -// interface/src -// -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Application.h" -#include - -#include -#include -#include -#include -#include "ui/Stats.h" -#include "Util.h" - -//void Application::paintGL() { -// // Some plugins process message events, allowing paintGL to be called reentrantly. -// -// _renderFrameCount++; -// // SG: Moved into the RenderEventHandler -// //_lastTimeRendered.start(); -// -// auto lastPaintBegin = usecTimestampNow(); -// PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); -// PerformanceTimer perfTimer("paintGL"); -// -// if (nullptr == _displayPlugin) { -// return; -// } -// -// DisplayPluginPointer displayPlugin; -// { -// PROFILE_RANGE(render, "/getActiveDisplayPlugin"); -// displayPlugin = getActiveDisplayPlugin(); -// } -// -// { -// PROFILE_RANGE(render, "/pluginBeginFrameRender"); -// // If a display plugin loses it's underlying support, it -// // needs to be able to signal us to not use it -// if (!displayPlugin->beginFrameRender(_renderFrameCount)) { -// QMetaObject::invokeMethod(this, "updateDisplayMode"); -// return; -// } -// } -// -// RenderArgs renderArgs; -// glm::mat4 HMDSensorPose; -// glm::mat4 eyeToWorld; -// glm::mat4 sensorToWorld; -// ViewFrustum viewFrustum; -// -// bool isStereo; -// glm::mat4 stereoEyeOffsets[2]; -// glm::mat4 stereoEyeProjections[2]; -// -// { -// QMutexLocker viewLocker(&_renderArgsMutex); -// renderArgs = _appRenderArgs._renderArgs; -// -// // don't render if there is no context. -// if (!_appRenderArgs._renderArgs._context) { -// return; -// } -// -// HMDSensorPose = _appRenderArgs._headPose; -// eyeToWorld = _appRenderArgs._eyeToWorld; -// sensorToWorld = _appRenderArgs._sensorToWorld; -// isStereo = _appRenderArgs._isStereo; -// for_each_eye([&](Eye eye) { -// stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; -// stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; -// }); -// viewFrustum = _appRenderArgs._renderArgs.getViewFrustum(); -// } -// -// { -// PROFILE_RANGE(render, "/gpuContextReset"); -// _graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); -// // Reset the gpu::Context Stages -// // Back to the default framebuffer; -// gpu::doInBatch("Application_render::gpuContextReset", _graphicsEngine.getGPUContext(), [&](gpu::Batch& batch) { -// batch.resetStages(); -// }); -// -// if (isStereo) { -// renderArgs._context->enableStereo(true); -// renderArgs._context->setStereoProjections(stereoEyeProjections); -// renderArgs._context->setStereoViews(stereoEyeOffsets); -// } -// } -// -// gpu::FramebufferPointer finalFramebuffer; -// QSize finalFramebufferSize; -// { -// PROFILE_RANGE(render, "/getOutputFramebuffer"); -// // Primary rendering pass -// auto framebufferCache = DependencyManager::get(); -// finalFramebufferSize = framebufferCache->getFrameBufferSize(); -// // Final framebuffer that will be handed to the display-plugin -// finalFramebuffer = framebufferCache->getFramebuffer(); -// } -// -// if (!_programsCompiled.load()) { -// gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { -// batch.setFramebuffer(finalFramebuffer); -// batch.enableSkybox(true); -// batch.enableStereo(isStereo); -// batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); -// _splashScreen->render(batch, viewFrustum); -// }); -// } else { -// { -// PROFILE_RANGE(render, "/renderOverlay"); -// PerformanceTimer perfTimer("renderOverlay"); -// // NOTE: There is no batch associated with this renderArgs -// // the ApplicationOverlay class assumes it's viewport is setup to be the device size -// renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize()); -// _applicationOverlay.renderOverlay(&renderArgs); -// } -// -// { -// PROFILE_RANGE(render, "/updateCompositor"); -// getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); -// } -// -// { -// PROFILE_RANGE(render, "/runRenderFrame"); -// renderArgs._hudOperator = displayPlugin->getHUDOperator(); -// renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); -// renderArgs._blitFramebuffer = finalFramebuffer; -// runRenderFrame(&renderArgs); -// } -// } -// -// auto frame = _graphicsEngine.getGPUContext()->endFrame(); -// frame->frameIndex = _renderFrameCount; -// frame->framebuffer = finalFramebuffer; -// frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { -// auto frameBufferCache = DependencyManager::get(); -// if (frameBufferCache) { -// frameBufferCache->releaseFramebuffer(framebuffer); -// } -// }; -// // deliver final scene rendering commands to the display plugin -// { -// PROFILE_RANGE(render, "/pluginOutput"); -// PerformanceTimer perfTimer("pluginOutput"); -// _renderLoopCounter.increment(); -// displayPlugin->submitFrame(frame); -// } -// -// // Reset the framebuffer and stereo state -// renderArgs._blitFramebuffer.reset(); -// renderArgs._context->enableStereo(false); -// -//#if !defined(DISABLE_QML) -// { -// auto stats = Stats::getInstance(); -// if (stats) { -// stats->setRenderDetails(renderArgs._details); -// } -// } -//#endif -// -// uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; -// _frameTimingsScriptingInterface.addValue(lastPaintDuration); -//} - -// WorldBox Render Data & rendering functions -// -//class WorldBoxRenderData { -//public: -// typedef render::Payload Payload; -// typedef Payload::DataPointer Pointer; -// -// int _val = 0; -// static render::ItemID _item; // unique WorldBoxRenderData -//}; -// -//render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID }; -// -//namespace render { -// template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); } -// template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } -// template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { -// if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) { -// PerformanceTimer perfTimer("worldBox"); -// -// auto& batch = *args->_batch; -// DependencyManager::get()->bindSimpleProgram(batch); -// renderWorldBox(args, batch); -// } -// } -//} -// -//void Application::runRenderFrame(RenderArgs* renderArgs) { -// PROFILE_RANGE(render, __FUNCTION__); -// PerformanceTimer perfTimer("display"); -// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()"); -// -// // The pending changes collecting the changes here -// render::Transaction transaction; -// -// if (DependencyManager::get()->shouldRenderEntities()) { -// // render models... -// PerformanceTimer perfTimer("entities"); -// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), -// "Application::runRenderFrame() ... entities..."); -// -// RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; -// -// renderArgs->_debugFlags = renderDebugFlags; -// } -// -// // Make sure the WorldBox is in the scene -// // For the record, this one RenderItem is the first one we created and added to the scene. -// // We could move that code elsewhere but you know... -// if (!render::Item::isValidID(WorldBoxRenderData::_item)) { -// auto worldBoxRenderData = std::make_shared(); -// auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData); -// -// WorldBoxRenderData::_item = _main3DScene->allocateID(); -// -// transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); -// _main3DScene->enqueueTransaction(transaction); -// } -// -// { -// PerformanceTimer perfTimer("EngineRun"); -// _renderEngine->getRenderContext()->args = renderArgs; -// _renderEngine->run(); -// } -//} - diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index b7a5e89d35..36bf3a1b97 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -56,6 +56,10 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { glwidget->makeCurrent(); _gpuContext = std::make_shared(); + _gpuContext->pushProgramsToSync(shader::allPrograms(), [this] { + _programsCompiled.store(true); + }, 1); + DependencyManager::get()->setGPUContext(_gpuContext); } From 8431b3b0c187db5f97566e98b960205c32316c9d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 7 Dec 2018 10:39:10 -0800 Subject: [PATCH 37/42] correct order of mixes --- libraries/gpu/src/gpu/Color.slh | 4 ++-- libraries/render-utils/src/simple_textured.slf | 2 +- libraries/render-utils/src/simple_textured_fade.slf | 4 ++-- libraries/render-utils/src/simple_textured_unlit.slf | 4 ++-- libraries/render-utils/src/simple_textured_unlit_fade.slf | 4 ++-- libraries/render-utils/src/simple_transparent_textured.slf | 2 +- .../render-utils/src/simple_transparent_textured_fade.slf | 2 +- .../render-utils/src/simple_transparent_textured_unlit.slf | 2 +- .../src/simple_transparent_textured_unlit_fade.slf | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libraries/gpu/src/gpu/Color.slh b/libraries/gpu/src/gpu/Color.slh index 16eb7487ed..65ddc0b01e 100644 --- a/libraries/gpu/src/gpu/Color.slh +++ b/libraries/gpu/src/gpu/Color.slh @@ -18,8 +18,8 @@ float color_scalar_sRGBToLinear(float value) { const float SRGB_ELBOW = 0.04045; - - return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4); + + return mix(pow((value + 0.055) / 1.055, 2.4), value / 12.92, float(value <= SRGB_ELBOW)); } vec3 color_sRGBToLinear(vec3 srgb) { diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 9494edb890..dbc49fcb5d 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -29,7 +29,7 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; packDeferredFragment( diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf index 5ca21a71ac..5a9eb0688e 100644 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -41,9 +41,9 @@ void main(void) { applyFade(fadeParams, _positionWS.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; - texel.a = abs(_color.a); + texel.a *= abs(_color.a); const float ALPHA_THRESHOLD = 0.999; if (texel.a < ALPHA_THRESHOLD) { diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf index 2d8f228f1c..475428f0ae 100644 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -29,9 +29,9 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; - texel.a = abs(_color.a); + texel.a *= abs(_color.a); const float ALPHA_THRESHOLD = 0.999; if (texel.a < ALPHA_THRESHOLD) { diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf index 442be14a8e..d0ba4c13fe 100644 --- a/libraries/render-utils/src/simple_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_textured_unlit_fade.slf @@ -41,9 +41,9 @@ void main(void) { applyFade(fadeParams, _positionWS.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; - texel.a = abs(_color.a); + texel.a *= abs(_color.a); const float ALPHA_THRESHOLD = 0.999; if (texel.a < ALPHA_THRESHOLD) { diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index 1a9d14e2fa..bd29ff2ec9 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -29,7 +29,7 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; texel.a *= abs(_color.a); diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index 75a88dc581..d401989f90 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -47,7 +47,7 @@ void main(void) { applyFade(fadeParams, _positionWS.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; texel.a *= abs(_color.a); diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit.slf b/libraries/render-utils/src/simple_transparent_textured_unlit.slf index 3f4abfc730..42a8270274 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit.slf @@ -28,7 +28,7 @@ layout(location=0) out vec4 _fragColor0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; texel.a *= abs(_color.a); diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf index e46426ec7a..afc0c94575 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf @@ -40,7 +40,7 @@ void main(void) { applyFade(fadeParams, _positionWS.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; texel.a *= abs(_color.a); From 818339823c64a65fd21a120a9c7da38a4d4da7d5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 6 Dec 2018 14:50:16 -0800 Subject: [PATCH 38/42] Add new number type in Create --- scripts/system/html/css/edit-style.css | 5 + scripts/system/html/js/entityProperties.js | 159 +++++++++++++-------- 2 files changed, 103 insertions(+), 61 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 13825119ce..5bfa5c0609 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1697,3 +1697,8 @@ input.number-slider { display: none; cursor: pointer; } + +input[type=number].hide-spinner::-webkit-inner-spin-button { + -webkit-appearance: none; + visibility: hidden; +} diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 84a1ab2a12..972c5f63be 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -75,7 +75,7 @@ const GROUPS = [ }, { label: "Parent Joint Index", - type: "number", + type: "number-draggable", propertyID: "parentJointIndex", }, { @@ -135,7 +135,7 @@ const GROUPS = [ }, { label: "Line Height", - type: "number", + type: "number-draggable", min: 0, step: 0.005, decimals: 4, @@ -183,7 +183,7 @@ const GROUPS = [ }, { label: "Light Intensity", - type: "number", + type: "number-draggable", min: 0, max: 10, step: 0.1, @@ -193,7 +193,7 @@ const GROUPS = [ }, { label: "Light Horizontal Angle", - type: "number", + type: "number-draggable", multiplier: DEGREES_TO_RADIANS, decimals: 2, unit: "deg", @@ -202,7 +202,7 @@ const GROUPS = [ }, { label: "Light Vertical Angle", - type: "number", + type: "number-draggable", multiplier: DEGREES_TO_RADIANS, decimals: 2, unit: "deg", @@ -241,7 +241,7 @@ const GROUPS = [ }, { label: "Ambient Intensity", - type: "number", + type: "number-draggable", min: 0, max: 10, step: 0.1, @@ -270,7 +270,7 @@ const GROUPS = [ }, { label: "Range", - type: "number", + type: "number-draggable", min: 5, max: 10000, step: 5, @@ -287,7 +287,7 @@ const GROUPS = [ }, { label: "Base", - type: "number", + type: "number-draggable", min: -1000, max: 1000, step: 10, @@ -298,7 +298,7 @@ const GROUPS = [ }, { label: "Ceiling", - type: "number", + type: "number-draggable", min: -1000, max: 5000, step: 10, @@ -315,7 +315,7 @@ const GROUPS = [ }, { label: "Background Blend", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -337,7 +337,7 @@ const GROUPS = [ }, { label: "Glare Angle", - type: "number", + type: "number-draggable", min: 0, max: 180, step: 1, @@ -353,7 +353,7 @@ const GROUPS = [ }, { label: "Bloom Intensity", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -363,7 +363,7 @@ const GROUPS = [ }, { label: "Bloom Threshold", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -373,7 +373,7 @@ const GROUPS = [ }, { label: "Bloom Size", - type: "number", + type: "number-draggable", min: 0, max: 2, step: 0.01, @@ -432,22 +432,22 @@ const GROUPS = [ }, { label: "Animation Frame", - type: "number", + type: "number-draggable", propertyID: "animation.currentFrame", }, { label: "First Frame", - type: "number", + type: "number-draggable", propertyID: "animation.firstFrame", }, { label: "Last Frame", - type: "number", + type: "number-draggable", propertyID: "animation.lastFrame", }, { label: "Animation FPS", - type: "number", + type: "number-draggable", propertyID: "animation.fps", }, { @@ -486,7 +486,7 @@ const GROUPS = [ }, { label: "Source Resolution", - type: "number", + type: "number-draggable", propertyID: "dpi", }, ] @@ -503,7 +503,7 @@ const GROUPS = [ }, { label: "Intensity", - type: "number", + type: "number-draggable", min: 0, step: 0.1, decimals: 1, @@ -511,7 +511,7 @@ const GROUPS = [ }, { label: "Fall-Off Radius", - type: "number", + type: "number-draggable", min: 0, step: 0.1, decimals: 1, @@ -525,14 +525,14 @@ const GROUPS = [ }, { label: "Spotlight Exponent", - type: "number", + type: "number-draggable", step: 0.01, decimals: 2, propertyID: "exponent", }, { label: "Spotlight Cut-Off", - type: "number", + type: "number-draggable", step: 0.01, decimals: 2, propertyID: "cutoff", @@ -563,7 +563,7 @@ const GROUPS = [ }, { label: "Submesh to Replace", - type: "number", + type: "number-draggable", min: 0, step: 1, propertyID: "submeshToReplace", @@ -577,7 +577,7 @@ const GROUPS = [ }, { label: "Priority", - type: "number", + type: "number-draggable", min: 0, propertyID: "priority", }, @@ -612,7 +612,7 @@ const GROUPS = [ }, { label: "Material Rotation", - type: "number", + type: "number-draggable", step: 0.1, decimals: 2, unit: "deg", @@ -636,7 +636,7 @@ const GROUPS = [ }, { label: "Lifespan", - type: "number", + type: "number-draggable", unit: "s", min: 0.01, max: 10, @@ -646,7 +646,7 @@ const GROUPS = [ }, { label: "Max Particles", - type: "number", + type: "number-draggable", min: 1, max: 10000, step: 1, @@ -667,7 +667,7 @@ const GROUPS = [ properties: [ { label: "Emit Rate", - type: "number", + type: "number-draggable", min: 1, max: 1000, step: 1, @@ -675,7 +675,7 @@ const GROUPS = [ }, { label: "Emit Speed", - type: "number", + type: "number-draggable", min: 0, max: 5, step: 0.01, @@ -684,7 +684,7 @@ const GROUPS = [ }, { label: "Speed Spread", - type: "number", + type: "number-draggable", min: 0, max: 5, step: 0.01, @@ -703,7 +703,7 @@ const GROUPS = [ }, { label: "Emit Radius Start", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -738,7 +738,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: 0, max: 4, step: 0.01, @@ -748,7 +748,7 @@ const GROUPS = [ }, { label: "Middle", - type: "number", + type: "number-draggable", min: 0, max: 4, step: 0.01, @@ -757,7 +757,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: 0, max: 4, step: 0.01, @@ -769,7 +769,7 @@ const GROUPS = [ }, { label: "Size Spread", - type: "number", + type: "number-draggable", min: 0, max: 4, step: 0.01, @@ -825,7 +825,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -835,7 +835,7 @@ const GROUPS = [ }, { label: "Middle", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -844,7 +844,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -856,7 +856,7 @@ const GROUPS = [ }, { label: "Alpha Spread", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -901,7 +901,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: -360, max: 360, step: 1, @@ -913,7 +913,7 @@ const GROUPS = [ }, { label: "Middle", - type: "number", + type: "number-draggable", min: -360, max: 360, step: 1, @@ -924,7 +924,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: -360, max: 360, step: 1, @@ -938,7 +938,7 @@ const GROUPS = [ }, { label: "Spin Spread", - type: "number", + type: "number-draggable", min: 0, max: 360, step: 1, @@ -965,7 +965,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: 0, max: 180, step: 1, @@ -976,7 +976,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: 0, max: 180, step: 1, @@ -993,7 +993,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: -180, max: 180, step: 1, @@ -1004,7 +1004,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: -180, max: 180, step: 1, @@ -1089,7 +1089,7 @@ const GROUPS = [ }, { label: "Scale", - type: "number", + type: "number-draggable", defaultValue: 100, unit: "%", buttons: [ { id: "rescale", label: "Rescale", className: "blue", onClick: rescaleDimensions }, @@ -1131,14 +1131,14 @@ const GROUPS = [ }, { label: "Clone Lifetime", - type: "number", + type: "number-draggable", unit: "s", propertyID: "cloneLifetime", showPropertyRule: { "cloneable": "true" }, }, { label: "Clone Limit", - type: "number", + type: "number-draggable", propertyID: "cloneLimit", showPropertyRule: { "cloneable": "true" }, }, @@ -1197,7 +1197,7 @@ const GROUPS = [ }, { label: "Lifetime", - type: "string", + type: "number", unit: "s", propertyID: "lifetime", }, @@ -1291,7 +1291,7 @@ const GROUPS = [ }, { label: "Linear Damping", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -1310,7 +1310,7 @@ const GROUPS = [ }, { label: "Angular Damping", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -1319,7 +1319,7 @@ const GROUPS = [ }, { label: "Bounciness", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -1328,7 +1328,7 @@ const GROUPS = [ }, { label: "Friction", - type: "number", + type: "number-draggable", min: 0, max: 10, step: 0.1, @@ -1337,7 +1337,7 @@ const GROUPS = [ }, { label: "Density", - type: "number", + type: "number-draggable", min: 100, max: 10000, step: 1, @@ -1454,12 +1454,13 @@ function getPropertyInputElement(propertyID) { let property = properties[propertyID]; switch (property.data.type) { case 'string': + case 'number': case 'bool': case 'dropdown': case 'textarea': case 'texture': return property.elInput; - case 'number': + case 'number-draggable': return property.elNumber.elInput; case 'vec3': case 'vec2': @@ -1529,6 +1530,7 @@ function resetProperties() { let propertyData = property.data; switch (propertyData.type) { + case 'number': case 'string': { property.elInput.value = ""; break; @@ -1537,7 +1539,7 @@ function resetProperties() { property.elInput.checked = false; break; } - case 'number': { + case 'number-draggable': { if (propertyData.defaultValue !== undefined) { property.elNumber.setValue(propertyData.defaultValue); } else { @@ -1873,7 +1875,33 @@ function createBoolProperty(property, elProperty) { return elInput; } -function createNumberProperty(property, elProperty) { +function createNumberProperty(property, elProperty) { + let elementID = property.elementID; + let propertyData = property.data; + + elProperty.className = "text"; + + let elInput = createElementFromHTML(` + + `) + + + elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); + + elProperty.appendChild(elInput); + + if (propertyData.buttons !== undefined) { + addButtons(elProperty, elementID, propertyData.buttons, false); + } + + return elInput; +} + +function createNumberSpinnerProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; @@ -2217,7 +2245,11 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI break; } case 'number': { - property.elNumber = createNumberProperty(property, elProperty); + property.elInput = createNumberProperty(property, elProperty); + break; + } + case 'number-draggable': { + property.elNumber = createNumberSpinnerProperty(property, elProperty); break; } case 'vec3': { @@ -3098,6 +3130,7 @@ function loaded() { let isPropertyNotNumber = false; switch (propertyData.type) { case 'number': + case 'number-draggable': isPropertyNotNumber = isNaN(propertyValue) || propertyValue === null; break; case 'vec3': @@ -3130,6 +3163,10 @@ function loaded() { break; } case 'number': { + property.elInput.value = propertyValue; + break; + } + case 'number-draggable': { let multiplier = propertyData.multiplier !== undefined ? propertyData.multiplier : 1; let value = propertyValue / multiplier; if (propertyData.round !== undefined) { From c9ab5c23eab77cbb92fb717cab9671fa45cdd35d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 6 Dec 2018 15:30:11 -0800 Subject: [PATCH 39/42] Add support for min/max/step/defaultValue on number field --- scripts/system/html/js/entityProperties.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 972c5f63be..cfead83851 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1533,6 +1533,11 @@ function resetProperties() { case 'number': case 'string': { property.elInput.value = ""; + if (propertyData.defaultValue !== undefined) { + property.elInput.setValue(propertyData.defaultValue); + } else { + property.elInput.setValue(""); + } break; } case 'bool': { @@ -1889,6 +1894,18 @@ function createNumberProperty(property, elProperty) { ${propertyData.readOnly ? 'readonly' : ''}> `) + if (propertyData.min !== undefined) { + elInput.setAttribute("min", propertyData.min); + } + if (propertyData.max !== undefined) { + elInput.setAttribute("max", propertyData.max); + } + if (propertyData.step !== undefined) { + elInput.setAttribute("step", propertyData.step); + } + if (propertyData.defaultValue !== undefined) { + elInput.value = propertyData.defaultValue; + } elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); From f42c31ca36c311432cafaaa679e8dc3ae330a01f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 6 Dec 2018 15:35:25 -0800 Subject: [PATCH 40/42] Update number property to reuse numberdraggable emit function --- scripts/system/html/js/entityProperties.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index cfead83851..1717f31832 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1532,11 +1532,10 @@ function resetProperties() { switch (propertyData.type) { case 'number': case 'string': { - property.elInput.value = ""; if (propertyData.defaultValue !== undefined) { - property.elInput.setValue(propertyData.defaultValue); + property.elInput.value = propertyData.defaultValue; } else { - property.elInput.setValue(""); + property.elInput.value = ""; } break; } @@ -1907,7 +1906,7 @@ function createNumberProperty(property, elProperty) { elInput.value = propertyData.defaultValue; } - elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); + elInput.addEventListener('change', createEmitNumberPropertyUpdateFunction(property)); elProperty.appendChild(elInput); @@ -1918,7 +1917,7 @@ function createNumberProperty(property, elProperty) { return elInput; } -function createNumberSpinnerProperty(property, elProperty) { +function createNumberDraggableProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; @@ -2266,7 +2265,7 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI break; } case 'number-draggable': { - property.elNumber = createNumberSpinnerProperty(property, elProperty); + property.elNumber = createNumberDraggableProperty(property, elProperty); break; } case 'vec3': { From bf844e047240cde91502e1e0e135d2e4bd1c45a3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 5 Dec 2018 16:07:45 -0800 Subject: [PATCH 41/42] Add hiding of certified properties in Create --- scripts/system/html/js/entityList.js | 8 ++++-- scripts/system/html/js/entityProperties.js | 33 ++++++++++++++++------ scripts/system/libraries/entityList.js | 3 +- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 9e6eb3311a..89b56c7f7b 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -23,6 +23,7 @@ const SCROLLBAR_WIDTH = 20; const RESIZER_WIDTH = 10; const DELTA_X_MOVE_COLUMNS_THRESHOLD = 2; const DELTA_X_COLUMN_SWAP_POSITION = 5; +const CERTIFIED_PLACEHOLDER = "** Certified **"; const COLUMNS = { type: { @@ -635,10 +636,11 @@ function loaded() { id: entity.id, name: entity.name, type: type, - url: filename, - fullUrl: entity.url, + url: entity.certificateID === "" ? filename : "" + CERTIFIED_PLACEHOLDER + "", + fullUrl: entity.certificateID === "" ? filename : CERTIFIED_PLACEHOLDER, locked: entity.locked, visible: entity.visible, + certificateID: entity.certificateID, verticesCount: displayIfNonZero(entity.verticesCount), texturesCount: displayIfNonZero(entity.texturesCount), texturesSize: decimalMegabytes(entity.texturesSize), @@ -876,7 +878,7 @@ function loaded() { if (column.data.glyph) { elCell.innerHTML = itemData[column.data.propertyID] ? column.data.columnHeader : null; } else { - elCell.innerText = itemData[column.data.propertyID]; + elCell.innerHTML = itemData[column.data.propertyID]; } elCell.style = "min-width:" + column.widthPx + "px;" + "max-width:" + column.widthPx + "px;"; elCell.className = createColumnClassName(column.columnID); diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 84a1ab2a12..c39761e311 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -390,7 +390,9 @@ const GROUPS = [ { label: "Model", type: "string", + placeholder: "URL", propertyID: "modelURL", + hideIfCertified: true, }, { label: "Collision Shape", @@ -404,11 +406,13 @@ const GROUPS = [ label: "Compound Shape", type: "string", propertyID: "compoundShapeURL", + hideIfCertified: true, }, { label: "Animation", type: "string", propertyID: "animation.url", + hideIfCertified: true, }, { label: "Play Automatically", @@ -460,6 +464,7 @@ const GROUPS = [ type: "textarea", propertyID: "originalTextures", readOnly: true, + hideIfCertified: true, }, ] }, @@ -1181,6 +1186,7 @@ const GROUPS = [ buttons: [ { id: "reload", label: "F", className: "glyph", onClick: reloadScripts } ], propertyID: "script", placeholder: "URL", + hideIfCertified: true, }, { label: "Server Script", @@ -1267,6 +1273,7 @@ const GROUPS = [ placeholder: "URL", propertyID: "collisionSoundURL", showPropertyRule: { "collisionless": "false" }, + hideIfCertified: true, }, { label: "Dynamic", @@ -3084,6 +3091,15 @@ function loaded() { showGroupsForType(selectedEntityProperties.type); + if (selectedEntityProperties.locked) { + disableProperties(); + getPropertyInputElement("locked").removeAttribute('disabled'); + } else { + enableProperties(); + disableSaveUserDataButton(); + disableSaveMaterialDataButton() + } + for (let propertyID in properties) { let property = properties[propertyID]; let propertyData = property.data; @@ -3094,6 +3110,14 @@ function loaded() { if (propertyValue === undefined && !isSubProperty) { continue; } + + if (propertyData.hideIfCertified) { + let shouldHide = selectedEntityProperties.certificateID !== ""; + if (shouldHide) { + propertyValue = "** Certified **"; + } + property.elInput.disabled = shouldHide; + } let isPropertyNotNumber = false; switch (propertyData.type) { @@ -3272,15 +3296,6 @@ function loaded() { hideMaterialDataSaved(); } - if (selectedEntityProperties.locked) { - disableProperties(); - getPropertyInputElement("locked").removeAttribute('disabled'); - } else { - enableProperties(); - disableSaveUserDataButton(); - disableSaveMaterialDataButton() - } - let activeElement = document.activeElement; if (doSelectElement && typeof activeElement.select !== "undefined") { activeElement.select(); diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index eeb16fd60d..f27ab6caf2 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -164,7 +164,7 @@ EntityListTool = function(shouldUseEditTabletApp) { var cameraPosition = Camera.position; PROFILE("getMultipleProperties", function () { var multipleProperties = Entities.getMultipleEntityProperties(ids, ['name', 'type', 'locked', - 'visible', 'renderInfo', 'modelURL', 'materialURL', 'script']); + 'visible', 'renderInfo', 'modelURL', 'materialURL', 'script', 'certificateID']); for (var i = 0; i < multipleProperties.length; i++) { var properties = multipleProperties[i]; @@ -182,6 +182,7 @@ EntityListTool = function(shouldUseEditTabletApp) { url: url, locked: properties.locked, visible: properties.visible, + certificateID: properties.certificateID, verticesCount: (properties.renderInfo !== undefined ? valueIfDefined(properties.renderInfo.verticesCount) : ""), texturesCount: (properties.renderInfo !== undefined ? From 51fd742722e9919ae8b0f2d11b899577351557d5 Mon Sep 17 00:00:00 2001 From: birarda Date: Fri, 7 Dec 2018 11:17:44 -0800 Subject: [PATCH 42/42] fix for initial send of non-instanced trait --- libraries/avatars/src/ClientTraitsHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index cbc8e93745..3e24c1f9ad 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -104,7 +104,7 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() { // we double check that it is a simple iterator here auto traitType = static_cast(std::distance(traitStatusesCopy.simpleCBegin(), simpleIt)); - if (_shouldPerformInitialSend || *simpleIt == Updated) { + if (initialSend || *simpleIt == Updated) { if (traitType == AvatarTraits::SkeletonModelURL) { _owningAvatar->packTrait(traitType, *traitsPacketList);