diff --git a/interface/src/scripting/SelectionScriptingInterface.cpp b/interface/src/scripting/SelectionScriptingInterface.cpp index 4200a8e0dd..ba500ae010 100644 --- a/interface/src/scripting/SelectionScriptingInterface.cpp +++ b/interface/src/scripting/SelectionScriptingInterface.cpp @@ -72,28 +72,29 @@ bool SelectionScriptingInterface::removeFromSelectedItemsList(const QString& lis } bool SelectionScriptingInterface::clearSelectedItemsList(const QString& listName) { - // QWriteLocker lock(&_selectionListsLock); - _selectedItemsListMap.insert(listName, GameplayObjects()); + { + QWriteLocker lock(&_selectionListsLock); + _selectedItemsListMap.insert(listName, GameplayObjects()); + } onSelectedItemsListChanged(listName); return true; } bool SelectionScriptingInterface::enableListHighlight(const QString& listName, const QVariantMap& highlightStyleValues) { - // QWriteLocker lock(&_selectionListsLock); + QWriteLocker lock(&_highlightStylesLock); - auto highlightStyle = _highlightedListMap.find(listName); - if (highlightStyle == _highlightedListMap.end()) { - highlightStyle = _highlightedListMap.insert(listName, SelectionHighlightStyle()); + auto highlightStyle = _highlightStyleMap.find(listName); + if (highlightStyle == _highlightStyleMap.end()) { + highlightStyle = _highlightStyleMap.insert(listName, SelectionHighlightStyle()); } if (!(*highlightStyle).isBoundToList()) { - auto currentList = _selectedItemsListMap.find(listName); + /* auto currentList = _selectedItemsListMap.find(listName); if (currentList == _selectedItemsListMap.end()) { _selectedItemsListMap.insert(listName, GameplayObjects()); - } + }*/ setupHandler(listName); - (*highlightStyle).setBoundToList(true); } @@ -113,33 +114,32 @@ bool SelectionScriptingInterface::enableListHighlight(const QString& listName, c } bool SelectionScriptingInterface::disableListHighlight(const QString& listName) { - // QWriteLocker lock(&_selectionListsLock); - auto highlightStyle = _highlightedListMap.find(listName); - if (highlightStyle != _highlightedListMap.end()) { - // if ((*highlightStyle).isBoundToList()) { - _highlightedListMap.erase(highlightStyle); + QWriteLocker lock(&_highlightStylesLock); + auto highlightStyle = _highlightStyleMap.find(listName); + if (highlightStyle != _highlightStyleMap.end()) { + if ((*highlightStyle).isBoundToList()) { + } - auto mainScene = qApp->getMain3DScene(); - if (mainScene) { - render::Transaction transaction; - transaction.removeHighlightFromSelection(listName.toStdString()); - mainScene->enqueueTransaction(transaction); - } - else { - qWarning() << "SelectionToSceneHandler::highlightStyleChanged(), Unexpected null scene, possibly during application shutdown"; - } - // emit highlightStyleRemoved(listName); + _highlightStyleMap.erase(highlightStyle); - // } + auto mainScene = qApp->getMain3DScene(); + if (mainScene) { + render::Transaction transaction; + transaction.removeHighlightFromSelection(listName.toStdString()); + mainScene->enqueueTransaction(transaction); + } + else { + qWarning() << "SelectionToSceneHandler::highlightStyleChanged(), Unexpected null scene, possibly during application shutdown"; + } } return true; } QVariantMap SelectionScriptingInterface::getListHighlightStyle(const QString& listName) const { - // QReadLocker lock(&_selectionListsLock); - auto highlightStyle = _highlightedListMap.find(listName); - if (highlightStyle == _highlightedListMap.end()) { + QReadLocker lock(&_highlightStylesLock); + auto highlightStyle = _highlightStyleMap.find(listName); + if (highlightStyle == _highlightStyleMap.end()) { return QVariantMap(); } else { return (*highlightStyle).toVariantMap(); @@ -147,9 +147,9 @@ QVariantMap SelectionScriptingInterface::getListHighlightStyle(const QString& li } render::HighlightStyle SelectionScriptingInterface::getHighlightStyle(const QString& listName) const { - // QReadLocker lock(&_selectionListsLock); - auto highlightStyle = _highlightedListMap.find(listName); - if (highlightStyle == _highlightedListMap.end()) { + QReadLocker lock(&_highlightStylesLock); + auto highlightStyle = _highlightStyleMap.find(listName); + if (highlightStyle == _highlightStyleMap.end()) { return render::HighlightStyle(); } else { return (*highlightStyle).getStyle(); @@ -157,25 +157,30 @@ render::HighlightStyle SelectionScriptingInterface::getHighlightStyle(const QStr } template bool SelectionScriptingInterface::addToGameplayObjects(const QString& listName, T idToAdd) { - // QWriteLocker lock(&_selectionListsLock); - - GameplayObjects currentList = _selectedItemsListMap.value(listName); - currentList.addToGameplayObjects(idToAdd); - _selectedItemsListMap.insert(listName, currentList); - + { + QWriteLocker lock(&_selectionListsLock); + GameplayObjects currentList = _selectedItemsListMap.value(listName); + currentList.addToGameplayObjects(idToAdd); + _selectedItemsListMap.insert(listName, currentList); + } onSelectedItemsListChanged(listName); return true; } template bool SelectionScriptingInterface::removeFromGameplayObjects(const QString& listName, T idToRemove) { - // QWriteLocker lock(&_selectionListsLock); - GameplayObjects currentList = _selectedItemsListMap.value(listName); - if (currentList.getContainsData()) { - currentList.removeFromGameplayObjects(idToRemove); - _selectedItemsListMap.insert(listName, currentList); - + bool listExist = false; + { + QWriteLocker lock(&_selectionListsLock); + auto currentList = _selectedItemsListMap.find(listName); + if (currentList != _selectedItemsListMap.end()) { + listExist = true; + (*currentList).removeFromGameplayObjects(idToRemove); + } + } + if (listExist) { onSelectedItemsListChanged(listName); return true; - } else { + } + else { return false; } } @@ -184,12 +189,12 @@ template bool SelectionScriptingInterface::removeFromGameplayObjects(c // GameplayObjects SelectionScriptingInterface::getList(const QString& listName) { - // QReadLocker lock(&_selectionListsLock); + QReadLocker lock(&_selectionListsLock); return _selectedItemsListMap.value(listName); } void SelectionScriptingInterface::printList(const QString& listName) { - // QReadLocker lock(&_selectionListsLock); + QReadLocker lock(&_selectionListsLock); auto currentList = _selectedItemsListMap.find(listName); if (currentList != _selectedItemsListMap.end()) { if ((*currentList).getContainsData()) { @@ -222,8 +227,12 @@ void SelectionScriptingInterface::printList(const QString& listName) { } bool SelectionScriptingInterface::removeListFromMap(const QString& listName) { - // QWriteLocker lock(&_selectionListsLock); - if (_selectedItemsListMap.remove(listName)) { + bool removed = false; + { + QWriteLocker lock(&_selectionListsLock); + bool removed = _selectedItemsListMap.remove(listName); + } + if (removed) { onSelectedItemsListChanged(listName); return true; } else { @@ -232,24 +241,25 @@ bool SelectionScriptingInterface::removeListFromMap(const QString& listName) { } void SelectionScriptingInterface::setupHandler(const QString& selectionName) { - // QWriteLocker lock(&_selectionListsLock); + QWriteLocker lock(&_selectionHandlersLock); auto handler = _handlerMap.find(selectionName); if (handler == _handlerMap.end()) { handler = _handlerMap.insert(selectionName, new SelectionToSceneHandler()); } - (*handler)->initialize(selectionName); - // connect(this, &SelectionScriptingInterface::selectedItemsListChanged, handler.value(), &SelectionToSceneHandler::selectedItemsListChanged); - } void SelectionScriptingInterface::onSelectedItemsListChanged(const QString& listName) { - // QWriteLocker lock(&_selectionListsLock); - auto handler = _handlerMap.find(listName); - if (handler != _handlerMap.end()) { - (*handler)->updateSceneFromSelectedList(); + { + QWriteLocker lock(&_selectionHandlersLock); + auto handler = _handlerMap.find(listName); + if (handler != _handlerMap.end()) { + (*handler)->updateSceneFromSelectedList(); + } } + + emit selectedItemsListChanged(listName); } @@ -312,66 +322,65 @@ void SelectionToSceneHandler::updateSceneFromSelectedList() { qWarning() << "SelectionToSceneHandler::updateRendererSelectedList(), Unexpected null scene, possibly during application shutdown"; } } -/* -void SelectionToSceneHandler::highlightStyleChanged(const QString& listName) { - if (listName == _listName) { - auto mainScene = qApp->getMain3DScene(); - if (mainScene) { - auto thisStyle = DependencyManager::get()->getHighlightStyle(listName); - render::Transaction transaction; - transaction.resetSelectionHighlight(listName.toStdString(), thisStyle); - mainScene->enqueueTransaction(transaction); - } - else { - qWarning() << "SelectionToSceneHandler::highlightStyleChanged(), Unexpected null scene, possibly during application shutdown"; - } - } -} -void SelectionToSceneHandler::highlightStyleRemoved(const QString& listName) { - if (listName == _listName) { - auto mainScene = qApp->getMain3DScene(); - if (mainScene) { - render::Transaction transaction; - transaction.removeHighlightFromSelection(listName.toStdString()); - mainScene->enqueueTransaction(transaction); - } - else { - qWarning() << "SelectionToSceneHandler::highlightStyleRemoved(), Unexpected null scene, possibly during application shutdown"; - } - } -} -*/ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) { - auto outlineColor = properties["outlineColor"]; - if (outlineColor.isValid()) { + auto colorVariant = properties["outlineUnoccludedColor"]; + if (colorVariant.isValid()) { bool isValid; - auto color = xColorFromVariant(properties["outlineColor"], isValid); + auto color = xColorFromVariant(colorVariant, isValid); if (isValid) { - _style.color = toGlm(color); + _style._outlineUnoccluded.color = toGlm(color); } } + colorVariant = properties["outlineOccludedColor"]; + if (colorVariant.isValid()) { + bool isValid; + auto color = xColorFromVariant(colorVariant, isValid); + if (isValid) { + _style._outlineOccluded.color = toGlm(color); + } + } + colorVariant = properties["fillUnoccludedColor"]; + if (colorVariant.isValid()) { + bool isValid; + auto color = xColorFromVariant(colorVariant, isValid); + if (isValid) { + _style._fillUnoccluded.color = toGlm(color); + } + } + colorVariant = properties["fillOccludedColor"]; + if (colorVariant.isValid()) { + bool isValid; + auto color = xColorFromVariant(colorVariant, isValid); + if (isValid) { + _style._fillOccluded.color = toGlm(color); + } + } + + auto intensityVariant = properties["outlineUnoccludedIntensity"]; + if (intensityVariant.isValid()) { + _style._outlineUnoccluded.alpha = intensityVariant.toFloat(); + } + intensityVariant = properties["outlineOccludedIntensity"]; + if (intensityVariant.isValid()) { + _style._outlineOccluded.alpha = intensityVariant.toFloat(); + } + intensityVariant = properties["fillUnoccludedIntensity"]; + if (intensityVariant.isValid()) { + _style._fillUnoccluded.alpha = intensityVariant.toFloat(); + } + intensityVariant = properties["fillOccludedIntensity"]; + if (intensityVariant.isValid()) { + _style._fillOccluded.alpha = intensityVariant.toFloat(); + } + auto outlineWidth = properties["outlineWidth"]; if (outlineWidth.isValid()) { - _style.outlineWidth = outlineWidth.toFloat(); + _style._outlineWidth = outlineWidth.toFloat(); } auto isOutlineSmooth = properties["isOutlineSmooth"]; if (isOutlineSmooth.isValid()) { - _style.isOutlineSmooth = isOutlineSmooth.toBool(); - } - - auto outlineIntensity = properties["outlineIntensity"]; - if (outlineIntensity.isValid()) { - _style.outlineIntensity = outlineIntensity.toFloat(); - } - - auto unoccludedFillOpacity = properties["unoccludedFillOpacity"]; - if (unoccludedFillOpacity.isValid()) { - _style.unoccludedFillOpacity = unoccludedFillOpacity.toFloat(); - } - auto occludedFillOpacity = properties["occludedFillOpacity"]; - if (occludedFillOpacity.isValid()) { - _style.occludedFillOpacity = occludedFillOpacity.toFloat(); + _style._isOutlineSmooth = isOutlineSmooth.toBool(); } return true; @@ -380,12 +389,18 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) { QVariantMap SelectionHighlightStyle::toVariantMap() const { QVariantMap properties; - properties["outlineColor"] = xColorToVariant(xColorFromGlm(_style.color)); - properties["outlineWidth"] = _style.outlineWidth; - properties["isOutlineSmooth"] = _style.isOutlineSmooth; - properties["outlineIntensity"] = _style.outlineIntensity; - properties["unoccludedFillOpacity"] = _style.unoccludedFillOpacity; - properties["occludedFillOpacity"] = _style.occludedFillOpacity; + properties["outlineUnoccludedColor"] = xColorToVariant(xColorFromGlm(_style._outlineUnoccluded.color)); + properties["outlineOccludedColor"] = xColorToVariant(xColorFromGlm(_style._outlineOccluded.color)); + properties["fillUnoccludedColor"] = xColorToVariant(xColorFromGlm(_style._fillUnoccluded.color)); + properties["fillOccludedColor"] = xColorToVariant(xColorFromGlm(_style._fillOccluded.color)); + + properties["outlineUnoccludedIntensity"] = _style._outlineUnoccluded.alpha; + properties["outlineOccludedIntensity"] = _style._outlineOccluded.alpha; + properties["fillUnoccludedIntensity"] = _style._fillUnoccluded.alpha; + properties["fillOccludedIntensity"] = _style._fillOccluded.alpha; + + properties["outlineWidth"] = _style._outlineWidth; + properties["isOutlineSmooth"] = _style._isOutlineSmooth; return properties; } \ No newline at end of file diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index d22df73218..6abf07537e 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -147,9 +147,12 @@ private: mutable QReadWriteLock _selectionListsLock; QMap _selectedItemsListMap; - QMap _highlightedListMap; + mutable QReadWriteLock _selectionHandlersLock; QMap _handlerMap; + mutable QReadWriteLock _highlightStylesLock; + QMap _highlightStyleMap; + template bool addToGameplayObjects(const QString& listName, T idToAdd); template bool removeFromGameplayObjects(const QString& listName, T idToRemove); diff --git a/libraries/render-utils/src/Highlight.slh b/libraries/render-utils/src/Highlight.slh index e6ebb25074..207276014c 100644 --- a/libraries/render-utils/src/Highlight.slh +++ b/libraries/render-utils/src/Highlight.slh @@ -36,8 +36,6 @@ void main(void) { // the blur will have a different width between the left / right sides and top / bottom // sides of the silhouette float highlightedDepth = texture(highlightedDepthMap, varTexCoord0).x; - float intensity = 0.0; - float isOccluded = 0.0; if (highlightedDepth < FAR_Z) { // We're not on the far plane so we are on the highlighted object, thus no outline to do! @@ -48,7 +46,11 @@ void main(void) { highlightedDepth = -evalZeyeFromZdb(highlightedDepth); sceneDepth = -evalZeyeFromZdb(sceneDepth); - intensity = sceneDepth < (highlightedDepth-LINEAR_DEPTH_BIAS) ? params._occludedFillOpacity : params._unoccludedFillOpacity; + if (sceneDepth < (highlightedDepth-LINEAR_DEPTH_BIAS)) { + outFragColor = vec4(params._fillOccludedColor, params._fillOccludedAlpha); + } else { + outFragColor = vec4(params._fillUnoccludedColor, params._fillUnoccludedAlpha); + } <@else@> discard; <@endif@> @@ -62,8 +64,9 @@ void main(void) { int x; int y; - float outlinedDepth = 0; - float sumOutlineDepth = 0; + float intensity = 0.0; + float outlinedDepth = 0.0; + float sumOutlineDepth = 0.0; for (y=0 ; y diff --git a/libraries/render-utils/src/HighlightEffect.cpp b/libraries/render-utils/src/HighlightEffect.cpp index 79ae96c07c..d1fcab67b6 100644 --- a/libraries/render-utils/src/HighlightEffect.cpp +++ b/libraries/render-utils/src/HighlightEffect.cpp @@ -88,7 +88,7 @@ HighlightSharedParameters::HighlightSharedParameters() { } float HighlightSharedParameters::getBlurPixelWidth(const render::HighlightStyle& style, int frameBufferHeight) { - return ceilf(style.outlineWidth * frameBufferHeight / 400.0f); + return ceilf(style._outlineWidth * frameBufferHeight / 400.0f); } PrepareDrawHighlight::PrepareDrawHighlight() { @@ -267,14 +267,19 @@ void DrawHighlight::run(const render::RenderContextPointer& renderContext, const { auto& shaderParameters = _configuration.edit(); - shaderParameters._color = highlight._style.color; - shaderParameters._intensity = highlight._style.outlineIntensity * (highlight._style.isOutlineSmooth ? 2.0f : 1.0f); - shaderParameters._unoccludedFillOpacity = highlight._style.unoccludedFillOpacity; - shaderParameters._occludedFillOpacity = highlight._style.occludedFillOpacity; - shaderParameters._threshold = highlight._style.isOutlineSmooth ? 1.0f : 1e-3f; - shaderParameters._blurKernelSize = std::min(7, std::max(2, (int)floorf(highlight._style.outlineWidth * 3 + 0.5f))); + shaderParameters._outlineUnoccludedColor = highlight._style._outlineUnoccluded.color; + shaderParameters._outlineUnoccludedAlpha = highlight._style._outlineUnoccluded.alpha * (highlight._style._isOutlineSmooth ? 2.0f : 1.0f); + shaderParameters._outlineOccludedColor = highlight._style._outlineOccluded.color; + shaderParameters._outlineOccludedAlpha = highlight._style._outlineOccluded.alpha * (highlight._style._isOutlineSmooth ? 2.0f : 1.0f); + shaderParameters._fillUnoccludedColor = highlight._style._fillUnoccluded.color; + shaderParameters._fillUnoccludedAlpha = highlight._style._fillUnoccluded.alpha; + shaderParameters._fillOccludedColor = highlight._style._fillOccluded.color; + shaderParameters._fillOccludedAlpha = highlight._style._fillOccluded.alpha; + + shaderParameters._threshold = highlight._style._isOutlineSmooth ? 1.0f : 1e-3f; + shaderParameters._blurKernelSize = std::min(7, std::max(2, (int)floorf(highlight._style._outlineWidth * 3 + 0.5f))); // Size is in normalized screen height. We decide that for highlight width = 1, this is equal to 1/400. - auto size = highlight._style.outlineWidth / 400.0f; + auto size = highlight._style._outlineWidth / 400.0f; shaderParameters._size.x = (size * framebufferSize.y) / framebufferSize.x; shaderParameters._size.y = size; } diff --git a/libraries/render-utils/src/Highlight_shared.slh b/libraries/render-utils/src/Highlight_shared.slh index 5efbde4d52..edc51e4ecb 100644 --- a/libraries/render-utils/src/Highlight_shared.slh +++ b/libraries/render-utils/src/Highlight_shared.slh @@ -11,17 +11,18 @@ struct HighlightParameters { - TVEC3 _color; - float _intensity; + TVEC3 _outlineUnoccludedColor; + float _outlineUnoccludedAlpha; + TVEC3 _outlineOccludedColor; + float _outlineOccludedAlpha; + TVEC3 _fillUnoccludedColor; + float _fillUnoccludedAlpha; + TVEC3 _fillOccludedColor; + float _fillOccludedAlpha; - TVEC2 _size; - float _unoccludedFillOpacity; - float _occludedFillOpacity; - - float _threshold; int _blurKernelSize; - float padding2; - float padding3; + float _threshold; + TVEC2 _size; }; // <@if 1@> diff --git a/libraries/render/src/render/HighlightStage.cpp b/libraries/render/src/render/HighlightStage.cpp index ade3844321..c9f097b387 100644 --- a/libraries/render/src/render/HighlightStage.cpp +++ b/libraries/render/src/render/HighlightStage.cpp @@ -61,42 +61,42 @@ void HighlightStageConfig::setSelectionName(const QString& name) { } void HighlightStageConfig::setOutlineSmooth(bool isSmooth) { - editStyle().isOutlineSmooth = isSmooth; + editStyle()._isOutlineSmooth = isSmooth; emit dirty(); } void HighlightStageConfig::setColorRed(float value) { - editStyle().color.r = value; + editStyle()._outlineUnoccluded.color.r = value; emit dirty(); } void HighlightStageConfig::setColorGreen(float value) { - editStyle().color.g = value; + editStyle()._outlineUnoccluded.color.g = value; emit dirty(); } void HighlightStageConfig::setColorBlue(float value) { - editStyle().color.b = value; + editStyle()._outlineUnoccluded.color.b = value; emit dirty(); } void HighlightStageConfig::setOutlineWidth(float value) { - editStyle().outlineWidth = value; + editStyle()._outlineWidth = value; emit dirty(); } void HighlightStageConfig::setOutlineIntensity(float value) { - editStyle().outlineIntensity = value; + editStyle()._outlineUnoccluded.alpha = value; emit dirty(); } void HighlightStageConfig::setUnoccludedFillOpacity(float value) { - editStyle().unoccludedFillOpacity = value; + editStyle()._fillUnoccluded.alpha = value; emit dirty(); } void HighlightStageConfig::setOccludedFillOpacity(float value) { - editStyle().occludedFillOpacity = value; + editStyle()._fillOccluded.alpha = value; emit dirty(); } diff --git a/libraries/render/src/render/HighlightStage.h b/libraries/render/src/render/HighlightStage.h index 94c6e3ca69..5e6574840f 100644 --- a/libraries/render/src/render/HighlightStage.h +++ b/libraries/render/src/render/HighlightStage.h @@ -83,28 +83,28 @@ namespace render { QString getSelectionName() const { return QString(_selectionName.c_str()); } void setSelectionName(const QString& name); - bool isOutlineSmooth() const { return getStyle().isOutlineSmooth; } + bool isOutlineSmooth() const { return getStyle()._isOutlineSmooth; } void setOutlineSmooth(bool isSmooth); - float getColorRed() const { return getStyle().color.r; } + float getColorRed() const { return getStyle()._outlineUnoccluded.color.r; } void setColorRed(float value); - float getColorGreen() const { return getStyle().color.g; } + float getColorGreen() const { return getStyle()._outlineUnoccluded.color.g; } void setColorGreen(float value); - float getColorBlue() const { return getStyle().color.b; } + float getColorBlue() const { return getStyle()._outlineUnoccluded.color.b; } void setColorBlue(float value); - float getOutlineWidth() const { return getStyle().outlineWidth; } + float getOutlineWidth() const { return getStyle()._outlineWidth; } void setOutlineWidth(float value); - float getOutlineIntensity() const { return getStyle().outlineIntensity; } + float getOutlineIntensity() const { return getStyle()._outlineUnoccluded.alpha; } void setOutlineIntensity(float value); - float getUnoccludedFillOpacity() const { return getStyle().unoccludedFillOpacity; } + float getUnoccludedFillOpacity() const { return getStyle()._fillUnoccluded.alpha; } void setUnoccludedFillOpacity(float value); - float getOccludedFillOpacity() const { return getStyle().occludedFillOpacity; } + float getOccludedFillOpacity() const { return getStyle()._fillOccluded.alpha; } void setOccludedFillOpacity(float value); std::string _selectionName{ "contextOverlayHighlightList" }; diff --git a/libraries/render/src/render/HighlightStyle.h b/libraries/render/src/render/HighlightStyle.h index 6e7373c78b..1243f5aa60 100644 --- a/libraries/render/src/render/HighlightStyle.h +++ b/libraries/render/src/render/HighlightStyle.h @@ -20,17 +20,22 @@ namespace render { // This holds the configuration for a particular outline style class HighlightStyle { public: + struct RGBA { + glm::vec3 color{ 1.f, 0.7f, 0.2f }; + float alpha{ 0.9f }; + }; + + RGBA _outlineUnoccluded{ { 1.f, 0.7f, 0.2f }, 0.9f }; + RGBA _outlineOccluded{ { 0.2f, 0.7f, 1.0f }, 0.9f }; + RGBA _fillUnoccluded{ { 1.f, 0.2f, 0.7f }, 0.0f }; + RGBA _fillOccluded{ { 0.7f, 1.f, 0.2f }, 0.0f }; + + float _outlineWidth{ 2.0f }; + bool _isOutlineSmooth{ false }; bool isFilled() const { - return unoccludedFillOpacity > 5e-3f || occludedFillOpacity > 5e-3f; + return _fillUnoccluded.alpha > 5e-3f || _fillOccluded.alpha > 5e-3f; } - - glm::vec3 color{ 1.f, 0.7f, 0.2f }; - float outlineWidth{ 2.0f }; - float outlineIntensity{ 0.9f }; - float unoccludedFillOpacity{ 0.0f }; - float occludedFillOpacity{ 0.0f }; - bool isOutlineSmooth{ false }; }; } diff --git a/scripts/developer/utilities/render/debugHighlight.js b/scripts/developer/utilities/render/debugHighlight.js index 5175761978..c647c601b9 100644 --- a/scripts/developer/utilities/render/debugHighlight.js +++ b/scripts/developer/utilities/render/debugHighlight.js @@ -9,6 +9,111 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +"use strict"; + +// +// Luci.js +// tablet-engine app +// +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + var TABLET_BUTTON_NAME = "Highlight"; + var QMLAPP_URL = Script.resolvePath("./highlight.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); + + + var onLuciScreen = false; + + function onClicked() { + if (onLuciScreen) { + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource(QMLAPP_URL); + } + } + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL, + sortOrder: 1 + }); + + var hasEventBridge = false; + + function wireEventBridge(on) { + if (!tablet) { + print("Warning in wireEventBridge(): 'tablet' undefined!"); + return; + } + if (on) { + if (!hasEventBridge) { + tablet.fromQml.connect(fromQml); + hasEventBridge = true; + } + } else { + if (hasEventBridge) { + tablet.fromQml.disconnect(fromQml); + hasEventBridge = false; + } + } + } + + function onScreenChanged(type, url) { + if (url === QMLAPP_URL) { + onLuciScreen = true; + } else { + onLuciScreen = false; + } + + button.editProperties({isActive: onLuciScreen}); + wireEventBridge(onLuciScreen); + } + + function fromQml(message) { + } + + button.clicked.connect(onClicked); + tablet.screenChanged.connect(onScreenChanged); + + var moveDebugCursor = false; + Controller.mousePressEvent.connect(function (e) { + if (e.isMiddleButton) { + moveDebugCursor = true; + setDebugCursor(e.x, e.y); + } + }); + Controller.mouseReleaseEvent.connect(function() { moveDebugCursor = false; }); + Controller.mouseMoveEvent.connect(function (e) { if (moveDebugCursor) setDebugCursor(e.x, e.y); }); + + + Script.scriptEnding.connect(function () { + if (onLuciScreen) { + tablet.gotoHomeScreen(); + } + button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); + tablet.removeButton(button); + }); + + function setDebugCursor(x, y) { + nx = (x / Window.innerWidth); + ny = 1.0 - ((y) / (Window.innerHeight - 32)); + + Render.getConfig("RenderMainView").getConfig("Antialiasing").debugCursorTexcoord = { x: nx, y: ny }; + } + +}()); + + + // Set up the qml ui var qml = Script.resolvePath('highlight.qml'); var window = new OverlayWindow({ diff --git a/scripts/developer/utilities/render/debugHighlight2.js b/scripts/developer/utilities/render/debugHighlight2.js new file mode 100644 index 0000000000..387d5bfe4a --- /dev/null +++ b/scripts/developer/utilities/render/debugHighlight2.js @@ -0,0 +1,251 @@ +// +// debugHighlight.js +// developer/utilities/render +// +// Olivier Prat, created on 08/08/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +"use strict"; + +// +// Luci.js +// tablet-engine app +// +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + var TABLET_BUTTON_NAME = "Highlight"; + var QMLAPP_URL = Script.resolvePath("./highlight2.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); + + + var onLuciScreen = false; + + function onClicked() { + if (onLuciScreen) { + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource(QMLAPP_URL); + } + } + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL, + sortOrder: 1 + }); + + var hasEventBridge = false; + + function wireEventBridge(on) { + if (!tablet) { + print("Warning in wireEventBridge(): 'tablet' undefined!"); + return; + } + if (on) { + if (!hasEventBridge) { + tablet.fromQml.connect(fromQml); + hasEventBridge = true; + } + } else { + if (hasEventBridge) { + tablet.fromQml.disconnect(fromQml); + hasEventBridge = false; + } + } + } + + function onScreenChanged(type, url) { + if (url === QMLAPP_URL) { + onLuciScreen = true; + } else { + onLuciScreen = false; + } + + button.editProperties({isActive: onLuciScreen}); + wireEventBridge(onLuciScreen); + } + + function fromQml(message) { + } + + button.clicked.connect(onClicked); + tablet.screenChanged.connect(onScreenChanged); + + var moveDebugCursor = false; + Controller.mousePressEvent.connect(function (e) { + if (e.isMiddleButton) { + moveDebugCursor = true; + setDebugCursor(e.x, e.y); + } + }); + Controller.mouseReleaseEvent.connect(function() { moveDebugCursor = false; }); + Controller.mouseMoveEvent.connect(function (e) { if (moveDebugCursor) setDebugCursor(e.x, e.y); }); + + + Script.scriptEnding.connect(function () { + if (onLuciScreen) { + tablet.gotoHomeScreen(); + } + button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); + tablet.removeButton(button); + }); + + function setDebugCursor(x, y) { + } + +}()); + + + +// Set up the qml ui + +// Created by Sam Gondelman on 9/7/2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +/* +(function() { // BEGIN LOCAL_SCOPE + +var END_DIMENSIONS = { + x: 0.15, + y: 0.15, + z: 0.15 +}; +var COLOR = {red: 97, green: 247, blue: 255}; +var end = { + type: "sphere", + dimensions: END_DIMENSIONS, + color: COLOR, + ignoreRayIntersection: true, + alpha: 1.0, + visible: true +} + +var COLOR2 = {red: 247, green: 97, blue: 255}; +var end2 = { + type: "sphere", + dimensions: END_DIMENSIONS, + color: COLOR2, + ignoreRayIntersection: true, + alpha: 1.0, + visible: true +} + +var highlightGroupIndex = 0 +var isSelectionAddEnabled = false +var isSelectionEnabled = false +var renderStates = [{name: "test", end: end}]; +var defaultRenderStates = [{name: "test", distance: 20.0, end: end2}]; +var time = 0 + +var ray = LaserPointers.createLaserPointer({ + joint: "Mouse", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS | RayPick.PICK_AVATARS | RayPick.PICK_INVISIBLE | RayPick.PICK_NONCOLLIDABLE, + renderStates: renderStates, + defaultRenderStates: defaultRenderStates, + enabled: false +}); + +function getSelectionName() { + var selectionName = "contextOverlayHighlightList" + + if (highlightGroupIndex>0) { + selectionName += highlightGroupIndex + } + return selectionName +} + +function fromQml(message) { + tokens = message.split(' ') + print("Received '"+message+"' from hightlight.qml") + if (tokens[0]=="highlight") { + highlightGroupIndex = parseInt(tokens[1]) + print("Switching to highlight group "+highlightGroupIndex) + } else if (tokens[0]=="pick") { + isSelectionEnabled = tokens[1]=='true' + print("Ray picking set to "+isSelectionEnabled.toString()) + if (isSelectionEnabled) { + LaserPointers.enableLaserPointer(ray) + } else { + LaserPointers.disableLaserPointer(ray) + } + time = 0 + } else if (tokens[0]=="add") { + isSelectionAddEnabled = tokens[1]=='true' + print("Add to selection set to "+isSelectionAddEnabled.toString()) + if (!isSelectionAddEnabled) { + Selection.clearSelectedItemsList(getSelectionName()) + } + } +} + +window.fromQml.connect(fromQml); + +function cleanup() { + LaserPointers.removeLaserPointer(ray); +} +Script.scriptEnding.connect(cleanup); + +var prevID = 0 +var prevType = "" +var selectedID = 0 +var selectedType = "" +function update(deltaTime) { + + // you have to do this repeatedly because there's a bug but I'll fix it + LaserPointers.setRenderState(ray, "test"); + + var result = LaserPointers.getPrevRayPickResult(ray); + var selectionName = getSelectionName() + + if (isSelectionEnabled && result.type != RayPick.INTERSECTED_NONE) { + time += deltaTime + if (result.objectID != prevID) { + var typeName = "" + if (result.type == RayPick.INTERSECTED_ENTITY) { + typeName = "entity" + } else if (result.type == RayPick.INTERSECTED_OVERLAY) { + typeName = "overlay" + } else if (result.type == RayPick.INTERSECTED_AVATAR) { + typeName = "avatar" + } + + prevID = result.objectID; + prevType = typeName; + time = 0 + } else if (time>1.0 && prevID!=selectedID) { + if (prevID != 0 && !isSelectionAddEnabled) { + Selection.removeFromSelectedItemsList(selectionName, selectedType, selectedID) + } + selectedID = prevID + selectedType = prevType + Selection.addToSelectedItemsList(selectionName, selectedType, selectedID) + print("HIGHLIGHT " + highlightGroupIndex + " picked type: " + result.type + ", id: " + result.objectID); + } + } else { + if (prevID != 0 && !isSelectionAddEnabled) { + Selection.removeFromSelectedItemsList(selectionName, prevType, prevID) + } + prevID = 0 + selectedID = 0 + time = 0 + } +} + +Script.update.connect(update); + +}()); // END LOCAL_SCOPE*/ \ No newline at end of file diff --git a/scripts/developer/utilities/render/highlight2.qml b/scripts/developer/utilities/render/highlight2.qml new file mode 100644 index 0000000000..6be74fcf40 --- /dev/null +++ b/scripts/developer/utilities/render/highlight2.qml @@ -0,0 +1,177 @@ +// +// highlight.qml +// developer/utilities/render +// +// Olivier Prat, created on 08/08/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls +import "configSlider" + +Rectangle { + id: root + HifiConstants { id: hifi;} + color: hifi.colors.baseGray; + anchors.margins: hifi.dimensions.contentMargin.x + + property var debugConfig: Render.getConfig("RenderMainView.HighlightDebug") + property var highlightConfig: Render.getConfig("UpdateScene.HighlightStageSetup") + + signal sendToScript(var message); + + Column { + id: col + spacing: 10 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x + + Row { + spacing: 10 + anchors.left: parent.left + anchors.right: parent.right + + HifiControls.CheckBox { + id: debug + text: "View Mask" + checked: root.debugConfig["viewMask"] + onCheckedChanged: { + root.debugConfig["viewMask"] = checked; + } + } + HifiControls.CheckBox { + text: "Hover select" + checked: false + onCheckedChanged: { + sendToScript("pick "+checked.toString()) + } + } + HifiControls.CheckBox { + text: "Add to selection" + checked: false + onCheckedChanged: { + sendToScript("add "+checked.toString()) + } + } + } + + HifiControls.ComboBox { + id: box + width: 350 + z: 999 + editable: true + colorScheme: hifi.colorSchemes.dark + model: [ + "contextOverlayHighlightList", + "highlightList1", + "highlightList2", + "highlightList3", + "highlightList4"] + label: "" + + Timer { + id: postpone + interval: 100; running: false; repeat: false + onTriggered: { paramWidgetLoader.sourceComponent = paramWidgets } + } + onCurrentIndexChanged: { + root.highlightConfig["selectionName"] = model[currentIndex]; + sendToScript("highlight "+currentIndex) + // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component + // by setting the loader source to Null and then recreate it 100ms later + paramWidgetLoader.sourceComponent = undefined; + postpone.interval = 100 + postpone.start() + } + } + + Loader { + id: paramWidgetLoader + sourceComponent: paramWidgets + width: 350 + } + + Component { + id: paramWidgets + + Column { + spacing: 10 + anchors.margins: hifi.dimensions.contentMargin.x + + HifiControls.Label { + text: "Outline" + } + Column { + spacing: 10 + anchors.left: parent.left + anchors.right: parent.right + HifiControls.CheckBox { + text: "Smooth" + checked: root.highlightConfig["isOutlineSmooth"] + onCheckedChanged: { + root.highlightConfig["isOutlineSmooth"] = checked; + } + } + Repeater { + model: ["Width:outlineWidth:5.0:0.0", + "Intensity:outlineIntensity:1.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: root.highlightConfig + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + } + } + } + + Separator {} + HifiControls.Label { + text: "Color" + } + Repeater { + model: ["Red:colorR:1.0:0.0", + "Green:colorG:1.0:0.0", + "Blue:colorB:1.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: root.highlightConfig + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + } + } + + Separator {} + HifiControls.Label { + text: "Fill Opacity" + } + Repeater { + model: ["Unoccluded:unoccludedFillOpacity:1.0:0.0", + "Occluded:occludedFillOpacity:1.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: root.highlightConfig + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + } + } + } + } + } +}