mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 04:08:13 +02:00
Merge pull request #9319 from howard-stearns/edit-button-to-select-in-pal
Edit button to select in pal
This commit is contained in:
commit
36c99a604b
7 changed files with 128 additions and 103 deletions
Binary file not shown.
52
interface/resources/qml/hifi/LetterboxMessage.qml
Normal file
52
interface/resources/qml/hifi/LetterboxMessage.qml
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
//
|
||||||
|
// LetterboxMessage.qml
|
||||||
|
// qml/hifi
|
||||||
|
//
|
||||||
|
// Created by Zach Fox and Howard Stearns on 1/5/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
|
||||||
|
//
|
||||||
|
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import "../styles-uit"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property alias text: popupText.text
|
||||||
|
property real radius: hifi.dimensions.borderRadius
|
||||||
|
visible: false
|
||||||
|
id: letterbox
|
||||||
|
anchors.fill: parent
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: "black"
|
||||||
|
opacity: 0.5
|
||||||
|
radius: radius
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
width: Math.max(parent.width * 0.75, 400)
|
||||||
|
height: popupText.contentHeight*1.5
|
||||||
|
anchors.centerIn: parent
|
||||||
|
radius: radius
|
||||||
|
color: "white"
|
||||||
|
FiraSansSemiBold {
|
||||||
|
id: popupText
|
||||||
|
size: hifi.fontSizes.textFieldInput
|
||||||
|
color: hifi.colors.darkGray
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: 15
|
||||||
|
anchors.rightMargin: 15
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onClicked: {
|
||||||
|
letterbox.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,21 +11,6 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
|
|
||||||
prototype:
|
|
||||||
- only show kick/mute when canKick
|
|
||||||
- margins everywhere
|
|
||||||
- column head centering
|
|
||||||
- column head font
|
|
||||||
- proper button .svg on toolbar
|
|
||||||
|
|
||||||
mvp:
|
|
||||||
- Show all participants, including ignored, and populate initial ignore/mute status.
|
|
||||||
- If name is elided, hover should scroll name left so the full name can be read.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
import "../styles-uit"
|
import "../styles-uit"
|
||||||
|
@ -326,6 +311,11 @@ Item {
|
||||||
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
|
||||||
|
@ -349,7 +339,9 @@ Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onClicked: namesPopup.visible = true
|
onClicked: letterbox("Bold names in the list are Avatar Display Names.\n" +
|
||||||
|
"If a Display Name isn't set, a unique Session Display Name is assigned." +
|
||||||
|
"\n\nAdministrators of this domain can also see the Username or Machine ID associated with each avatar present.")
|
||||||
onEntered: helpText.color = hifi.colors.baseGrayHighlight
|
onEntered: helpText.color = hifi.colors.baseGrayHighlight
|
||||||
onExited: helpText.color = hifi.colors.darkGray
|
onExited: helpText.color = hifi.colors.darkGray
|
||||||
}
|
}
|
||||||
|
@ -378,87 +370,14 @@ Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onClicked: adminPopup.visible = true
|
onClicked: letterbox('Silencing a user mutes their microphone. Silenced users can unmute themselves by clicking the "UNMUTE" button on their HUD.\n\n' +
|
||||||
|
"Banning a user will remove them from this domain and prevent them from returning. You can un-ban users from your domain's settings page.)")
|
||||||
onEntered: adminHelpText.color = "#94132e"
|
onEntered: adminHelpText.color = "#94132e"
|
||||||
onExited: adminHelpText.color = hifi.colors.redHighlight
|
onExited: adminHelpText.color = hifi.colors.redHighlight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Explanitory popup upon clicking "[?]" next to "NAMES"
|
LetterboxMessage {
|
||||||
Item {
|
id: letterboxMessage
|
||||||
visible: false
|
|
||||||
id: namesPopup
|
|
||||||
anchors.fill: pal
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "black"
|
|
||||||
opacity: 0.5
|
|
||||||
radius: hifi.dimensions.borderRadius
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
width: Math.max(parent.width * 0.75, 400)
|
|
||||||
height: popupText.contentHeight*1.5
|
|
||||||
anchors.centerIn: parent
|
|
||||||
radius: hifi.dimensions.borderRadius
|
|
||||||
color: "white"
|
|
||||||
FiraSansSemiBold {
|
|
||||||
id: popupText
|
|
||||||
text: "Bold names in the list are Avatar Display Names.\n" +
|
|
||||||
"If a Display Name isn't set, a unique Session Display Name is assigned." +
|
|
||||||
"\n\nAdministrators of this domain can also see the Username or Machine ID associated with each avatar present."
|
|
||||||
size: hifi.fontSizes.textFieldInput
|
|
||||||
color: hifi.colors.darkGray
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: 15
|
|
||||||
anchors.rightMargin: 15
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
onClicked: {
|
|
||||||
namesPopup.visible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Explanitory popup upon clicking "[?]" next to "ADMIN"
|
|
||||||
Item {
|
|
||||||
visible: false
|
|
||||||
id: adminPopup
|
|
||||||
anchors.fill: pal
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "black"
|
|
||||||
opacity: 0.5
|
|
||||||
radius: hifi.dimensions.borderRadius
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
width: Math.max(parent.width * 0.75, 400)
|
|
||||||
height: adminPopupText.contentHeight*1.5
|
|
||||||
anchors.centerIn: parent
|
|
||||||
radius: hifi.dimensions.borderRadius
|
|
||||||
color: "white"
|
|
||||||
FiraSansSemiBold {
|
|
||||||
id: adminPopupText
|
|
||||||
text: 'Silencing a user mutes their microphone. Silenced users can unmute themselves by clicking the "UNMUTE" button on their HUD.\n\n' +
|
|
||||||
"Banning a user will remove them from this domain and prevent them from returning. You can un-ban users from your domain's settings page."
|
|
||||||
size: hifi.fontSizes.textFieldInput
|
|
||||||
color: hifi.colors.darkGray
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: 15
|
|
||||||
anchors.rightMargin: 15
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
onClicked: {
|
|
||||||
adminPopup.visible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
||||||
|
@ -495,14 +414,20 @@ Item {
|
||||||
sortModel();
|
sortModel();
|
||||||
break;
|
break;
|
||||||
case 'select':
|
case 'select':
|
||||||
var sessionId = message.params[0];
|
var sessionIds = message.params[0];
|
||||||
var selected = message.params[1];
|
var selected = message.params[1];
|
||||||
var userIndex = findSessionIndex(sessionId);
|
var userIndex = findSessionIndex(sessionIds[0]);
|
||||||
if (selected) {
|
if (sessionIds.length > 1) {
|
||||||
table.selection.clear(); // for now, no multi-select
|
letterbox('Only one user can be selected at a time.');
|
||||||
table.selection.select(userIndex);
|
} else if (userIndex < 0) {
|
||||||
|
letterbox('The last editor is not among this list of users.');
|
||||||
} else {
|
} else {
|
||||||
table.selection.deselect(userIndex);
|
if (selected) {
|
||||||
|
table.selection.clear(); // for now, no multi-select
|
||||||
|
table.selection.select(userIndex);
|
||||||
|
} else {
|
||||||
|
table.selection.deselect(userIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Received an "updateUsername()" request from the JS
|
// Received an "updateUsername()" request from the JS
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
<input type="button" id="visible" class="glyph" value="" />
|
<input type="button" id="visible" class="glyph" value="" />
|
||||||
</div>
|
</div>
|
||||||
<input type="button" id="teleport" value="Jump To Selection" />
|
<input type="button" id="teleport" value="Jump To Selection" />
|
||||||
|
<input type="button" id="pal" class="glyph" value="" />
|
||||||
<input type="button" class="red" id="delete" value="Delete" />
|
<input type="button" class="red" id="delete" value="Delete" />
|
||||||
</div>
|
</div>
|
||||||
<div id="entity-list">
|
<div id="entity-list">
|
||||||
|
@ -94,4 +95,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -39,6 +39,7 @@ function loaded() {
|
||||||
elInView = document.getElementById("in-view")
|
elInView = document.getElementById("in-view")
|
||||||
elRadius = document.getElementById("radius");
|
elRadius = document.getElementById("radius");
|
||||||
elTeleport = document.getElementById("teleport");
|
elTeleport = document.getElementById("teleport");
|
||||||
|
elPal = document.getElementById("pal");
|
||||||
elEntityTable = document.getElementById("entity-table");
|
elEntityTable = document.getElementById("entity-table");
|
||||||
elInfoToggle = document.getElementById("info-toggle");
|
elInfoToggle = document.getElementById("info-toggle");
|
||||||
elInfoToggleGlyph = elInfoToggle.firstChild;
|
elInfoToggleGlyph = elInfoToggle.firstChild;
|
||||||
|
@ -274,6 +275,9 @@ function loaded() {
|
||||||
elTeleport.onclick = function () {
|
elTeleport.onclick = function () {
|
||||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'teleport' }));
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'teleport' }));
|
||||||
}
|
}
|
||||||
|
elPal.onclick = function () {
|
||||||
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'pal' }));
|
||||||
|
}
|
||||||
elDelete.onclick = function() {
|
elDelete.onclick = function() {
|
||||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||||
refreshEntities();
|
refreshEntities();
|
||||||
|
|
|
@ -98,7 +98,6 @@ EntityListTool = function(opts) {
|
||||||
webView.emitScriptEvent(JSON.stringify(data));
|
webView.emitScriptEvent(JSON.stringify(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
webView.webEventReceived.connect(function(data) {
|
webView.webEventReceived.connect(function(data) {
|
||||||
data = JSON.parse(data);
|
data = JSON.parse(data);
|
||||||
if (data.type == "selectionUpdate") {
|
if (data.type == "selectionUpdate") {
|
||||||
|
@ -120,6 +119,23 @@ EntityListTool = function(opts) {
|
||||||
if (selectionManager.hasSelection()) {
|
if (selectionManager.hasSelection()) {
|
||||||
MyAvatar.position = selectionManager.worldPosition;
|
MyAvatar.position = selectionManager.worldPosition;
|
||||||
}
|
}
|
||||||
|
} else if (data.type == "pal") {
|
||||||
|
var sessionIds = {}; // Collect the sessionsIds of all selected entitities, w/o duplicates.
|
||||||
|
selectionManager.selections.forEach(function (id) {
|
||||||
|
var lastEditedBy = Entities.getEntityProperties(id, 'lastEditedBy').lastEditedBy;
|
||||||
|
if (lastEditedBy) {
|
||||||
|
sessionIds[lastEditedBy] = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var dedupped = Object.keys(sessionIds);
|
||||||
|
if (!selectionManager.selections.length) {
|
||||||
|
Window.alert('No objects selected.');
|
||||||
|
} else if (!dedupped.length) {
|
||||||
|
Window.alert('There were no recent users of the ' + selectionManager.selections.length + ' selected objects.');
|
||||||
|
} else {
|
||||||
|
// No need to subscribe if we're just sending.
|
||||||
|
Messages.sendMessage('com.highfidelity.pal', JSON.stringify({method: 'select', params: [dedupped, true]}), 'local');
|
||||||
|
}
|
||||||
} else if (data.type == "delete") {
|
} else if (data.type == "delete") {
|
||||||
deleteSelectedEntities();
|
deleteSelectedEntities();
|
||||||
} else if (data.type == "toggleLocked") {
|
} else if (data.type == "toggleLocked") {
|
||||||
|
@ -140,4 +156,4 @@ EntityListTool = function(opts) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
|
|
|
@ -321,7 +321,7 @@ function removeOverlays() {
|
||||||
function handleClick(pickRay) {
|
function handleClick(pickRay) {
|
||||||
ExtendedOverlay.applyPickRay(pickRay, function (overlay) {
|
ExtendedOverlay.applyPickRay(pickRay, function (overlay) {
|
||||||
// Don't select directly. Tell qml, who will give us back a list of ids.
|
// Don't select directly. Tell qml, who will give us back a list of ids.
|
||||||
var message = {method: 'select', params: [overlay.key, !overlay.selected]};
|
var message = {method: 'select', params: [[overlay.key], !overlay.selected]};
|
||||||
pal.sendToQml(message);
|
pal.sendToQml(message);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -392,6 +392,31 @@ function onClicked() {
|
||||||
pal.setVisible(!pal.visible);
|
pal.setVisible(!pal.visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Message from other scripts, such as edit.js
|
||||||
|
//
|
||||||
|
var CHANNEL = 'com.highfidelity.pal';
|
||||||
|
function receiveMessage(channel, messageString, senderID) {
|
||||||
|
if ((channel !== CHANNEL) ||
|
||||||
|
(senderID !== MyAvatar.sessionUUID)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var message = JSON.parse(messageString);
|
||||||
|
switch (message.method) {
|
||||||
|
case 'select':
|
||||||
|
if (!pal.visible) {
|
||||||
|
onClicked();
|
||||||
|
}
|
||||||
|
pal.sendToQml(message); // Accepts objects, not just strings.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print('Unrecognized PAL message', messageString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Messages.subscribe(CHANNEL);
|
||||||
|
Messages.messageReceived.connect(receiveMessage);
|
||||||
|
|
||||||
|
|
||||||
var AVERAGING_RATIO = 0.05;
|
var AVERAGING_RATIO = 0.05;
|
||||||
var LOUDNESS_FLOOR = 11.0;
|
var LOUDNESS_FLOOR = 11.0;
|
||||||
var LOUDNESS_SCALE = 2.8 / 5.0;
|
var LOUDNESS_SCALE = 2.8 / 5.0;
|
||||||
|
@ -471,6 +496,8 @@ Script.scriptEnding.connect(function () {
|
||||||
Users.usernameFromIDReply.disconnect(usernameFromIDReply);
|
Users.usernameFromIDReply.disconnect(usernameFromIDReply);
|
||||||
Window.domainChanged.disconnect(clearIgnoredInQMLAndClosePAL);
|
Window.domainChanged.disconnect(clearIgnoredInQMLAndClosePAL);
|
||||||
Window.domainConnectionRefused.disconnect(clearIgnoredInQMLAndClosePAL);
|
Window.domainConnectionRefused.disconnect(clearIgnoredInQMLAndClosePAL);
|
||||||
|
Messages.unsubscribe(CHANNEL);
|
||||||
|
Messages.messageReceived.disconnect(receiveMessage);
|
||||||
off();
|
off();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue