From 8bb200902f3b1c496afadfba0cc9ecb249f70857 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 10 Jan 2017 16:40:48 -0800 Subject: [PATCH 01/11] First pass --- assignment-client/src/audio/AudioMixer.cpp | 18 ++++++++-- assignment-client/src/audio/AudioMixer.h | 1 + .../src/audio/AudioMixerClientData.h | 6 ++++ .../src/audio/AudioMixerSlave.cpp | 7 ++-- assignment-client/src/audio/AudioMixerSlave.h | 2 +- interface/resources/qml/hifi/NameCard.qml | 33 ++++++++++++++++++- interface/resources/qml/hifi/Pal.qml | 2 ++ libraries/networking/src/NodeList.cpp | 23 +++++++++++++ libraries/networking/src/NodeList.h | 1 + libraries/networking/src/udt/PacketHeaders.h | 3 +- .../src/UsersScriptingInterface.cpp | 5 +++ .../src/UsersScriptingInterface.h | 8 +++++ scripts/system/pal.js | 4 +++ 13 files changed, 105 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 19ebd4ea87..fddd2d641e 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -68,7 +68,8 @@ AudioMixer::AudioMixer(ReceivedMessage& message) : packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket"); packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket"); - packetReceiver.registerListener(PacketType::RequestsDomainListData, this, "handleRequestsDomainListDataPacket"); + packetReceiver.registerListener(PacketType::RequestsDomainListData, this, "handleRequestsDomainListDataPacket"); + packetReceiver.registerListener(PacketType::PerAvatarGainSet, this, "handlePerAvatarGainSetDataPacket"); connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled); } @@ -186,7 +187,9 @@ void AudioMixer::handleNodeKilled(SharedNodePointer killedNode) { nodeList->eachNode([&killedNode](const SharedNodePointer& node) { auto clientData = dynamic_cast(node->getLinkedData()); if (clientData) { - clientData->removeHRTFsForNode(killedNode->getUUID()); + QUuid killedUUID = killedNode->getUUID(); + clientData->removePerAvatarGain(killedUUID); + clientData->removeHRTFsForNode(killedUUID); } }); } @@ -240,6 +243,17 @@ void AudioMixer::handleNodeIgnoreRequestPacket(QSharedPointer p sendingNode->parseIgnoreRequestMessage(packet); } +void AudioMixer::handlePerAvatarGainSetDataPacket(QSharedPointer packet, SharedNodePointer sendingNode) { + auto clientData = dynamic_cast(sendingNode->getLinkedData()); + if (clientData) { + // parse the UUID from the packet + QUuid ignoredUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + float gain; + packet->readPrimitive(&gain); + clientData->setPerAvatarGain(ignoredUUID, gain); + } +} + void AudioMixer::handleRadiusIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { sendingNode->parseIgnoreRadiusRequestMessage(packet); } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index d9759653fb..d88bc3b917 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -66,6 +66,7 @@ private slots: void handleRadiusIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); void handleKillAvatarPacket(QSharedPointer packet, SharedNodePointer sendingNode); void handleNodeMuteRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); + void handlePerAvatarGainSetDataPacket(QSharedPointer packet, SharedNodePointer sendingNode); void start(); void removeHRTFsForFinishedInjector(const QUuid& streamID); diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index e637fd0409..d7fbfe5112 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -95,6 +95,10 @@ public: bool getRequestsDomainListData() { return _requestsDomainListData; } void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; } + float getPerAvatarGain(const QUuid& avatarID) { return (_perAvatarGain.count(avatarID) ? _perAvatarGain.at(avatarID) : 1.0f); } + void setPerAvatarGain(const QUuid& avatarID, float gain) { _perAvatarGain[avatarID] = gain; } + void removePerAvatarGain(const QUuid& avatarID) { _perAvatarGain.erase(avatarID); } + signals: void injectorStreamFinished(const QUuid& streamIdentifier); @@ -125,6 +129,8 @@ private: bool _shouldMuteClient { false }; bool _requestsDomainListData { false }; + + std::unordered_map _perAvatarGain; }; #endif // hifi_AudioMixerClientData_h diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index 28d3358eb5..90037b7187 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -252,12 +252,13 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& node) { // Enumerate the audio streams attached to the otherNode auto streamsCopy = otherData->getAudioStreams(); + float thisAvatarGain = nodeData->getPerAvatarGain(otherNode->getUUID()); for (auto& streamPair : streamsCopy) { auto otherNodeStream = streamPair.second; bool isSelfWithEcho = ((*otherNode == *node) && (otherNodeStream->shouldLoopbackForNode())); // Add all audio streams that should be added to the mix if (isSelfWithEcho || (!isSelfWithEcho && !insideIgnoreRadius)) { - addStreamToMix(*nodeData, otherNode->getUUID(), *nodeAudioStream, *otherNodeStream); + addStreamToMix(*nodeData, otherNode->getUUID(), *nodeAudioStream, *otherNodeStream, thisAvatarGain); } } } @@ -278,7 +279,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& node) { } void AudioMixerSlave::addStreamToMix(AudioMixerClientData& listenerNodeData, const QUuid& sourceNodeID, - const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd) { + const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd, float perAvatarGain) { // to reduce artifacts we calculate the gain and azimuth for every source for this listener // even if we are not going to end up mixing in this source @@ -295,7 +296,7 @@ void AudioMixerSlave::addStreamToMix(AudioMixerClientData& listenerNodeData, con float distance = glm::max(glm::length(relativePosition), EPSILON); // figure out the gain for this source at the listener - float gain = gainForSource(listeningNodeStream, streamToAdd, relativePosition, isEcho); + float gain = gainForSource(listeningNodeStream, streamToAdd, relativePosition, isEcho) + (perAvatarGain - 1.0f); // figure out the azimuth to this source at the listener float azimuth = isEcho ? 0.0f : azimuthForSource(listeningNodeStream, listeningNodeStream, relativePosition); diff --git a/assignment-client/src/audio/AudioMixerSlave.h b/assignment-client/src/audio/AudioMixerSlave.h index c4aabfbb4a..89aa70f99a 100644 --- a/assignment-client/src/audio/AudioMixerSlave.h +++ b/assignment-client/src/audio/AudioMixerSlave.h @@ -43,7 +43,7 @@ private: bool prepareMix(const SharedNodePointer& node); // add a stream to the mix void addStreamToMix(AudioMixerClientData& listenerData, const QUuid& streamerID, - const AvatarAudioStream& listenerStream, const PositionalAudioStream& streamer); + const AvatarAudioStream& listenerStream, const PositionalAudioStream& streamer, float perAvatarGain); float gainForSource(const AvatarAudioStream& listener, const PositionalAudioStream& streamer, const glm::vec3& relativePosition, bool isEcho); diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index a0dde8bacc..0a0b662193 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -10,6 +10,7 @@ // import QtQuick 2.5 +import QtQuick.Controls 1.4 import QtGraphicalEffects 1.0 import "../styles-uit" @@ -27,12 +28,14 @@ Row { } // Properties - property int contentHeight: 50 + property int contentHeight: isMyCard ? 50 : 70 + property string uuid: "" property string displayName: "" property string userName: "" property int displayTextHeight: 18 property int usernameTextHeight: 12 property real audioLevel: 0.0 + property bool isMyCard: false /* User image commented out for now - will probably be re-introduced later. Column { @@ -138,5 +141,33 @@ Row { } } } + + // Per-Avatar Gain Slider Spacer + Item { + width: parent.width + height: 4 + visible: !isMyCard + } + // Per-Avatar Gain Slider + Slider { + id: gainSlider + visible: !isMyCard + width: parent.width + height: 16 + value: 1.0 + minimumValue: 0.0 + maximumValue: 1.5 + stepSize: 0.1 + updateValueWhileDragging: false + onValueChanged: updateGainFromQML(uuid, value) + } + } + + function updateGainFromQML(avatarUuid, gainValue) { + var data = { + sessionId: avatarUuid, + gain: (Math.exp(gainValue) - 1) / (Math.E - 1) + }; + pal.sendToScript({method: 'updateGain', params: data}); } } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 66dce622ff..4f65497da5 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -65,6 +65,7 @@ Rectangle { displayName: myData.displayName userName: myData.userName audioLevel: myData.audioLevel + isMyCard: true // Size width: nameCardWidth height: parent.height @@ -206,6 +207,7 @@ Rectangle { userName: model && model.userName audioLevel: model && model.audioLevel visible: !isCheckBox && !isButton + uuid: model && model.sessionId // Size width: nameCardWidth height: parent.height diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index d890431a45..00f13dff3d 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -951,6 +951,29 @@ void NodeList::maybeSendIgnoreSetToNode(SharedNodePointer newNode) { } } +void NodeList::setAvatarGain(const QUuid& nodeID, float gain) { + // cannot set gain of yourself or nobody + if (!nodeID.isNull() && _sessionUUID != nodeID) { + auto audioMixer = soloNodeOfType(NodeType::AudioMixer); + if (audioMixer) { + // setup the packet + auto setAvatarGainPacket = NLPacket::create(PacketType::PerAvatarGainSet, NUM_BYTES_RFC4122_UUID + sizeof(float), true); + + // write the node ID to the packet + setAvatarGainPacket->write(nodeID.toRfc4122()); + setAvatarGainPacket->writePrimitive((gain < 5.0f ? gain : 5.0f)); + + qCDebug(networking) << "Sending Set Avatar Gain packet UUID: " << uuidStringWithoutCurlyBraces(nodeID) << "Gain:" << gain; + + sendPacket(std::move(setAvatarGainPacket), *audioMixer); + } else { + qWarning() << "Couldn't find audio mixer to send set gain request"; + } + } else { + qWarning() << "NodeList::setAvatarGain called with an invalid ID or an ID which matches the current session ID:" << nodeID; + } +} + void NodeList::kickNodeBySessionID(const QUuid& nodeID) { // send a request to domain-server to kick the node with the given session ID // the domain-server will handle the persistence of the kick (via username or IP) diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 8e285629dc..5c477303e2 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -82,6 +82,7 @@ public: bool isIgnoringNode(const QUuid& nodeID) const; void personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled); bool isPersonalMutingNode(const QUuid& nodeID) const; + void setAvatarGain(const QUuid& nodeID, float gain); void kickNodeBySessionID(const QUuid& nodeID); void muteNodeBySessionID(const QUuid& nodeID); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index e4c4937622..0328037eb3 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -106,7 +106,8 @@ public: ViewFrustum, RequestsDomainListData, ExitingSpaceBubble, - LAST_PACKET_TYPE = ExitingSpaceBubble + PerAvatarGainSet, + LAST_PACKET_TYPE = ExitingSpaceBubble // FIXME!!! }; }; diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index d0ad699846..3a3225ec75 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -42,6 +42,11 @@ bool UsersScriptingInterface::getPersonalMuteStatus(const QUuid& nodeID) { return DependencyManager::get()->isPersonalMutingNode(nodeID); } +void UsersScriptingInterface::setAvatarGain(const QUuid& nodeID, float gain) { + // ask the NodeList to set the gain of the specified avatar + DependencyManager::get()->setAvatarGain(nodeID, gain); +} + void UsersScriptingInterface::kick(const QUuid& nodeID) { // ask the NodeList to kick the user with the given session ID DependencyManager::get()->kickNodeBySessionID(nodeID); diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 341285a742..d2d77a6796 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -61,6 +61,14 @@ public slots: */ bool getPersonalMuteStatus(const QUuid& nodeID); + /**jsdoc + * Sets an avatar's gain for you and you only. + * @function Users.setAvatarGain + * @param {nodeID} nodeID The node or session ID of the user whose gain you want to modify. + * @param {float} gain The gain of the avatar you'd like to set. + */ + void setAvatarGain(const QUuid& nodeID, float gain); + /**jsdoc * Kick another user. * @function Users.kick diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 48f44570fd..12f0793b97 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -233,6 +233,10 @@ pal.fromQml.connect(function (message) { // messages are {method, params}, like removeOverlays(); populateUserList(); break; + case 'updateGain': + data = message.params; + Users.setAvatarGain(data['sessionId'], data['gain']); + break; default: print('Unrecognized message from Pal.qml:', JSON.stringify(message)); } From dcff873cd46d4747c53539a728c3717c774453fa Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 10 Jan 2017 16:50:38 -0800 Subject: [PATCH 02/11] Modify slider function --- assignment-client/src/audio/AudioMixerSlave.cpp | 2 +- interface/resources/qml/hifi/NameCard.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index 90037b7187..d502239341 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -296,7 +296,7 @@ void AudioMixerSlave::addStreamToMix(AudioMixerClientData& listenerNodeData, con float distance = glm::max(glm::length(relativePosition), EPSILON); // figure out the gain for this source at the listener - float gain = gainForSource(listeningNodeStream, streamToAdd, relativePosition, isEcho) + (perAvatarGain - 1.0f); + float gain = gainForSource(listeningNodeStream, streamToAdd, relativePosition, isEcho) * perAvatarGain; // figure out the azimuth to this source at the listener float azimuth = isEcho ? 0.0f : azimuthForSource(listeningNodeStream, listeningNodeStream, relativePosition); diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 0a0b662193..18dbaf1fe1 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -166,7 +166,7 @@ Row { function updateGainFromQML(avatarUuid, gainValue) { var data = { sessionId: avatarUuid, - gain: (Math.exp(gainValue) - 1) / (Math.E - 1) + gain: (Math.pow(20, gainValue) - 1) / (20 - 1) }; pal.sendToScript({method: 'updateGain', params: data}); } From 503468e49b865f341ffdcfd7a965b12b1a959f39 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 10 Jan 2017 17:20:25 -0800 Subject: [PATCH 03/11] Style changes --- interface/resources/qml/hifi/NameCard.qml | 19 +++++++++++++++++-- interface/resources/qml/hifi/Pal.qml | 6 +++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 18dbaf1fe1..1f4ef07131 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -11,6 +11,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.0 import "../styles-uit" @@ -28,7 +29,7 @@ Row { } // Properties - property int contentHeight: isMyCard ? 50 : 70 + property int contentHeight: 70 property string uuid: "" property string displayName: "" property string userName: "" @@ -153,13 +154,27 @@ Row { id: gainSlider visible: !isMyCard width: parent.width - height: 16 + height: 18 value: 1.0 minimumValue: 0.0 maximumValue: 1.5 stepSize: 0.1 updateValueWhileDragging: false onValueChanged: updateGainFromQML(uuid, value) + style: SliderStyle { + groove: Rectangle { + color: "#dbdbdb" + implicitWidth: gainSlider.width + implicitHeight: 4 + radius: 2 + } + handle: Rectangle { + anchors.centerIn: parent + color: (control.pressed || control.hovered) ? "#00b4ef" : "#8F8F8F" + implicitWidth: 10 + implicitHeight: 18 + } + } } } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 4f65497da5..2cc07bf90d 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -24,8 +24,8 @@ Rectangle { // Style color: "#E3E3E3" // Properties - property int myCardHeight: 70 - property int rowHeight: 70 + property int myCardHeight: 90 + property int rowHeight: 90 property int actionButtonWidth: 75 property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 4 : 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth property var myData: ({displayName: "", userName: "", audioLevel: 0.0}) // valid dummy until set @@ -51,7 +51,7 @@ Rectangle { id: myInfo // Size width: palContainer.width - height: myCardHeight + 20 + height: myCardHeight // Style color: pal.color // Anchors From 8c3766dfe81d26192b0f1447f55d511041e73f58 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 10 Jan 2017 17:21:51 -0800 Subject: [PATCH 04/11] Fixme --- libraries/networking/src/udt/PacketHeaders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 0328037eb3..c012ed8f67 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -107,7 +107,7 @@ public: RequestsDomainListData, ExitingSpaceBubble, PerAvatarGainSet, - LAST_PACKET_TYPE = ExitingSpaceBubble // FIXME!!! + LAST_PACKET_TYPE = PerAvatarGainSet }; }; From b9cddc31a941f940067692537b2117449244ee52 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 11 Jan 2017 11:56:35 -0800 Subject: [PATCH 05/11] Checkpoint before implementing Ken's suggestions --- interface/resources/qml/hifi/NameCard.qml | 3 ++- interface/resources/qml/hifi/Pal.qml | 4 +++- scripts/system/pal.js | 12 ++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 1f4ef07131..4b8ee6cbc3 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -155,7 +155,7 @@ Row { visible: !isMyCard width: parent.width height: 18 - value: 1.0 + value: pal.gain[uuid] ? pal.gain[uuid] : 1.0 minimumValue: 0.0 maximumValue: 1.5 stepSize: 0.1 @@ -179,6 +179,7 @@ Row { } function updateGainFromQML(avatarUuid, gainValue) { + pal.gain[avatarUuid] = gainValue; var data = { sessionId: avatarUuid, gain: (Math.pow(20, gainValue) - 1) / (20 - 1) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 2cc07bf90d..039ab78baf 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -32,6 +32,7 @@ Rectangle { property var ignored: ({}); // Keep a local list of ignored avatars & their data. Necessary because HashMap is slow to respond after ignoring. property var userModelData: [] // This simple list is essentially a mirror of the userModel listModel without all the extra complexities. property bool iAmAdmin: false + property var gain: ({}); // Keep a local list of per-avatar gain. Far faster than keeping this data on the server. // This is the container for the PAL Rectangle { @@ -494,8 +495,9 @@ Rectangle { } } break; - case 'clearIgnored': + case 'clearLocalQMLData': ignored = {}; + gain = {}; break; default: console.log('Unrecognized message:', JSON.stringify(message)); diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 12f0793b97..6b3fd00c3b 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -586,14 +586,14 @@ button.clicked.connect(onClicked); pal.visibleChanged.connect(onVisibleChanged); pal.closed.connect(off); Users.usernameFromIDReply.connect(usernameFromIDReply); -function clearIgnoredInQMLAndClosePAL() { - pal.sendToQml({ method: 'clearIgnored' }); +function clearLocalQMLDataAndClosePAL() { + pal.sendToQml({ method: 'clearLocalQMLData' }); if (pal.visible) { onClicked(); // Close the PAL } } -Window.domainChanged.connect(clearIgnoredInQMLAndClosePAL); -Window.domainConnectionRefused.connect(clearIgnoredInQMLAndClosePAL); +Window.domainChanged.connect(clearLocalQMLDataAndClosePAL); +Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL); // // Cleanup. @@ -604,8 +604,8 @@ Script.scriptEnding.connect(function () { pal.visibleChanged.disconnect(onVisibleChanged); pal.closed.disconnect(off); Users.usernameFromIDReply.disconnect(usernameFromIDReply); - Window.domainChanged.disconnect(clearIgnoredInQMLAndClosePAL); - Window.domainConnectionRefused.disconnect(clearIgnoredInQMLAndClosePAL); + Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL); + Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL); Messages.unsubscribe(CHANNEL); Messages.messageReceived.disconnect(receiveMessage); off(); From b0b6aeac6c0eba9331eaa4f837803032acb93944 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 11 Jan 2017 16:16:35 -0800 Subject: [PATCH 06/11] Ken's feedback --- assignment-client/src/audio/AudioMixer.cpp | 13 ++++---- .../src/audio/AudioMixerClientData.h | 6 ---- .../src/audio/AudioMixerSlave.cpp | 7 ++--- assignment-client/src/audio/AudioMixerSlave.h | 2 +- interface/resources/qml/hifi/NameCard.qml | 30 ++++++++++++------- interface/resources/qml/hifi/Pal.qml | 6 ++-- libraries/audio/src/AudioHRTF.h | 2 +- libraries/networking/src/NodeList.cpp | 4 ++- .../src/UsersScriptingInterface.h | 3 +- 9 files changed, 41 insertions(+), 32 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index fddd2d641e..07639867eb 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -28,6 +28,7 @@ #include #include +#include "AudioHelpers.h" #include "AudioRingBuffer.h" #include "AudioMixerClientData.h" #include "AvatarAudioStream.h" @@ -188,7 +189,6 @@ void AudioMixer::handleNodeKilled(SharedNodePointer killedNode) { auto clientData = dynamic_cast(node->getLinkedData()); if (clientData) { QUuid killedUUID = killedNode->getUUID(); - clientData->removePerAvatarGain(killedUUID); clientData->removeHRTFsForNode(killedUUID); } }); @@ -246,11 +246,14 @@ void AudioMixer::handleNodeIgnoreRequestPacket(QSharedPointer p void AudioMixer::handlePerAvatarGainSetDataPacket(QSharedPointer packet, SharedNodePointer sendingNode) { auto clientData = dynamic_cast(sendingNode->getLinkedData()); if (clientData) { + QUuid listeningNodeUUID = sendingNode->getUUID(); // parse the UUID from the packet - QUuid ignoredUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); - float gain; - packet->readPrimitive(&gain); - clientData->setPerAvatarGain(ignoredUUID, gain); + QUuid audioSourceUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + uint8_t packedGain; + packet->readPrimitive(&packedGain); + float gain = unpackFloatGainFromByte(packedGain); + clientData->hrtfForStream(audioSourceUUID, QUuid()).setGainAdjustment(gain); + qDebug() << "Setting gain adjustment for hrtf[" << listeningNodeUUID << "][" << audioSourceUUID << "] to " << gain; } } diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index d7fbfe5112..e637fd0409 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -95,10 +95,6 @@ public: bool getRequestsDomainListData() { return _requestsDomainListData; } void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; } - float getPerAvatarGain(const QUuid& avatarID) { return (_perAvatarGain.count(avatarID) ? _perAvatarGain.at(avatarID) : 1.0f); } - void setPerAvatarGain(const QUuid& avatarID, float gain) { _perAvatarGain[avatarID] = gain; } - void removePerAvatarGain(const QUuid& avatarID) { _perAvatarGain.erase(avatarID); } - signals: void injectorStreamFinished(const QUuid& streamIdentifier); @@ -129,8 +125,6 @@ private: bool _shouldMuteClient { false }; bool _requestsDomainListData { false }; - - std::unordered_map _perAvatarGain; }; #endif // hifi_AudioMixerClientData_h diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index d502239341..28d3358eb5 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -252,13 +252,12 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& node) { // Enumerate the audio streams attached to the otherNode auto streamsCopy = otherData->getAudioStreams(); - float thisAvatarGain = nodeData->getPerAvatarGain(otherNode->getUUID()); for (auto& streamPair : streamsCopy) { auto otherNodeStream = streamPair.second; bool isSelfWithEcho = ((*otherNode == *node) && (otherNodeStream->shouldLoopbackForNode())); // Add all audio streams that should be added to the mix if (isSelfWithEcho || (!isSelfWithEcho && !insideIgnoreRadius)) { - addStreamToMix(*nodeData, otherNode->getUUID(), *nodeAudioStream, *otherNodeStream, thisAvatarGain); + addStreamToMix(*nodeData, otherNode->getUUID(), *nodeAudioStream, *otherNodeStream); } } } @@ -279,7 +278,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& node) { } void AudioMixerSlave::addStreamToMix(AudioMixerClientData& listenerNodeData, const QUuid& sourceNodeID, - const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd, float perAvatarGain) { + const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd) { // to reduce artifacts we calculate the gain and azimuth for every source for this listener // even if we are not going to end up mixing in this source @@ -296,7 +295,7 @@ void AudioMixerSlave::addStreamToMix(AudioMixerClientData& listenerNodeData, con float distance = glm::max(glm::length(relativePosition), EPSILON); // figure out the gain for this source at the listener - float gain = gainForSource(listeningNodeStream, streamToAdd, relativePosition, isEcho) * perAvatarGain; + float gain = gainForSource(listeningNodeStream, streamToAdd, relativePosition, isEcho); // figure out the azimuth to this source at the listener float azimuth = isEcho ? 0.0f : azimuthForSource(listeningNodeStream, listeningNodeStream, relativePosition); diff --git a/assignment-client/src/audio/AudioMixerSlave.h b/assignment-client/src/audio/AudioMixerSlave.h index 89aa70f99a..c4aabfbb4a 100644 --- a/assignment-client/src/audio/AudioMixerSlave.h +++ b/assignment-client/src/audio/AudioMixerSlave.h @@ -43,7 +43,7 @@ private: bool prepareMix(const SharedNodePointer& node); // add a stream to the mix void addStreamToMix(AudioMixerClientData& listenerData, const QUuid& streamerID, - const AvatarAudioStream& listenerStream, const PositionalAudioStream& streamer, float perAvatarGain); + const AvatarAudioStream& listenerStream, const PositionalAudioStream& streamer); float gainForSource(const AvatarAudioStream& listener, const PositionalAudioStream& streamer, const glm::vec3& relativePosition, bool isEcho); diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 4b8ee6cbc3..3e8ee355c8 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -155,10 +155,10 @@ Row { visible: !isMyCard width: parent.width height: 18 - value: pal.gain[uuid] ? pal.gain[uuid] : 1.0 - minimumValue: 0.0 - maximumValue: 1.5 - stepSize: 0.1 + value: pal.gainSliderValueDB[uuid] ? pal.gainSliderValueDB[uuid] : 0.0 + minimumValue: -60.0 + maximumValue: 20.0 + stepSize: 2 updateValueWhileDragging: false onValueChanged: updateGainFromQML(uuid, value) style: SliderStyle { @@ -167,6 +167,12 @@ Row { implicitWidth: gainSlider.width implicitHeight: 4 radius: 2 + MouseArea { + anchors.fill: parent + onDoubleClicked: { + gainSlider.value = 0.0 + } + } } handle: Rectangle { anchors.centerIn: parent @@ -178,12 +184,14 @@ Row { } } - function updateGainFromQML(avatarUuid, gainValue) { - pal.gain[avatarUuid] = gainValue; - var data = { - sessionId: avatarUuid, - gain: (Math.pow(20, gainValue) - 1) / (20 - 1) - }; - pal.sendToScript({method: 'updateGain', params: data}); + function updateGainFromQML(avatarUuid, sliderValue) { + if (pal.gainSliderValueDB[avatarUuid] !== sliderValue) { + pal.gainSliderValueDB[avatarUuid] = sliderValue; + var data = { + sessionId: avatarUuid, + gain: sliderValue + }; + pal.sendToScript({method: 'updateGain', params: data}); + } } } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 039ab78baf..c74d8757f7 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -32,7 +32,9 @@ Rectangle { property var ignored: ({}); // Keep a local list of ignored avatars & their data. Necessary because HashMap is slow to respond after ignoring. property var userModelData: [] // This simple list is essentially a mirror of the userModel listModel without all the extra complexities. property bool iAmAdmin: false - property var gain: ({}); // Keep a local list of per-avatar gain. Far faster than keeping this data on the server. + // Keep a local list of per-avatar gainSliderValueDBs. Far faster than fetching this data from the server. + // NOTE: if another script modifies the per-avatar gain, this value won't be accurate! + property var gainSliderValueDB: ({}); // This is the container for the PAL Rectangle { @@ -497,7 +499,7 @@ Rectangle { break; case 'clearLocalQMLData': ignored = {}; - gain = {}; + gainSliderValueDB = {}; break; default: console.log('Unrecognized message:', JSON.stringify(message)); diff --git a/libraries/audio/src/AudioHRTF.h b/libraries/audio/src/AudioHRTF.h index c9d053bec4..6a17a2d3cc 100644 --- a/libraries/audio/src/AudioHRTF.h +++ b/libraries/audio/src/AudioHRTF.h @@ -45,7 +45,7 @@ public: void renderSilent(int16_t* input, float* output, int index, float azimuth, float distance, float gain, int numFrames); // - // HRTF local gain adjustment + // HRTF local gain adjustment in amplitude (1.0 == unity) // void setGainAdjustment(float gain) { _gainAdjust = HRTF_GAIN * gain; }; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 00f13dff3d..98a563c4e5 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -26,6 +26,7 @@ #include "AccountManager.h" #include "AddressManager.h" #include "Assignment.h" +#include "AudioHelpers.h" #include "HifiSockAddr.h" #include "FingerprintUtils.h" @@ -961,7 +962,8 @@ void NodeList::setAvatarGain(const QUuid& nodeID, float gain) { // write the node ID to the packet setAvatarGainPacket->write(nodeID.toRfc4122()); - setAvatarGainPacket->writePrimitive((gain < 5.0f ? gain : 5.0f)); + // We need to convert the gain in dB (from the script) to an amplitude before packing it. + setAvatarGainPacket->writePrimitive(packFloatGainToByte(fastExp2f(gain / 6.0206f))); qCDebug(networking) << "Sending Set Avatar Gain packet UUID: " << uuidStringWithoutCurlyBraces(nodeID) << "Gain:" << gain; diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index d2d77a6796..0b6b7855b5 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -63,9 +63,10 @@ public slots: /**jsdoc * Sets an avatar's gain for you and you only. + * Units are Decibels (dB) * @function Users.setAvatarGain * @param {nodeID} nodeID The node or session ID of the user whose gain you want to modify. - * @param {float} gain The gain of the avatar you'd like to set. + * @param {float} gain The gain of the avatar you'd like to set. Units are dB. */ void setAvatarGain(const QUuid& nodeID, float gain); From a9226e303c666e72bdb3b1b67b7b601cbf4b4025 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 12 Jan 2017 11:18:43 -0800 Subject: [PATCH 07/11] Pull out visual changess & move them to other PR --- interface/resources/qml/controls-uit/CheckBox.qml | 1 + interface/resources/qml/hifi/LetterboxMessage.qml | 6 +++--- interface/resources/qml/hifi/NameCard.qml | 8 ++++---- interface/resources/qml/hifi/Pal.qml | 1 - 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/controls-uit/CheckBox.qml b/interface/resources/qml/controls-uit/CheckBox.qml index 09a0e04148..d3cbb87e5b 100644 --- a/interface/resources/qml/controls-uit/CheckBox.qml +++ b/interface/resources/qml/controls-uit/CheckBox.qml @@ -16,6 +16,7 @@ import "../styles-uit" Original.CheckBox { id: checkBox + HifiConstants { id: hifi } property int colorScheme: hifi.colorSchemes.light readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light diff --git a/interface/resources/qml/hifi/LetterboxMessage.qml b/interface/resources/qml/hifi/LetterboxMessage.qml index c8adcdcb74..290cff6634 100644 --- a/interface/resources/qml/hifi/LetterboxMessage.qml +++ b/interface/resources/qml/hifi/LetterboxMessage.qml @@ -15,7 +15,7 @@ import "../styles-uit" Item { property alias text: popupText.text - property real popupRadius: hifi.dimensions.borderRadius + property real radius: hifi.dimensions.borderRadius visible: false id: letterbox anchors.fill: parent @@ -23,13 +23,13 @@ Item { anchors.fill: parent color: "black" opacity: 0.5 - radius: popupRadius + radius: radius } Rectangle { width: Math.max(parent.width * 0.75, 400) height: popupText.contentHeight*1.5 anchors.centerIn: parent - radius: popupRadius + radius: radius color: "white" FiraSansSemiBold { id: popupText diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 3e8ee355c8..7892e0755e 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +import Hifi 1.0 as Hifi import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 @@ -135,10 +136,9 @@ Row { start: Qt.point(0, 0) end: Qt.point(parent.width, 0) gradient: Gradient { - GradientStop { position: 0.0; color: "#2c8e72" } - GradientStop { position: 0.9; color: "#1fc6a6" } - GradientStop { position: 0.91; color: "#ea4c5f" } - GradientStop { position: 1.0; color: "#ea4c5f" } + GradientStop { position: 0.05; color: "#00CFEF" } + GradientStop { position: 0.5; color: "#9450A5" } + GradientStop { position: 0.95; color: "#EA4C5F" } } } } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index c74d8757f7..fe0c25d803 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -451,7 +451,6 @@ Rectangle { if (selected) { table.selection.clear(); // for now, no multi-select table.selection.select(userIndex); - table.positionViewAtRow(userIndex, ListView.Visible); } else { table.selection.deselect(userIndex); } From a69a10b8e4dd687c107d7732661ba3d0734b865b Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 13 Jan 2017 13:15:01 -0800 Subject: [PATCH 08/11] Cleanup after rebase --- interface/resources/qml/controls-uit/CheckBox.qml | 1 - interface/resources/qml/hifi/LetterboxMessage.qml | 6 +++--- interface/resources/qml/hifi/NameCard.qml | 8 ++++---- interface/resources/qml/hifi/Pal.qml | 1 + 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/controls-uit/CheckBox.qml b/interface/resources/qml/controls-uit/CheckBox.qml index d3cbb87e5b..09a0e04148 100644 --- a/interface/resources/qml/controls-uit/CheckBox.qml +++ b/interface/resources/qml/controls-uit/CheckBox.qml @@ -16,7 +16,6 @@ import "../styles-uit" Original.CheckBox { id: checkBox - HifiConstants { id: hifi } property int colorScheme: hifi.colorSchemes.light readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light diff --git a/interface/resources/qml/hifi/LetterboxMessage.qml b/interface/resources/qml/hifi/LetterboxMessage.qml index 290cff6634..c8adcdcb74 100644 --- a/interface/resources/qml/hifi/LetterboxMessage.qml +++ b/interface/resources/qml/hifi/LetterboxMessage.qml @@ -15,7 +15,7 @@ import "../styles-uit" Item { property alias text: popupText.text - property real radius: hifi.dimensions.borderRadius + property real popupRadius: hifi.dimensions.borderRadius visible: false id: letterbox anchors.fill: parent @@ -23,13 +23,13 @@ Item { anchors.fill: parent color: "black" opacity: 0.5 - radius: radius + radius: popupRadius } Rectangle { width: Math.max(parent.width * 0.75, 400) height: popupText.contentHeight*1.5 anchors.centerIn: parent - radius: radius + radius: popupRadius color: "white" FiraSansSemiBold { id: popupText diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 7892e0755e..3e8ee355c8 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -9,7 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -import Hifi 1.0 as Hifi import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 @@ -136,9 +135,10 @@ Row { start: Qt.point(0, 0) end: Qt.point(parent.width, 0) gradient: Gradient { - GradientStop { position: 0.05; color: "#00CFEF" } - GradientStop { position: 0.5; color: "#9450A5" } - GradientStop { position: 0.95; color: "#EA4C5F" } + GradientStop { position: 0.0; color: "#2c8e72" } + GradientStop { position: 0.9; color: "#1fc6a6" } + GradientStop { position: 0.91; color: "#ea4c5f" } + GradientStop { position: 1.0; color: "#ea4c5f" } } } } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index fe0c25d803..c74d8757f7 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -451,6 +451,7 @@ Rectangle { if (selected) { table.selection.clear(); // for now, no multi-select table.selection.select(userIndex); + table.positionViewAtRow(userIndex, ListView.Visible); } else { table.selection.deselect(userIndex); } From 8343769352f8a94d941ce15535aab88caa914257 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 13 Jan 2017 15:25:07 -0800 Subject: [PATCH 09/11] NameCard improvements & user feedback --- interface/resources/qml/hifi/NameCard.qml | 41 +++++++++++++---------- interface/resources/qml/hifi/Pal.qml | 2 +- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 3e8ee355c8..b5bd0a88f8 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -20,16 +20,13 @@ Row { // Spacing spacing: 10 // Anchors - anchors.top: parent.top anchors { - topMargin: (parent.height - contentHeight)/2 - bottomMargin: (parent.height - contentHeight)/2 + verticalCenter: parent.verticalCenter leftMargin: 10 rightMargin: 10 } // Properties - property int contentHeight: 70 property string uuid: "" property string displayName: "" property string userName: "" @@ -42,7 +39,7 @@ Row { Column { id: avatarImage // Size - height: contentHeight + height: parent.height width: height Image { id: userImage @@ -56,9 +53,8 @@ Row { Column { id: textContainer // Size - width: parent.width - /*avatarImage.width - */parent.anchors.leftMargin - parent.anchors.rightMargin - parent.spacing - height: contentHeight - + width: parent.width - /*avatarImage.width - parent.spacing - */parent.anchors.leftMargin - parent.anchors.rightMargin + anchors.verticalCenter: parent.verticalCenter // DisplayName Text FiraSansSemiBold { id: displayNameText @@ -94,7 +90,7 @@ Row { // Spacer Item { - height: 4 + height: 3 width: parent.width } @@ -146,7 +142,7 @@ Row { // Per-Avatar Gain Slider Spacer Item { width: parent.width - height: 4 + height: 3 visible: !isMyCard } // Per-Avatar Gain Slider @@ -159,20 +155,31 @@ Row { minimumValue: -60.0 maximumValue: 20.0 stepSize: 2 - updateValueWhileDragging: false + updateValueWhileDragging: true onValueChanged: updateGainFromQML(uuid, value) + MouseArea { + anchors.fill: parent + onWheel: { + // Do nothing. + } + onDoubleClicked: { + gainSlider.value = 0.0 + } + onPressed: { + // Pass through to Slider + mouse.accepted = false + } + onReleased: { + // Pass through to Slider + mouse.accepted = false + } + } style: SliderStyle { groove: Rectangle { color: "#dbdbdb" implicitWidth: gainSlider.width implicitHeight: 4 radius: 2 - MouseArea { - anchors.fill: parent - onDoubleClicked: { - gainSlider.value = 0.0 - } - } } handle: Rectangle { anchors.centerIn: parent diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index c74d8757f7..0b093ed430 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -25,7 +25,7 @@ Rectangle { color: "#E3E3E3" // Properties property int myCardHeight: 90 - property int rowHeight: 90 + property int rowHeight: 80 property int actionButtonWidth: 75 property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 4 : 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth property var myData: ({displayName: "", userName: "", audioLevel: 0.0}) // valid dummy until set From a89868dcad7cf23c27396d861e6bdcedf3d9678f Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 13 Jan 2017 15:41:17 -0800 Subject: [PATCH 10/11] Make sliders appear only when row is selected --- interface/resources/qml/hifi/NameCard.qml | 5 +++-- interface/resources/qml/hifi/Pal.qml | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index b5bd0a88f8..10afee2e6a 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -34,6 +34,7 @@ Row { property int usernameTextHeight: 12 property real audioLevel: 0.0 property bool isMyCard: false + property bool selected: false /* User image commented out for now - will probably be re-introduced later. Column { @@ -143,12 +144,12 @@ Row { Item { width: parent.width height: 3 - visible: !isMyCard + visible: !isMyCard && selected } // Per-Avatar Gain Slider Slider { id: gainSlider - visible: !isMyCard + visible: !isMyCard && selected width: parent.width height: 18 value: pal.gainSliderValueDB[uuid] ? pal.gainSliderValueDB[uuid] : 0.0 diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 0b093ed430..052c953316 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -25,7 +25,7 @@ Rectangle { color: "#E3E3E3" // Properties property int myCardHeight: 90 - property int rowHeight: 80 + property int rowHeight: 70 property int actionButtonWidth: 75 property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 4 : 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth property var myData: ({displayName: "", userName: "", audioLevel: 0.0}) // valid dummy until set @@ -190,7 +190,7 @@ Rectangle { // This Rectangle refers to each Row in the table. rowDelegate: Rectangle { // The only way I know to specify a row height. // Size - height: rowHeight + height: rowHeight + (styleData.selected ? 20 : 0) color: styleData.selected ? hifi.colors.orangeHighlight : styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd @@ -211,6 +211,7 @@ Rectangle { audioLevel: model && model.audioLevel visible: !isCheckBox && !isButton uuid: model && model.sessionId + selected: styleData.selected // Size width: nameCardWidth height: parent.height From a5343d9aa9104e1c9117ef26d1cc1e9224e24c4d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 13 Jan 2017 17:20:29 -0800 Subject: [PATCH 11/11] Final tweaks before PR! --- interface/resources/qml/hifi/NameCard.qml | 73 ++++++++++++++++------- interface/resources/qml/hifi/Pal.qml | 2 +- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 10afee2e6a..c6daf53b9a 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -15,10 +15,8 @@ import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.0 import "../styles-uit" -Row { +Item { id: thisNameCard - // Spacing - spacing: 10 // Anchors anchors { verticalCenter: parent.verticalCenter @@ -51,10 +49,11 @@ Row { } } */ - Column { + Item { id: textContainer // Size width: parent.width - /*avatarImage.width - parent.spacing - */parent.anchors.leftMargin - parent.anchors.rightMargin + height: childrenRect.height anchors.verticalCenter: parent.verticalCenter // DisplayName Text FiraSansSemiBold { @@ -64,6 +63,8 @@ Row { elide: Text.ElideRight // Size width: parent.width + // Anchors + anchors.top: parent.top // Text Size size: thisNameCard.displayTextHeight // Text Positioning @@ -81,6 +82,8 @@ Row { visible: thisNameCard.displayName // Size width: parent.width + // Anchors + anchors.top: displayNameText.bottom // Text Size size: thisNameCard.usernameTextHeight // Text Positioning @@ -91,25 +94,56 @@ Row { // Spacer Item { - height: 3 + id: spacer + height: 4 width: parent.width + // Anchors + anchors.top: userNameText.bottom } // VU Meter - Rectangle { // CHANGEME to the appropriate type! + Rectangle { id: nameCardVUMeter // Size - width: parent.width + width: ((gainSlider.value - gainSlider.minimumValue)/(gainSlider.maximumValue - gainSlider.minimumValue)) * parent.width height: 8 + // Anchors + anchors.top: spacer.bottom // Style radius: 4 + color: "#c5c5c5" + // Rectangle for the zero-gain point on the VU meter + Rectangle { + id: vuMeterZeroGain + visible: gainSlider.visible + // Size + width: 4 + height: 18 + // Style + color: hifi.colors.darkGray + // Anchors + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: (-gainSlider.minimumValue)/(gainSlider.maximumValue - gainSlider.minimumValue) * gainSlider.width - 4 + } + // Rectangle for the VU meter line + Rectangle { + id: vuMeterLine + width: gainSlider.width + visible: gainSlider.visible + // Style + color: vuMeterBase.color + radius: nameCardVUMeter.radius + height: nameCardVUMeter.height / 2 + anchors.verticalCenter: nameCardVUMeter.verticalCenter + } // Rectangle for the VU meter base Rectangle { id: vuMeterBase // Anchors anchors.fill: parent // Style - color: "#c5c5c5" + color: parent.color radius: parent.radius } // Rectangle for the VU meter audio level @@ -118,7 +152,7 @@ Row { // Size width: (thisNameCard.audioLevel) * parent.width // Style - color: "#c5c5c5" + color: parent.color radius: parent.radius // Anchors anchors.bottom: parent.bottom @@ -140,22 +174,20 @@ Row { } } - // Per-Avatar Gain Slider Spacer - Item { - width: parent.width - height: 3 - visible: !isMyCard && selected - } // Per-Avatar Gain Slider Slider { id: gainSlider - visible: !isMyCard && selected + // Size width: parent.width - height: 18 + height: 14 + // Anchors + anchors.verticalCenter: nameCardVUMeter.verticalCenter + // Properties + visible: !isMyCard && selected value: pal.gainSliderValueDB[uuid] ? pal.gainSliderValueDB[uuid] : 0.0 minimumValue: -60.0 maximumValue: 20.0 - stepSize: 2 + stepSize: 5 updateValueWhileDragging: true onValueChanged: updateGainFromQML(uuid, value) MouseArea { @@ -177,16 +209,17 @@ Row { } style: SliderStyle { groove: Rectangle { - color: "#dbdbdb" + color: "#c5c5c5" implicitWidth: gainSlider.width implicitHeight: 4 radius: 2 + opacity: 0 } handle: Rectangle { anchors.centerIn: parent color: (control.pressed || control.hovered) ? "#00b4ef" : "#8F8F8F" implicitWidth: 10 - implicitHeight: 18 + implicitHeight: 16 } } } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 052c953316..3438baa217 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -190,7 +190,7 @@ Rectangle { // This Rectangle refers to each Row in the table. rowDelegate: Rectangle { // The only way I know to specify a row height. // Size - height: rowHeight + (styleData.selected ? 20 : 0) + height: rowHeight color: styleData.selected ? hifi.colors.orangeHighlight : styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd