mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:24:00 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into blue
This commit is contained in:
commit
7a4ec35b99
8 changed files with 106 additions and 85 deletions
|
@ -384,18 +384,20 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) {
|
|||
if (includeThisAvatar) {
|
||||
numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122());
|
||||
numAvatarDataBytes += avatarPacketList->write(bytes);
|
||||
_stats.numOthersIncluded++;
|
||||
|
||||
// increment the number of avatars sent to this reciever
|
||||
nodeData->incrementNumAvatarsSentLastFrame();
|
||||
if (detail != AvatarData::NoData) {
|
||||
_stats.numOthersIncluded++;
|
||||
|
||||
// set the last sent sequence number for this sender on the receiver
|
||||
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
|
||||
otherNodeData->getLastReceivedSequenceNumber());
|
||||
// increment the number of avatars sent to this reciever
|
||||
nodeData->incrementNumAvatarsSentLastFrame();
|
||||
|
||||
// remember the last time we sent details about this other node to the receiver
|
||||
nodeData->setLastBroadcastTime(otherNode->getUUID(), start);
|
||||
// set the last sent sequence number for this sender on the receiver
|
||||
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
|
||||
otherNodeData->getLastReceivedSequenceNumber());
|
||||
|
||||
// remember the last time we sent details about this other node to the receiver
|
||||
nodeData->setLastBroadcastTime(otherNode->getUUID(), start);
|
||||
}
|
||||
}
|
||||
|
||||
avatarPacketList->endSegment();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import Qt.labs.settings 1.0
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
||||
|
@ -29,7 +30,9 @@ Rectangle {
|
|||
property int myCardHeight: 90
|
||||
property int rowHeight: 70
|
||||
property int actionButtonWidth: 55
|
||||
property int nameCardWidth: palContainer.width - actionButtonWidth*(iAmAdmin ? 4 : 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth
|
||||
property int actionButtonAllowance: actionButtonWidth * 2
|
||||
property int minNameCardWidth: palContainer.width - (actionButtonAllowance * 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth
|
||||
property int nameCardWidth: minNameCardWidth + (iAmAdmin ? 0 : actionButtonAllowance)
|
||||
property var myData: ({displayName: "", userName: "", audioLevel: 0.0, admin: true}) // valid dummy until set
|
||||
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.
|
||||
|
@ -52,6 +55,16 @@ Rectangle {
|
|||
letterboxMessage.visible = true
|
||||
letterboxMessage.popupRadius = 0
|
||||
}
|
||||
Settings {
|
||||
id: settings
|
||||
category: "pal"
|
||||
property bool filtered: false
|
||||
property int nearDistance: 30
|
||||
}
|
||||
function refreshWithFilter() {
|
||||
// We should just be able to set settings.filtered to filter.checked, but see #3249, so send to .js for saving.
|
||||
pal.sendToScript({method: 'refresh', params: {filter: filter.checked && {distance: settings.nearDistance}}});
|
||||
}
|
||||
|
||||
// This is the container for the PAL
|
||||
Rectangle {
|
||||
|
@ -88,11 +101,32 @@ Rectangle {
|
|||
audioLevel: myData.audioLevel
|
||||
isMyCard: true
|
||||
// Size
|
||||
width: nameCardWidth
|
||||
width: minNameCardWidth
|
||||
height: parent.height
|
||||
// Anchors
|
||||
anchors.left: parent.left
|
||||
}
|
||||
Row {
|
||||
HifiControls.CheckBox {
|
||||
id: filter
|
||||
checked: settings.filtered
|
||||
text: "in view"
|
||||
boxSize: reload.height * 0.70
|
||||
onCheckedChanged: refreshWithFilter()
|
||||
}
|
||||
HifiControls.GlyphButton {
|
||||
id: reload
|
||||
glyph: hifi.glyphs.reload
|
||||
width: reload.height
|
||||
onClicked: refreshWithFilter()
|
||||
}
|
||||
spacing: 50
|
||||
anchors {
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
topMargin: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
// Rectangles used to cover up rounded edges on bottom of MyInfo Rectangle
|
||||
Rectangle {
|
||||
|
@ -306,45 +340,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Refresh button
|
||||
Rectangle {
|
||||
// Size
|
||||
width: hifi.dimensions.tableHeaderHeight-1
|
||||
height: hifi.dimensions.tableHeaderHeight-1
|
||||
// Anchors
|
||||
anchors.left: table.left
|
||||
anchors.leftMargin: 4
|
||||
anchors.top: table.top
|
||||
// Style
|
||||
color: hifi.colors.tableBackgroundLight
|
||||
// Actual refresh icon
|
||||
HiFiGlyphs {
|
||||
id: reloadButton
|
||||
text: hifi.glyphs.reloadSmall
|
||||
// Size
|
||||
size: parent.width*1.5
|
||||
// Anchors
|
||||
anchors.fill: parent
|
||||
// Style
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: hifi.colors.darkGray
|
||||
}
|
||||
MouseArea {
|
||||
id: reloadButtonArea
|
||||
// Anchors
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
// Everyone likes a responsive refresh button!
|
||||
// So use onPressed instead of onClicked
|
||||
onPressed: {
|
||||
reloadButton.color = hifi.colors.lightGrayText
|
||||
pal.sendToScript({method: 'refresh'})
|
||||
}
|
||||
onReleased: reloadButton.color = (containsMouse ? hifi.colors.baseGrayHighlight : hifi.colors.darkGray)
|
||||
onEntered: reloadButton.color = hifi.colors.baseGrayHighlight
|
||||
onExited: reloadButton.color = (pressed ? hifi.colors.lightGrayText: hifi.colors.darkGray)
|
||||
}
|
||||
}
|
||||
|
||||
// Separator between user and admin functions
|
||||
Rectangle {
|
||||
// Size
|
||||
|
@ -501,7 +497,7 @@ Rectangle {
|
|||
if (alreadyRefreshed === true) {
|
||||
letterbox('', '', 'The last editor of this object is either you or not among this list of users.');
|
||||
} else {
|
||||
pal.sendToScript({method: 'refresh', params: message.params});
|
||||
pal.sendToScript({method: 'refresh', params: {selected: message.params}});
|
||||
}
|
||||
} else {
|
||||
// If we've already refreshed the PAL and found the avatar in the model
|
||||
|
|
|
@ -192,6 +192,8 @@ QVariantMap Camera::getViewFrustum() {
|
|||
result["orientation"].setValue(frustum.getOrientation());
|
||||
result["projection"].setValue(frustum.getProjection());
|
||||
result["centerRadius"].setValue(frustum.getCenterRadius());
|
||||
result["fieldOfView"].setValue(frustum.getFieldOfView());
|
||||
result["aspectRatio"].setValue(frustum.getAspectRatio());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ AvatarManager::AvatarManager(QObject* parent) :
|
|||
// immediately remove that avatar instead of waiting for the absence of packets from avatar mixer
|
||||
connect(nodeList.data(), &NodeList::ignoredNode, this, [=](const QUuid& nodeID, bool enabled) {
|
||||
if (enabled) {
|
||||
removeAvatar(nodeID);
|
||||
removeAvatar(nodeID, KillAvatarReason::AvatarIgnored);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason remo
|
|||
|
||||
void AvatarHashMap::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
|
||||
qCDebug(avatars) << "Removed avatar with UUID" << uuidStringWithoutCurlyBraces(removedAvatar->getSessionUUID())
|
||||
<< "from AvatarHashMap";
|
||||
<< "from AvatarHashMap" << removalReason;
|
||||
emit avatarRemovedEvent(removedAvatar->getSessionUUID());
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,6 @@ signals:
|
|||
private:
|
||||
bool getRequestsDomainListData();
|
||||
void setRequestsDomainListData(bool requests);
|
||||
bool _requestsDomainListData;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ var DEFAULT_SCRIPTS = [
|
|||
"system/bubble.js",
|
||||
"system/snapshot.js",
|
||||
"system/help.js",
|
||||
"system/pal.js", //"system/mod.js", // older UX, if you prefer
|
||||
"system/pal.js", // "system/mod.js", // older UX, if you prefer
|
||||
"system/goto.js",
|
||||
"system/marketplaces/marketplaces.js",
|
||||
"system/edit.js",
|
||||
|
@ -54,9 +54,6 @@ if (previousSetting === true || previousSetting === 'true') {
|
|||
previousSetting = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (Menu.menuExists(MENU_CATEGORY) && !Menu.menuItemExists(MENU_CATEGORY, MENU_ITEM)) {
|
||||
Menu.addMenuItem({
|
||||
menuName: MENU_CATEGORY,
|
||||
|
@ -78,11 +75,11 @@ function runDefaultsSeparately() {
|
|||
Script.load(DEFAULT_SCRIPTS[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// start all scripts
|
||||
if (Menu.isOptionChecked(MENU_ITEM)) {
|
||||
// we're debugging individual default scripts
|
||||
// so we load each into its own ScriptEngine instance
|
||||
debuggingDefaultScripts = true;
|
||||
runDefaultsSeparately();
|
||||
} else {
|
||||
// include all default scripts into this ScriptEngine
|
||||
|
@ -90,32 +87,14 @@ if (Menu.isOptionChecked(MENU_ITEM)) {
|
|||
}
|
||||
|
||||
function menuItemEvent(menuItem) {
|
||||
if (menuItem == MENU_ITEM) {
|
||||
|
||||
isChecked = Menu.isOptionChecked(MENU_ITEM);
|
||||
if (menuItem === MENU_ITEM) {
|
||||
var isChecked = Menu.isOptionChecked(MENU_ITEM);
|
||||
if (isChecked === true) {
|
||||
Settings.setValue(SETTINGS_KEY, true);
|
||||
} else if (isChecked === false) {
|
||||
Settings.setValue(SETTINGS_KEY, false);
|
||||
}
|
||||
Window.alert('You must reload all scripts for this to take effect.')
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function stopLoadedScripts() {
|
||||
// remove debug script loads
|
||||
var runningScripts = ScriptDiscoveryService.getRunning();
|
||||
for (var i in runningScripts) {
|
||||
var scriptName = runningScripts[i].name;
|
||||
for (var j in DEFAULT_SCRIPTS) {
|
||||
if (DEFAULT_SCRIPTS[j].slice(-scriptName.length) === scriptName) {
|
||||
ScriptDiscoveryService.stopScript(runningScripts[i].url);
|
||||
}
|
||||
}
|
||||
Menu.triggerOption("Reload All Scripts");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +105,6 @@ function removeMenuItem() {
|
|||
}
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
stopLoadedScripts();
|
||||
removeMenuItem();
|
||||
});
|
||||
|
||||
|
|
|
@ -37,6 +37,15 @@ var conserveResources = true;
|
|||
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
|
||||
function projectVectorOntoPlane(normalizedVector, planeNormal) {
|
||||
return Vec3.cross(planeNormal, Vec3.cross(normalizedVector, planeNormal));
|
||||
}
|
||||
function angleBetweenVectorsInPlane(from, to, normal) {
|
||||
var projectedFrom = projectVectorOntoPlane(from, normal);
|
||||
var projectedTo = projectVectorOntoPlane(to, normal);
|
||||
return Vec3.orientedAngle(projectedFrom, projectedTo, normal);
|
||||
}
|
||||
|
||||
//
|
||||
// Overlays.
|
||||
//
|
||||
|
@ -230,7 +239,11 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
|
|||
break;
|
||||
case 'refresh':
|
||||
removeOverlays();
|
||||
populateUserList(message.params);
|
||||
// If filter is specified from .qml instead of through settings, update the settings.
|
||||
if (message.params.filter !== undefined) {
|
||||
Settings.setValue('pal/filtered', !!message.params.filter);
|
||||
}
|
||||
populateUserList(message.params.selected);
|
||||
UserActivityLogger.palAction("refresh", "");
|
||||
break;
|
||||
case 'updateGain':
|
||||
|
@ -272,13 +285,42 @@ function addAvatarNode(id) {
|
|||
color: color(selected, false, 0.0),
|
||||
ignoreRayIntersection: false}, selected, !conserveResources);
|
||||
}
|
||||
// Each open/refresh will capture a stable set of avatarsOfInterest, within the specified filter.
|
||||
var avatarsOfInterest = {};
|
||||
function populateUserList(selectData) {
|
||||
var filter = Settings.getValue('pal/filtered') && {distance: Settings.getValue('pal/nearDistance')};
|
||||
var data = [], avatars = AvatarList.getAvatarIdentifiers();
|
||||
conserveResources = avatars.length > 20;
|
||||
avatarsOfInterest = {};
|
||||
var myPosition = filter && Camera.position,
|
||||
frustum = filter && Camera.frustum,
|
||||
verticalHalfAngle = filter && (frustum.fieldOfView / 2),
|
||||
horizontalHalfAngle = filter && (verticalHalfAngle * frustum.aspectRatio),
|
||||
orientation = filter && Camera.orientation,
|
||||
front = filter && Quat.getFront(orientation),
|
||||
verticalAngleNormal = filter && Quat.getRight(orientation),
|
||||
horizontalAngleNormal = filter && Quat.getUp(orientation);
|
||||
avatars.forEach(function (id) { // sorting the identifiers is just an aid for debugging
|
||||
var avatar = AvatarList.getAvatar(id);
|
||||
var name = avatar.sessionDisplayName;
|
||||
if (!name) {
|
||||
// Either we got a data packet but no identity yet, or something is really messed up. In any case,
|
||||
// we won't be able to do anything with this user, so don't include them.
|
||||
// In normal circumstances, a refresh will bring in the new user, but if we're very heavily loaded,
|
||||
// we could be losing and gaining people randomly.
|
||||
print('No avatar identity data for', id);
|
||||
return;
|
||||
}
|
||||
if (id && myPosition && (Vec3.distance(avatar.position, myPosition) > filter.distance)) {
|
||||
return;
|
||||
}
|
||||
var normal = id && filter && Vec3.normalize(Vec3.subtract(avatar.position, myPosition));
|
||||
var horizontal = normal && angleBetweenVectorsInPlane(normal, front, horizontalAngleNormal);
|
||||
var vertical = normal && angleBetweenVectorsInPlane(normal, front, verticalAngleNormal);
|
||||
if (id && filter && ((Math.abs(horizontal) > horizontalHalfAngle) || (Math.abs(vertical) > verticalHalfAngle))) {
|
||||
return;
|
||||
}
|
||||
var avatarPalDatum = {
|
||||
displayName: avatar.sessionDisplayName,
|
||||
displayName: name,
|
||||
userName: '',
|
||||
sessionId: id || '',
|
||||
audioLevel: 0.0,
|
||||
|
@ -290,10 +332,12 @@ function populateUserList(selectData) {
|
|||
addAvatarNode(id); // No overlay for ourselves
|
||||
// Everyone needs to see admin status. Username and fingerprint returns default constructor output if the requesting user isn't an admin.
|
||||
Users.requestUsernameFromID(id);
|
||||
avatarsOfInterest[id] = true;
|
||||
}
|
||||
data.push(avatarPalDatum);
|
||||
print('PAL data:', JSON.stringify(avatarPalDatum));
|
||||
});
|
||||
conserveResources = Object.keys(avatarsOfInterest).length > 20;
|
||||
sendToQml({ method: 'users', params: data });
|
||||
if (selectData) {
|
||||
selectData[2] = true;
|
||||
|
@ -318,8 +362,8 @@ var pingPong = true;
|
|||
function updateOverlays() {
|
||||
var eye = Camera.position;
|
||||
AvatarList.getAvatarIdentifiers().forEach(function (id) {
|
||||
if (!id) {
|
||||
return; // don't update ourself
|
||||
if (!id || !avatarsOfInterest[id]) {
|
||||
return; // don't update ourself, or avatars we're not interested in
|
||||
}
|
||||
var avatar = AvatarList.getAvatar(id);
|
||||
if (!avatar) {
|
||||
|
|
Loading…
Reference in a new issue