mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
Merge pull request #9401 from zfox23/PAL_DisplayName
PAL: Editable Display Names & Immediate Update
This commit is contained in:
commit
7a568ed8a7
9 changed files with 138 additions and 26 deletions
|
@ -262,8 +262,12 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
// setup a PacketList for the avatarPackets
|
// setup a PacketList for the avatarPackets
|
||||||
auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData);
|
auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData);
|
||||||
|
|
||||||
if (avatar.getSessionDisplayName().isEmpty() && // We haven't set it yet...
|
if (nodeData->getAvatarSessionDisplayNameMustChange()) {
|
||||||
nodeData->getReceivedIdentity()) { // ... but we have processed identity (with possible displayName).
|
const QString& existingBaseDisplayName = nodeData->getBaseDisplayName();
|
||||||
|
if (--_sessionDisplayNames[existingBaseDisplayName].second <= 0) {
|
||||||
|
_sessionDisplayNames.remove(existingBaseDisplayName);
|
||||||
|
}
|
||||||
|
|
||||||
QString baseName = avatar.getDisplayName().trimmed();
|
QString baseName = avatar.getDisplayName().trimmed();
|
||||||
const QRegularExpression curses{ "fuck|shit|damn|cock|cunt" }; // POC. We may eventually want something much more elaborate (subscription?).
|
const QRegularExpression curses{ "fuck|shit|damn|cock|cunt" }; // POC. We may eventually want something much more elaborate (subscription?).
|
||||||
baseName = baseName.replace(curses, "*"); // Replace rather than remove, so that people have a clue that the person's a jerk.
|
baseName = baseName.replace(curses, "*"); // Replace rather than remove, so that people have a clue that the person's a jerk.
|
||||||
|
@ -276,11 +280,14 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
QPair<int, int>& soFar = _sessionDisplayNames[baseName]; // Inserts and answers 0, 0 if not already present, which is what we want.
|
QPair<int, int>& soFar = _sessionDisplayNames[baseName]; // Inserts and answers 0, 0 if not already present, which is what we want.
|
||||||
int& highWater = soFar.first;
|
int& highWater = soFar.first;
|
||||||
nodeData->setBaseDisplayName(baseName);
|
nodeData->setBaseDisplayName(baseName);
|
||||||
avatar.setSessionDisplayName((highWater > 0) ? baseName + "_" + QString::number(highWater) : baseName);
|
QString sessionDisplayName = (highWater > 0) ? baseName + "_" + QString::number(highWater) : baseName;
|
||||||
|
avatar.setSessionDisplayName(sessionDisplayName);
|
||||||
highWater++;
|
highWater++;
|
||||||
soFar.second++; // refcount
|
soFar.second++; // refcount
|
||||||
nodeData->flagIdentityChange();
|
nodeData->flagIdentityChange();
|
||||||
sendIdentityPacket(nodeData, node); // Tell new node about its sessionUUID. Others will find out below.
|
nodeData->setAvatarSessionDisplayNameMustChange(false);
|
||||||
|
sendIdentityPacket(nodeData, node); // Tell node whose name changed about its new session display name. Others will find out below.
|
||||||
|
qDebug() << "Giving session display name" << sessionDisplayName << "to node with ID" << node->getUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is an AGENT we have received head data from
|
// this is an AGENT we have received head data from
|
||||||
|
@ -584,7 +591,7 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
|
||||||
if (avatar.processAvatarIdentity(identity)) {
|
if (avatar.processAvatarIdentity(identity)) {
|
||||||
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
||||||
nodeData->flagIdentityChange();
|
nodeData->flagIdentityChange();
|
||||||
nodeData->setReceivedIdentity();
|
nodeData->setAvatarSessionDisplayNameMustChange(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,8 +53,8 @@ public:
|
||||||
|
|
||||||
HRCTime getIdentityChangeTimestamp() const { return _identityChangeTimestamp; }
|
HRCTime getIdentityChangeTimestamp() const { return _identityChangeTimestamp; }
|
||||||
void flagIdentityChange() { _identityChangeTimestamp = p_high_resolution_clock::now(); }
|
void flagIdentityChange() { _identityChangeTimestamp = p_high_resolution_clock::now(); }
|
||||||
bool getReceivedIdentity() const { return _gotIdentity; }
|
bool getAvatarSessionDisplayNameMustChange() const { return _avatarSessionDisplayNameMustChange; }
|
||||||
void setReceivedIdentity() { _gotIdentity = true; }
|
void setAvatarSessionDisplayNameMustChange(bool set = true) { _avatarSessionDisplayNameMustChange = set; }
|
||||||
|
|
||||||
void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; }
|
void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; }
|
||||||
float getFullRateDistance() const { return _fullRateDistance; }
|
float getFullRateDistance() const { return _fullRateDistance; }
|
||||||
|
@ -112,7 +112,7 @@ private:
|
||||||
std::unordered_set<QUuid> _hasReceivedFirstPacketsFrom;
|
std::unordered_set<QUuid> _hasReceivedFirstPacketsFrom;
|
||||||
|
|
||||||
HRCTime _identityChangeTimestamp;
|
HRCTime _identityChangeTimestamp;
|
||||||
bool _gotIdentity { false };
|
bool _avatarSessionDisplayNameMustChange{ false };
|
||||||
|
|
||||||
float _fullRateDistance = FLT_MAX;
|
float _fullRateDistance = FLT_MAX;
|
||||||
float _maxAvatarDistance = FLT_MAX;
|
float _maxAvatarDistance = FLT_MAX;
|
||||||
|
|
Binary file not shown.
|
@ -28,7 +28,7 @@ Item {
|
||||||
property string uuid: ""
|
property string uuid: ""
|
||||||
property string displayName: ""
|
property string displayName: ""
|
||||||
property string userName: ""
|
property string userName: ""
|
||||||
property int displayTextHeight: 18
|
property real displayNameTextPixelSize: 18
|
||||||
property int usernameTextHeight: 12
|
property int usernameTextHeight: 12
|
||||||
property real audioLevel: 0.0
|
property real audioLevel: 0.0
|
||||||
property bool isMyCard: false
|
property bool isMyCard: false
|
||||||
|
@ -55,18 +55,112 @@ Item {
|
||||||
width: parent.width - /*avatarImage.width - parent.spacing - */parent.anchors.leftMargin - parent.anchors.rightMargin
|
width: parent.width - /*avatarImage.width - parent.spacing - */parent.anchors.leftMargin - parent.anchors.rightMargin
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
// DisplayName Text
|
|
||||||
|
// DisplayName field for my card
|
||||||
|
Rectangle {
|
||||||
|
id: myDisplayName
|
||||||
|
visible: isMyCard
|
||||||
|
// Size
|
||||||
|
width: parent.width + 70
|
||||||
|
height: 35
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: -10
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.textFieldLightBackground
|
||||||
|
border.color: hifi.colors.blueHighlight
|
||||||
|
border.width: 0
|
||||||
|
TextInput {
|
||||||
|
id: myDisplayNameText
|
||||||
|
// Properties
|
||||||
|
text: thisNameCard.displayName
|
||||||
|
maximumLength: 256
|
||||||
|
clip: true
|
||||||
|
// Size
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
// Anchors
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: editGlyph.width + editGlyph.anchors.rightMargin
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.darkGray
|
||||||
|
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||||
|
font.family: firaSansSemiBold.name
|
||||||
|
font.pixelSize: displayNameTextPixelSize
|
||||||
|
selectionColor: hifi.colors.blueHighlight
|
||||||
|
selectedTextColor: "black"
|
||||||
|
// Text Positioning
|
||||||
|
verticalAlignment: TextInput.AlignVCenter
|
||||||
|
horizontalAlignment: TextInput.AlignLeft
|
||||||
|
// Signals
|
||||||
|
onEditingFinished: {
|
||||||
|
pal.sendToScript({method: 'displayNameUpdate', params: text})
|
||||||
|
cursorPosition = 0
|
||||||
|
focus = false
|
||||||
|
myDisplayName.border.width = 0
|
||||||
|
color = hifi.colors.darkGray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: {
|
||||||
|
myDisplayName.border.width = 1
|
||||||
|
myDisplayNameText.focus ? myDisplayNameText.cursorPosition = myDisplayNameText.positionAt(mouseX, mouseY, TextInput.CursorOnCharacter) : myDisplayNameText.selectAll();
|
||||||
|
myDisplayNameText.focus = true
|
||||||
|
myDisplayNameText.color = "black"
|
||||||
|
}
|
||||||
|
onDoubleClicked: {
|
||||||
|
myDisplayNameText.selectAll();
|
||||||
|
myDisplayNameText.focus = true;
|
||||||
|
}
|
||||||
|
onEntered: myDisplayName.color = hifi.colors.lightGrayText
|
||||||
|
onExited: myDisplayName.color = hifi.colors.textFieldLightBackground
|
||||||
|
}
|
||||||
|
// Edit pencil glyph
|
||||||
|
HiFiGlyphs {
|
||||||
|
id: editGlyph
|
||||||
|
text: hifi.glyphs.editPencil
|
||||||
|
// Text Size
|
||||||
|
size: displayNameTextPixelSize*1.5
|
||||||
|
// Anchors
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
// Style
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
color: hifi.colors.baseGray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Spacer for DisplayName for my card
|
||||||
|
Rectangle {
|
||||||
|
id: myDisplayNameSpacer
|
||||||
|
width: myDisplayName.width
|
||||||
|
// Anchors
|
||||||
|
anchors.top: myDisplayName.bottom
|
||||||
|
height: 5
|
||||||
|
visible: isMyCard
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
// DisplayName Text for others' cards
|
||||||
FiraSansSemiBold {
|
FiraSansSemiBold {
|
||||||
id: displayNameText
|
id: displayNameText
|
||||||
// Properties
|
// Properties
|
||||||
text: thisNameCard.displayName
|
text: thisNameCard.displayName
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
visible: !isMyCard
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: parent.width
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
// Text Size
|
// Text Size
|
||||||
size: thisNameCard.displayTextHeight
|
size: displayNameTextPixelSize
|
||||||
// Text Positioning
|
// Text Positioning
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
// Style
|
// Style
|
||||||
|
@ -83,7 +177,7 @@ Item {
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: parent.width
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: displayNameText.bottom
|
anchors.top: isMyCard ? myDisplayNameSpacer.bottom : displayNameText.bottom
|
||||||
// Text Size
|
// Text Size
|
||||||
size: thisNameCard.usernameTextHeight
|
size: thisNameCard.usernameTextHeight
|
||||||
// Text Positioning
|
// Text Positioning
|
||||||
|
@ -105,7 +199,7 @@ Item {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: nameCardVUMeter
|
id: nameCardVUMeter
|
||||||
// Size
|
// Size
|
||||||
width: ((gainSlider.value - gainSlider.minimumValue)/(gainSlider.maximumValue - gainSlider.minimumValue)) * parent.width
|
width: isMyCard ? myDisplayName.width - 20 : ((gainSlider.value - gainSlider.minimumValue)/(gainSlider.maximumValue - gainSlider.minimumValue)) * parent.width
|
||||||
height: 8
|
height: 8
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: spacer.bottom
|
anchors.top: spacer.bottom
|
||||||
|
|
|
@ -35,6 +35,17 @@ Rectangle {
|
||||||
// Keep a local list of per-avatar gainSliderValueDBs. Far faster than fetching this data from 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!
|
// NOTE: if another script modifies the per-avatar gain, this value won't be accurate!
|
||||||
property var gainSliderValueDB: ({});
|
property var gainSliderValueDB: ({});
|
||||||
|
|
||||||
|
// The letterbox used for popup messages
|
||||||
|
LetterboxMessage {
|
||||||
|
id: letterboxMessage
|
||||||
|
z: 999 // Force the popup on top of everything else
|
||||||
|
}
|
||||||
|
function letterbox(message) {
|
||||||
|
letterboxMessage.text = message
|
||||||
|
letterboxMessage.visible = true
|
||||||
|
letterboxMessage.popupRadius = 0
|
||||||
|
}
|
||||||
|
|
||||||
// This is the container for the PAL
|
// This is the container for the PAL
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -176,8 +187,6 @@ Rectangle {
|
||||||
TableViewColumn {
|
TableViewColumn {
|
||||||
visible: iAmAdmin
|
visible: iAmAdmin
|
||||||
role: "kick"
|
role: "kick"
|
||||||
// The hacky spaces used to center text over the button, since I don't know how to apply a margin
|
|
||||||
// to column header text.
|
|
||||||
title: "BAN"
|
title: "BAN"
|
||||||
width: actionButtonWidth
|
width: actionButtonWidth
|
||||||
movable: false
|
movable: false
|
||||||
|
@ -337,11 +346,6 @@ Rectangle {
|
||||||
visible: iAmAdmin
|
visible: iAmAdmin
|
||||||
color: hifi.colors.lightGrayText
|
color: hifi.colors.lightGrayText
|
||||||
}
|
}
|
||||||
function letterbox(message) {
|
|
||||||
letterboxMessage.text = message;
|
|
||||||
letterboxMessage.visible = true
|
|
||||||
|
|
||||||
}
|
|
||||||
// This Rectangle refers to the [?] popup button next to "NAMES"
|
// This Rectangle refers to the [?] popup button next to "NAMES"
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: hifi.colors.tableBackgroundLight
|
color: hifi.colors.tableBackgroundLight
|
||||||
|
@ -402,9 +406,6 @@ Rectangle {
|
||||||
onExited: adminHelpText.color = hifi.colors.redHighlight
|
onExited: adminHelpText.color = hifi.colors.redHighlight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LetterboxMessage {
|
|
||||||
id: letterboxMessage
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
||||||
|
|
|
@ -312,10 +312,11 @@ Item {
|
||||||
readonly property string error: "="
|
readonly property string error: "="
|
||||||
readonly property string settings: "@"
|
readonly property string settings: "@"
|
||||||
readonly property string trash: "{"
|
readonly property string trash: "{"
|
||||||
readonly property string objectGroup: ""
|
readonly property string objectGroup: "\ue000"
|
||||||
readonly property string cm: "}"
|
readonly property string cm: "}"
|
||||||
readonly property string msvg79: "~"
|
readonly property string msvg79: "~"
|
||||||
readonly property string deg: "\\"
|
readonly property string deg: "\\"
|
||||||
readonly property string px: "|"
|
readonly property string px: "|"
|
||||||
|
readonly property string editPencil: "\ue00d"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1047,7 +1047,7 @@ bool AvatarData::processAvatarIdentity(const Identity& identity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (identity.displayName != _displayName) {
|
if (identity.displayName != _displayName) {
|
||||||
setDisplayName(identity.displayName);
|
_displayName = identity.displayName;
|
||||||
hasIdentityChanged = true;
|
hasIdentityChanged = true;
|
||||||
}
|
}
|
||||||
maybeUpdateSessionDisplayNameFromTransport(identity.sessionDisplayName);
|
maybeUpdateSessionDisplayNameFromTransport(identity.sessionDisplayName);
|
||||||
|
@ -1094,6 +1094,9 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
|
|
||||||
void AvatarData::setDisplayName(const QString& displayName) {
|
void AvatarData::setDisplayName(const QString& displayName) {
|
||||||
_displayName = displayName;
|
_displayName = displayName;
|
||||||
|
_sessionDisplayName = "";
|
||||||
|
|
||||||
|
sendIdentityPacket();
|
||||||
|
|
||||||
qCDebug(avatars) << "Changing display name for avatar to" << displayName;
|
qCDebug(avatars) << "Changing display name for avatar to" << displayName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,7 +211,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
|
||||||
HandControllerJoints,
|
HandControllerJoints,
|
||||||
HasKillAvatarReason,
|
HasKillAvatarReason,
|
||||||
SessionDisplayName,
|
SessionDisplayName,
|
||||||
Unignore
|
Unignore,
|
||||||
|
ImmediateSessionDisplayNameUpdates
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DomainConnectRequestVersion : PacketVersion {
|
enum class DomainConnectRequestVersion : PacketVersion {
|
||||||
|
|
|
@ -237,6 +237,11 @@ pal.fromQml.connect(function (message) { // messages are {method, params}, like
|
||||||
data = message.params;
|
data = message.params;
|
||||||
Users.setAvatarGain(data['sessionId'], data['gain']);
|
Users.setAvatarGain(data['sessionId'], data['gain']);
|
||||||
break;
|
break;
|
||||||
|
case 'displayNameUpdate':
|
||||||
|
if (MyAvatar.displayName != message.params) {
|
||||||
|
MyAvatar.displayName = message.params;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
print('Unrecognized message from Pal.qml:', JSON.stringify(message));
|
print('Unrecognized message from Pal.qml:', JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue