diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 86cc0218a4..3343cec26f 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -14,6 +14,7 @@ import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.0 import "../styles-uit" +import "../controls-uit" as HifiControls import "toolbars" // references Users, UserActivityLogger, MyAvatar, Vec3, Quat, AddressManager from root context @@ -42,8 +43,9 @@ Item { property bool selected: false property bool isAdmin: false property bool isPresent: true + property string placeName: "" property string profilePicBorderColor: (connectionStatus == "connection" ? hifi.colors.indigoAccent : (connectionStatus == "friend" ? hifi.colors.greenHighlight : "transparent")) - + property alias avImage: avatarImage Item { id: avatarImage visible: profileUrl !== "" && userName !== ""; @@ -79,25 +81,6 @@ Item { anchors.fill: parent; visible: userImage.status != Image.Ready; } - StateImage { - id: infoHoverImage; - visible: false; - imageURL: "../../images/info-icon-2-state.svg"; - size: 32; - buttonState: 1; - anchors.centerIn: parent; - } - MouseArea { - anchors.fill: parent - enabled: selected || isMyCard; - hoverEnabled: enabled - onClicked: { - userInfoViewer.url = defaultBaseUrl + "/users/" + userName; - userInfoViewer.visible = true; - } - onEntered: infoHoverImage.visible = true; - onExited: infoHoverImage.visible = false; - } } // Colored border around avatarImage @@ -316,9 +299,10 @@ Item { visible: thisNameCard.userName !== ""; // Size width: parent.width - height: pal.activeTab == "nearbyTab" || isMyCard ? usernameTextPixelSize + 4 : parent.height; + height: usernameTextPixelSize + 4 // Anchors - anchors.top: isMyCard ? myDisplayName.bottom : (pal.activeTab == "nearbyTab" ? displayNameContainer.bottom : parent.top); + anchors.top: isMyCard ? myDisplayName.bottom : pal.activeTab == "nearbyTab" ? displayNameContainer.bottom : undefined //(parent.height - displayNameTextPixelSize/2)); + anchors.verticalCenter: pal.activeTab == "connectionsTab" ? avatarImage.verticalCenter : undefined anchors.left: avatarImage.right; anchors.leftMargin: avatarImage.visible ? 5 : 0; anchors.rightMargin: 5; @@ -346,6 +330,92 @@ Item { } } } + StateImage { + id: nameCardConnectionInfoImage + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" + imageURL: "../../images/info-icon-2-state.svg" // PLACEHOLDER!!! + size: 32; + buttonState: 0; + anchors.left: avatarImage.right + anchors.bottom: parent.bottom + } + MouseArea { + anchors.fill:nameCardConnectionInfoImage + enabled: selected + hoverEnabled: true + onClicked: { + userInfoViewer.url = defaultBaseUrl + "/users/" + userName; + userInfoViewer.visible = true; + } + onEntered: { + nameCardConnectionInfoImage.buttonState = 1; + } + onExited: { + nameCardConnectionInfoImage.buttonState = 0; + } + } + FiraSansRegular { + id: nameCardConnectionInfoText + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard + width: parent.width + height: displayNameTextPixelSize + size: displayNameTextPixelSize - 4 + anchors.left: nameCardConnectionInfoImage.right + anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter + anchors.leftMargin: 5 + verticalAlignment: Text.AlignVCenter + text: "Info" + color: hifi.colors.baseGray + } + HiFiGlyphs { + id: nameCardRemoveConnectionImage + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" + text: hifi.glyphs.close + size: 28; + x: 120 + anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter + } + MouseArea { + anchors.fill:nameCardRemoveConnectionImage + enabled: selected + hoverEnabled: true + onClicked: { + // send message to pal.js to forgetConnection + pal.sendToScript({method: 'removeConnection', params: thisNameCard.userName}); + } + onEntered: { + nameCardRemoveConnectionImage.text = hifi.glyphs.closeInverted; + } + onExited: { + nameCardRemoveConnectionImage.text = hifi.glyphs.close; + } + } + FiraSansRegular { + id: nameCardRemoveConnectionText + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard + width: parent.width + height: displayNameTextPixelSize + size: displayNameTextPixelSize - 4 + anchors.left: nameCardRemoveConnectionImage.right + anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter + anchors.leftMargin: 5 + verticalAlignment: Text.AlignVCenter + text: "Forget" + color: hifi.colors.baseGray + } + HifiControls.Button { + id: visitConnectionButton + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard + text: "Visit" + enabled: thisNameCard.placeName !== "" + anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter + x: 240 + onClicked: { + AddressManager.goToUser(thisNameCard.userName); + UserActivityLogger.palAction("go_to_user", thisNameCard.userName); + } + } + // VU Meter Rectangle { id: nameCardVUMeter @@ -484,7 +554,7 @@ Item { } } } - + function updateGainFromQML(avatarUuid, sliderValue, isReleased) { Users.setAvatarGain(avatarUuid, sliderValue); if (isReleased) { diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 2f10f0fdf5..d8566bb28e 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -52,6 +52,13 @@ Rectangle { id: letterboxMessage; z: 999; // Force the popup on top of everything else } + Connections { + target: GlobalServices + onMyUsernameChanged: { + myData.userName = Account.username; + myDataChanged(); // Setting a property within an object isn't enough to update dependencies. This will do it. + } + } // The ComboDialog used for setting availability ComboDialog { id: comboDialog; @@ -763,7 +770,7 @@ Rectangle { // This Rectangle refers to each Row in the connectionsTable. rowDelegate: Rectangle { // Size - height: rowHeight; + height: rowHeight + (styleData.selected ? 15 : 0); color: connectionsRowColor(styleData.selected, styleData.alternate); } @@ -779,6 +786,7 @@ Rectangle { profileUrl: (model && model.profileUrl) || ""; displayName: ""; userName: model ? model.userName : ""; + placeName: model ? model.placeName : "" connectionStatus : model ? model.connection : ""; selected: styleData.selected; // Size @@ -797,12 +805,16 @@ Rectangle { elide: Text.ElideRight; // Size width: parent.width; - // Anchors - anchors.fill: parent; + // you would think that this would work: + // anchors.verticalCenter: connectionsNameCard.avImage.verticalCenter + // but no! you cannot anchor to a non-sibling or parent. So I will + // align with the friends checkbox, where I did the manual alignment + anchors.verticalCenter: friendsCheckBox.verticalCenter // Text Size size: 16; // Text Positioning verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter // Style color: hifi.colors.blueAccent; font.underline: true; @@ -822,8 +834,12 @@ Rectangle { // "Friends" checkbox HifiControlsUit.CheckBox { id: friendsCheckBox; - visible: styleData.role === "friends" && model.userName !== myData.userName; - anchors.centerIn: parent; + visible: styleData.role === "friends" && model && model.userName !== myData.userName; + // you would think that this would work: + // anchors.verticalCenter: connectionsNameCard.avImage.verticalCenter + // but no! you cannot anchor to a non-sibling or parent. So: + x: parent.width/2 - boxSize/2 + y: connectionsNameCard.avImage.y + connectionsNameCard.avImage.height/2 - boxSize/2 checked: model ? (model["connection"] === "friend" ? true : false) : false; boxSize: 24; onClicked: { @@ -901,7 +917,7 @@ Rectangle { wrapMode: Text.WordWrap textFormat: Text.StyledText; // Text - text: HMD.active ? + text: HMD.isMounted ? "When you meet someone you want to remember later, you can connect with a handshake:

" + "1. Put your hand out onto their hand and squeeze your controller's grip button on its side.
" + "2. Once the other person puts their hand onto yours, you'll see your connection form.
" + @@ -960,7 +976,6 @@ Rectangle { // Text size size: hifi.fontSizes.tabularData; // Anchors - anchors.top: myCard.top; anchors.left: parent.left; // Style color: hifi.colors.baseGrayHighlight; diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 9e6c18bb96..3bbd26e010 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -278,11 +278,9 @@ void OffscreenQmlSurface::cleanup() { } void OffscreenQmlSurface::render() { - #ifdef HIFI_ENABLE_NSIGHT_DEBUG return; #endif - if (_paused) { return; } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 414bcf0d63..da264cbf7d 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -28,6 +28,12 @@ #include "skin_model_shadow_vert.h" #include "skin_model_normal_map_vert.h" +#include "simple_vert.h" +#include "simple_textured_frag.h" +#include "simple_textured_unlit_frag.h" +#include "simple_transparent_textured_frag.h" +#include "simple_transparent_textured_unlit_frag.h" + #include "model_frag.h" #include "model_unlit_frag.h" #include "model_shadow_frag.h" @@ -135,6 +141,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { void initDeferredPipelines(render::ShapePlumber& plumber) { // Vertex shaders + auto simpleVertex = gpu::Shader::createVertex(std::string(simple_vert)); auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); @@ -145,6 +152,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); // Pixel shaders + auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag)); + auto simpleUnlitPixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); + auto simpleTranslucentPixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_frag)); + auto simpleTranslucentUnlitPixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_unlit_frag)); auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag)); auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); @@ -167,13 +178,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { modelVertex, modelPixel); addPipeline( Key::Builder(), - modelVertex, modelPixel); + simpleVertex, simplePixel); addPipeline( Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); addPipeline( Key::Builder().withUnlit(), - modelVertex, modelUnlitPixel); + simpleVertex, simpleUnlitPixel); addPipeline( Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); @@ -189,13 +200,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { modelVertex, modelTranslucentPixel); addPipeline( Key::Builder().withTranslucent(), - modelVertex, modelTranslucentPixel); + simpleVertex, simpleTranslucentPixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withUnlit(), modelVertex, modelTranslucentUnlitPixel); addPipeline( Key::Builder().withTranslucent().withUnlit(), - modelVertex, modelTranslucentUnlitPixel); + simpleVertex, simpleTranslucentUnlitPixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 6067c81a1b..550f6546fd 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -26,15 +26,17 @@ in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); + float colorAlpha = _color.a; if (_color.a <= 0.0) { texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; } const float ALPHA_THRESHOLD = 0.999; - if (_color.a * texel.a < ALPHA_THRESHOLD) { + if (colorAlpha * texel.a < ALPHA_THRESHOLD) { packDeferredFragmentTranslucent( normalize(_normal), - _color.a * texel.a, + colorAlpha * texel.a, _color.rgb * texel.rgb, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf index 4f02140825..d261fb343a 100644 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// simple.frag +// simple_textured_unlit.frag // fragment shader // // Created by Clément Brisset on 5/29/15. @@ -25,15 +25,17 @@ in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0.st); + float colorAlpha = _color.a; if (_color.a <= 0.0) { texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; } const float ALPHA_THRESHOLD = 0.999; - if (_color.a * texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( + if (colorAlpha * texel.a < ALPHA_THRESHOLD) { + packDeferredFragmentTranslucent( normalize(_normal), - _color.a * texel.a, + colorAlpha * texel.a, _color.rgb * texel.rgb, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf new file mode 100644 index 0000000000..b9eb921e9d --- /dev/null +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -0,0 +1,62 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_transparent_textured.slf +// fragment shader +// +// Created by Sam Gateau on 4/3/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Color.slh@> + +<@include DeferredBufferWrite.slh@> +<@include DeferredGlobalLight.slh@> +<$declareEvalGlobalLightingAlphaBlended()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec4 _position; +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0.st); + float opacity = _color.a; + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + opacity = -_color.a; + } + opacity *= texel.a; + vec3 albedo = _color.rgb * texel.rgb; + + vec3 fragPosition = _position.xyz; + vec3 fragNormal = normalize(_normal); + + TransformCamera cam = getTransformCamera(); + + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + 1.0, + fragPosition, + fragNormal, + albedo, + DEFAULT_FRESNEL, + 0.0, + vec3(0.0f), + DEFAULT_ROUGHNESS, + opacity), + opacity); + +} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit.slf b/libraries/render-utils/src/simple_transparent_textured_unlit.slf new file mode 100644 index 0000000000..693d7be2db --- /dev/null +++ b/libraries/render-utils/src/simple_transparent_textured_unlit.slf @@ -0,0 +1,36 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_transparent_textured_unlit.slf +// fragment shader +// +// Created by Sam Gateau on 4/3/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Color.slh@> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; + + +layout(location = 0) out vec4 _fragColor0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0.st); + float colorAlpha = _color.a; + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; + } + _fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a); +} \ No newline at end of file diff --git a/scripts/system/pal.js b/scripts/system/pal.js index b39c993894..5fbea90025 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -269,13 +269,26 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See getConnectionData(); UserActivityLogger.palAction("refresh_connections", ""); break; + case 'removeConnection': + connectionUserName = message.params; + request({ + uri: METAVERSE_BASE + '/api/v1/user/connections/' + connectionUserName, + method: 'DELETE' + }, function (error, response) { + if (error || (response.status !== 'success')) { + print("Error: unable to remove connection", connectionUserName, error || response.status); + return; + } + getConnectionData(); + }); + break + case 'removeFriend': friendUserName = message.params; request({ uri: METAVERSE_BASE + '/api/v1/user/friends/' + friendUserName, method: 'DELETE' }, function (error, response) { - print(JSON.stringify(response)); if (error || (response.status !== 'success')) { print("Error: unable to unfriend", friendUserName, error || response.status); return;