Merge pull request #8232 from birarda/ignore

add a script to ignore other avatars
This commit is contained in:
Chris Collins 2016-07-13 17:10:49 -07:00 committed by GitHub
commit ff2d7addd7
25 changed files with 673 additions and 34 deletions

View file

@ -93,6 +93,7 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
this, "handleNodeAudioPacket");
packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket");
packetReceiver.registerListener(PacketType::NegotiateAudioFormat, this, "handleNegotiateAudioFormat");
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
}
@ -324,7 +325,8 @@ bool AudioMixer::prepareMixForListeningNode(Node* node) {
// loop through all other nodes that have sufficient audio to mix
DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& otherNode){
if (otherNode->getLinkedData()) {
// make sure that we have audio data for this other node and that it isn't being ignored by our listening node
if (otherNode->getLinkedData() && !node->isIgnoringNodeWithID(otherNode->getUUID())) {
AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData();
// enumerate the ARBs attached to the otherNode and add all that should be added to mix
@ -554,6 +556,10 @@ void AudioMixer::handleNodeKilled(SharedNodePointer killedNode) {
});
}
void AudioMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
sendingNode->parseIgnoreRequestMessage(packet);
}
void AudioMixer::removeHRTFsForFinishedInjector(const QUuid& streamID) {
auto injectorClientData = qobject_cast<AudioMixerClientData*>(sender());
if (injectorClientData) {

View file

@ -47,6 +47,7 @@ private slots:
void handleMuteEnvironmentPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
void handleNegotiateAudioFormat(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
void handleNodeKilled(SharedNodePointer killedNode);
void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
void removeHRTFsForFinishedInjector(const QUuid& streamID);

View file

@ -45,6 +45,7 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) :
packetReceiver.registerListener(PacketType::AvatarData, this, "handleAvatarDataPacket");
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket");
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
auto nodeList = DependencyManager::get<NodeList>();
connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &AvatarMixer::handlePacketVersionMismatch);
@ -227,14 +228,15 @@ void AvatarMixer::broadcastAvatarData() {
// send back a packet with other active node data to this node
nodeList->eachMatchingNode(
[&](const SharedNodePointer& otherNode)->bool {
if (!otherNode->getLinkedData()) {
// make sure we have data for this avatar, that it isn't the same node,
// and isn't an avatar that the viewing node has ignored
if (!otherNode->getLinkedData()
|| otherNode->getUUID() == node->getUUID()
|| node->isIgnoringNodeWithID(otherNode->getUUID())) {
return false;
} else {
return true;
}
if (otherNode->getUUID() == node->getUUID()) {
return false;
}
return true;
},
[&](const SharedNodePointer& otherNode) {
++numOtherAvatars;
@ -431,6 +433,10 @@ void AvatarMixer::handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message
DependencyManager::get<NodeList>()->processKillNode(*message);
}
void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
senderNode->parseIgnoreRequestMessage(message);
}
void AvatarMixer::sendStatsPacket() {
QJsonObject statsObject;
statsObject["average_listeners_last_second"] = (float) _sumListeners / (float) _numStatFrames;

View file

@ -37,9 +37,11 @@ private slots:
void handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message);
void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void domainSettingsRequestComplete();
void handlePacketVersionMismatch(PacketType type, const HifiSockAddr& senderSockAddr, const QUuid& senderUUID);
private:
void broadcastAvatarData();
void parseDomainServerSettings(const QJsonObject& domainSettings);

View file

@ -98,6 +98,7 @@
#include <Tooltip.h>
#include <udt/PacketHeaders.h>
#include <UserActivityLogger.h>
#include <UsersScriptingInterface.h>
#include <recording/Deck.h>
#include <recording/Recorder.h>
#include <shared/StringHelpers.h>
@ -440,6 +441,7 @@ bool setupEssentials(int& argc, char** argv) {
DependencyManager::set<FramebufferCache>();
DependencyManager::set<AnimationCache>();
DependencyManager::set<ModelBlender>();
DependencyManager::set<UsersScriptingInterface>();
DependencyManager::set<AvatarManager>();
DependencyManager::set<LODManager>();
DependencyManager::set<StandAloneJSConsole>();
@ -4755,6 +4757,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface());
scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
scriptEngine->registerGlobalObject("Users", DependencyManager::get<UsersScriptingInterface>().data());
}
bool Application::canAcceptURL(const QString& urlString) const {

View file

@ -29,6 +29,7 @@
#include <RegisteredMetaTypes.h>
#include <Rig.h>
#include <SettingHandle.h>
#include <UsersScriptingInterface.h>
#include <UUID.h>
#include "Application.h"
@ -69,10 +70,15 @@ AvatarManager::AvatarManager(QObject* parent) :
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
qRegisterMetaType<QWeakPointer<Node> >("NodeWeakPointer");
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
auto nodeList = DependencyManager::get<NodeList>();
auto& packetReceiver = nodeList->getPacketReceiver();
packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket");
packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar");
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "processAvatarIdentityPacket");
// when we hear that the user has ignored an avatar by session UUID
// immediately remove that avatar instead of waiting for the absence of packets from avatar mixer
connect(nodeList.data(), &NodeList::ignoredNode, this, &AvatarManager::removeAvatar);
}
AvatarManager::~AvatarManager() {
@ -85,7 +91,8 @@ void AvatarManager::init() {
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
}
connect(DependencyManager::get<SceneScriptingInterface>().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged, this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection);
connect(DependencyManager::get<SceneScriptingInterface>().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged,
this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection);
render::ScenePointer scene = qApp->getMain3DScene();
render::PendingChanges pendingChanges;

View file

@ -78,6 +78,9 @@ public slots:
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
void updateAvatarRenderStatus(bool shouldRenderAvatars);
private slots:
virtual void removeAvatar(const QUuid& sessionUUID) override;
private:
explicit AvatarManager(QObject* parent = 0);
explicit AvatarManager(const AvatarManager& other);
@ -88,7 +91,6 @@ private:
virtual AvatarSharedPointer newSharedAvatar() override;
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) override;
virtual void removeAvatar(const QUuid& sessionUUID) override;
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) override;
QVector<AvatarSharedPointer> _avatarFades;

View file

@ -14,7 +14,7 @@ class QmlWrapper : public QObject {
Q_OBJECT
public:
QmlWrapper(QObject* qmlObject, QObject* parent = nullptr)
: QObject(parent), _qmlObject(qmlObject) {
: QObject(parent), _qmlObject(qmlObject) {
}
Q_INVOKABLE void writeProperty(QString propertyName, QVariant propertyValue) {
@ -91,6 +91,10 @@ public:
return new ToolbarButtonProxy(rawButton, this);
}
Q_INVOKABLE void removeButton(const QVariant& name) {
QMetaObject::invokeMethod(_qmlObject, "removeButton", Qt::AutoConnection, Q_ARG(QVariant, name));
}
};
@ -112,4 +116,4 @@ QObject* ToolbarScriptingInterface::getToolbar(const QString& toolbarId) {
}
#include "ToolbarScriptingInterface.moc"
#include "ToolbarScriptingInterface.moc"

View file

@ -19,7 +19,9 @@
#include "AvatarHashMap.h"
AvatarHashMap::AvatarHashMap() {
connect(DependencyManager::get<NodeList>().data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
auto nodeList = DependencyManager::get<NodeList>();
connect(nodeList.data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
}
QVector<QUuid> AvatarHashMap::getAvatarIdentifiers() {
@ -105,7 +107,10 @@ void AvatarHashMap::processAvatarDataPacket(QSharedPointer<ReceivedMessage> mess
QByteArray byteArray = message->readWithoutCopy(message->getBytesLeftToRead());
if (sessionUUID != _lastOwnerSessionUUID) {
// make sure this isn't our own avatar data or for a previously ignored node
auto nodeList = DependencyManager::get<NodeList>();
if (sessionUUID != _lastOwnerSessionUUID && !nodeList->isIgnoringNode(sessionUUID)) {
auto avatar = newOrExistingAvatar(sessionUUID, sendingNode);
// have the matching (or new) avatar parse the data from the packet
@ -124,9 +129,13 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage>
AvatarData::Identity identity;
AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity);
// mesh URL for a UUID, find avatar in our list
auto avatar = newOrExistingAvatar(identity.uuid, sendingNode);
avatar->processAvatarIdentity(identity);
// make sure this isn't for an ignored avatar
auto nodeList = DependencyManager::get<NodeList>();
if (!nodeList->isIgnoringNode(identity.uuid)) {
// mesh URL for a UUID, find avatar in our list
auto avatar = newOrExistingAvatar(identity.uuid, sendingNode);
avatar->processAvatarIdentity(identity);
}
}
void AvatarHashMap::processKillAvatar(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {

View file

@ -19,12 +19,14 @@
#include <functional>
#include <memory>
#include <glm/glm.hpp>
#include <DependencyManager.h>
#include <NLPacket.h>
#include <Node.h>
#include "AvatarData.h"
#include <glm/glm.hpp>
class AvatarHashMap : public QObject, public Dependency {
Q_OBJECT

View file

@ -425,12 +425,8 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr<NLPacket> packet, const Node&
}
int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
QMutexLocker locker(&sendingNode->getMutex());
NodeData* linkedData = sendingNode->getLinkedData();
if (!linkedData && linkedDataCreateCallback) {
linkedDataCreateCallback(sendingNode.data());
}
NodeData* linkedData = getOrCreateLinkedData(sendingNode);
if (linkedData) {
QMutexLocker linkedDataLocker(&linkedData->getMutex());
@ -440,6 +436,17 @@ int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage
return 0;
}
NodeData* LimitedNodeList::getOrCreateLinkedData(SharedNodePointer node) {
QMutexLocker locker(&node->getMutex());
NodeData* linkedData = node->getLinkedData();
if (!linkedData && linkedDataCreateCallback) {
linkedDataCreateCallback(node.data());
}
return node->getLinkedData();
}
SharedNodePointer LimitedNodeList::nodeWithUUID(const QUuid& nodeUUID) {
QReadLocker readLocker(&_nodeMutex);

View file

@ -149,6 +149,7 @@ public:
void processKillNode(ReceivedMessage& message);
int updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer matchingNode);
NodeData* getOrCreateLinkedData(SharedNodePointer node);
unsigned int broadcastToNodes(std::unique_ptr<NLPacket> packet, const NodeSet& destinationNodeTypes);
SharedNodePointer soloNodeOfType(NodeType_t nodeType);

View file

@ -12,15 +12,17 @@
#include <cstring>
#include <stdio.h>
#include <UUID.h>
#include "Node.h"
#include "SharedUtil.h"
#include "NodePermissions.h"
#include <QtCore/QDataStream>
#include <QtCore/QDebug>
#include <UUID.h>
#include "NetworkLogging.h"
#include "NodePermissions.h"
#include "SharedUtil.h"
#include "Node.h"
const QString UNKNOWN_NodeType_t_NAME = "Unknown";
int NodePtrMetaTypeId = qRegisterMetaType<Node*>("Node*");
@ -78,6 +80,27 @@ void Node::updateClockSkewUsec(qint64 clockSkewSample) {
_clockSkewUsec = (quint64)_clockSkewMovingPercentile.getValueAtPercentile();
}
void Node::parseIgnoreRequestMessage(QSharedPointer<ReceivedMessage> message) {
while (message->getBytesLeftToRead()) {
// parse out the UUID being ignored from the packet
QUuid ignoredUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
addIgnoredNode(ignoredUUID);
}
}
void Node::addIgnoredNode(const QUuid& otherNodeID) {
if (!otherNodeID.isNull() && otherNodeID != _uuid) {
qCDebug(networking) << "Adding" << uuidStringWithoutCurlyBraces(otherNodeID) << "to ignore set for"
<< uuidStringWithoutCurlyBraces(_uuid);
// add the session UUID to the set of ignored ones for this listening node
_ignoredNodeIDSet.insert(otherNodeID);
} else {
qCWarning(networking) << "Node::addIgnoredNode called with null ID or ID of ignoring node.";
}
}
QDataStream& operator<<(QDataStream& out, const Node& node) {
out << node._type;
out << node._uuid;

View file

@ -21,6 +21,10 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QUuid>
#include <UUIDHasher.h>
#include <tbb/concurrent_unordered_set.h>
#include "HifiSockAddr.h"
#include "NetworkPeer.h"
#include "NodeData.h"
@ -66,6 +70,10 @@ public:
bool getCanRezTmp() const { return _permissions.canRezTemporaryEntities; }
bool getCanWriteToAssetServer() const { return _permissions.canWriteToAssetServer; }
void parseIgnoreRequestMessage(QSharedPointer<ReceivedMessage> message);
void addIgnoredNode(const QUuid& otherNodeID);
bool isIgnoringNodeWithID(const QUuid& nodeID) const { return _ignoredNodeIDSet.find(nodeID) != _ignoredNodeIDSet.cend(); }
friend QDataStream& operator<<(QDataStream& out, const Node& node);
friend QDataStream& operator>>(QDataStream& in, Node& node);
@ -84,6 +92,7 @@ private:
QMutex _mutex;
MovingPercentile _clockSkewMovingPercentile;
NodePermissions _permissions;
tbb::concurrent_unordered_set<QUuid, UUIDHasher> _ignoredNodeIDSet;
};
Q_DECLARE_METATYPE(Node*)

View file

@ -93,6 +93,9 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
// anytime we get a new node we will want to attempt to punch to it
connect(this, &LimitedNodeList::nodeAdded, this, &NodeList::startNodeHolePunch);
// anytime we get a new node we may need to re-send our set of ignored node IDs to it
connect(this, &LimitedNodeList::nodeActivated, this, &NodeList::maybeSendIgnoreSetToNode);
// setup our timer to send keepalive pings (it's started and stopped on domain connect/disconnect)
_keepAlivePingTimer.setInterval(KEEPALIVE_PING_INTERVAL_MS);
@ -215,6 +218,11 @@ void NodeList::reset() {
_numNoReplyDomainCheckIns = 0;
// lock and clear our set of ignored IDs
_ignoredSetLock.lockForWrite();
_ignoredNodeIDs.clear();
_ignoredSetLock.unlock();
// refresh the owner UUID to the NULL UUID
setSessionUUID(QUuid());
@ -692,3 +700,67 @@ void NodeList::sendKeepAlivePings() {
sendPacket(constructPingPacket(), *node);
});
}
void NodeList::ignoreNodeBySessionID(const QUuid& nodeID) {
// enumerate the nodes to send a reliable ignore packet to each that can leverage it
if (!nodeID.isNull() && _sessionUUID != nodeID) {
eachMatchingNode([&nodeID](const SharedNodePointer& node)->bool {
if (node->getType() == NodeType::AudioMixer || node->getType() == NodeType::AvatarMixer) {
return true;
} else {
return false;
}
}, [&nodeID, this](const SharedNodePointer& destinationNode) {
// create a reliable NLPacket with space for the ignore UUID
auto ignorePacket = NLPacket::create(PacketType::NodeIgnoreRequest, NUM_BYTES_RFC4122_UUID, true);
// write the node ID to the packet
ignorePacket->write(nodeID.toRfc4122());
qDebug() << "Sending packet to ignore node" << uuidStringWithoutCurlyBraces(nodeID);
// send off this ignore packet reliably to the matching node
sendPacket(std::move(ignorePacket), *destinationNode);
});
QReadLocker setLocker { &_ignoredSetLock };
// add this nodeID to our set of ignored IDs
_ignoredNodeIDs.insert(nodeID);
emit ignoredNode(nodeID);
} else {
qWarning() << "UsersScriptingInterface::ignore called with an invalid ID or an ID which matches the current session ID.";
}
}
bool NodeList::isIgnoringNode(const QUuid& nodeID) const {
QReadLocker setLocker { &_ignoredSetLock };
return _ignoredNodeIDs.find(nodeID) != _ignoredNodeIDs.cend();
}
void NodeList::maybeSendIgnoreSetToNode(SharedNodePointer newNode) {
if (newNode->getType() == NodeType::AudioMixer || newNode->getType() == NodeType::AvatarMixer) {
// this is a mixer that we just added - it's unlikely it knows who we were previously ignoring in this session,
// so send that list along now (assuming it isn't empty)
QReadLocker setLocker { &_ignoredSetLock };
if (_ignoredNodeIDs.size() > 0) {
// setup a packet list so we can send the stream of ignore IDs
auto ignorePacketList = NLPacketList::create(PacketType::NodeIgnoreRequest, QByteArray(), true);
// enumerate the ignored IDs and write them to the packet list
auto it = _ignoredNodeIDs.cbegin();
while (it != _ignoredNodeIDs.end()) {
ignorePacketList->write(it->toRfc4122());
++it;
}
// send this NLPacketList to the new node
sendPacketList(std::move(ignorePacketList), *newNode);
}
}
}

View file

@ -20,6 +20,8 @@
#include <unistd.h> // not on windows, not needed for mac or windows
#endif
#include <tbb/concurrent_unordered_set.h>
#include <QtCore/QElapsedTimer>
#include <QtCore/QMutex>
#include <QtCore/QSet>
@ -68,6 +70,9 @@ public:
void setIsShuttingDown(bool isShuttingDown) { _isShuttingDown = isShuttingDown; }
void ignoreNodeBySessionID(const QUuid& nodeID);
bool isIgnoringNode(const QUuid& nodeID) const;
public slots:
void reset();
void sendDomainServerCheckIn();
@ -92,6 +97,8 @@ public slots:
signals:
void limitOfSilentDomainCheckInsReached();
void receivedDomainServerList();
void ignoredNode(const QUuid& nodeID);
private slots:
void stopKeepalivePingTimer();
void sendPendingDSPathQuery();
@ -103,6 +110,8 @@ private slots:
void pingPunchForDomainServer();
void sendKeepAlivePings();
void maybeSendIgnoreSetToNode(SharedNodePointer node);
private:
NodeList() : LimitedNodeList(0, 0) { assert(false); } // Not implemented, needed for DependencyManager templates compile
@ -129,6 +138,9 @@ private:
bool _isShuttingDown { false };
QTimer _keepAlivePingTimer;
mutable QReadWriteLock _ignoredSetLock;
tbb::concurrent_unordered_set<QUuid, UUIDHasher> _ignoredNodeIDs;
#if (PR_BUILD || DEV_BUILD)
bool _shouldSendNewerVersion { false };
#endif

View file

@ -40,8 +40,6 @@ const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
<< PacketType::ICEServerHeartbeatDenied << PacketType::AssignmentClientStatus << PacketType::StopNode
<< PacketType::DomainServerRemovedNode;
const QSet<PacketType> RELIABLE_PACKETS = QSet<PacketType>();
PacketVersion versionForPacketType(PacketType packetType) {
switch (packetType) {
case PacketType::DomainList:
@ -62,6 +60,8 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::AssetUpload:
// Removal of extension from Asset requests
return 18;
case PacketType::NodeIgnoreRequest:
return 18; // Introduction of node ignore request (which replaced an unused packet tpye)
case PacketType::DomainConnectionDenied:
return static_cast<PacketVersion>(DomainConnectionDeniedVersion::IncludesReasonCode);

View file

@ -61,7 +61,7 @@ public:
AssignmentClientStatus,
NoisyMute,
AvatarIdentity,
TYPE_UNUSED_1,
NodeIgnoreRequest,
DomainConnectRequest,
DomainServerRequireDTLS,
NodeJsonStats,
@ -109,7 +109,6 @@ typedef char PacketVersion;
extern const QSet<PacketType> NON_VERIFIED_PACKETS;
extern const QSet<PacketType> NON_SOURCED_PACKETS;
extern const QSet<PacketType> RELIABLE_PACKETS;
PacketVersion versionForPacketType(PacketType packetType);
QByteArray protocolVersionsSignature(); /// returns a unqiue signature for all the current protocols

View file

@ -65,7 +65,9 @@ void PacketQueue::queuePacket(PacketPointer packet) {
}
void PacketQueue::queuePacketList(PacketListPointer packetList) {
packetList->preparePackets(getNextMessageNumber());
if (packetList->isOrdered()) {
packetList->preparePackets(getNextMessageNumber());
}
LockGuard locker(_packetsLock);
_channels.push_back(std::move(packetList->_packets));

View file

@ -0,0 +1,19 @@
//
// UsersScriptingInterface.cpp
// libraries/script-engine/src
//
// Created by Stephen Birarda on 2016-07-11.
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "UsersScriptingInterface.h"
#include <NodeList.h>
void UsersScriptingInterface::ignore(const QUuid& nodeID) {
// ask the NodeList to ignore this user (based on the session ID of their node)
DependencyManager::get<NodeList>()->ignoreNodeBySessionID(nodeID);
}

View file

@ -0,0 +1,28 @@
//
// UsersScriptingInterface.h
// libraries/script-engine/src
//
// Created by Stephen Birarda on 2016-07-11.
// Copyright 2016 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
//
#pragma once
#ifndef hifi_UsersScriptingInterface_h
#define hifi_UsersScriptingInterface_h
#include <DependencyManager.h>
class UsersScriptingInterface : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public slots:
void ignore(const QUuid& nodeID);
};
#endif // hifi_UsersScriptingInterface_h

View file

@ -17,6 +17,7 @@ Script.load("system/goto.js");
Script.load("system/hmd.js");
Script.load("system/examples.js");
Script.load("system/edit.js");
Script.load("system/ignore.js");
Script.load("system/selectAudioDevice.js");
Script.load("system/notifications.js");
Script.load("system/controllers/handControllerGrab.js");

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 23.7 34.7" style="enable-background:new 0 0 23.7 34.7;" xml:space="preserve">
<style type="text/css">
.st0{fill:#414042;}
.st1{fill:#58595B;}
.st2{fill:#EF3B4E;}
</style>
<path class="st0" d="M23,12.5c0-6.2-5-11.2-11.2-11.2c-6.2,0-11.2,5-11.2,11.2c0,5.2,3.6,9.6,8.4,10.8l3.2,10.1l2.6-10.2
C19.6,21.8,23,17.5,23,12.5z M11.9,22.2c-5.4,0-9.8-4.4-9.8-9.8c0-5.4,4.4-9.8,9.8-9.8c5.4,0,9.8,4.4,9.8,9.8
C21.6,17.9,17.3,22.2,11.9,22.2z"/>
<path class="st0" d="M12.3,33.9L9,23.4c-5-1.3-8.5-5.8-8.5-10.9c0-6.2,5.1-11.3,11.3-11.3c6.2,0,11.3,5.1,11.3,11.3
c0,5-3.3,9.4-8.1,10.8L12.3,33.9z M11.9,1.4c-6.1,0-11.1,5-11.1,11.1c0,5.1,3.4,9.5,8.3,10.7l0.1,0l0,0.1l3.1,9.7l2.5-9.9l0.1,0
c4.7-1.4,8-5.7,8-10.6C22.9,6.4,18,1.4,11.9,1.4z M11.9,22.4c-5.5,0-9.9-4.4-9.9-9.9s4.4-9.9,9.9-9.9s9.9,4.4,9.9,9.9
S17.3,22.4,11.9,22.4z M11.9,2.8c-5.3,0-9.7,4.3-9.7,9.7c0,5.3,4.3,9.7,9.7,9.7s9.7-4.3,9.7-9.7C21.5,7.1,17.2,2.8,11.9,2.8z"/>
<g>
<path class="st0" d="M16,8.3c-0.4-0.4-1.1-0.4-1.5,0L11.8,11L9,8.2c-0.4-0.4-1.1-0.4-1.5,0C7.1,8.7,7,9.4,7.5,9.8l2.7,2.7l-2.7,2.7
c-0.4,0.4-0.4,1.1,0,1.5c0.4,0.4,1.1,0.4,1.5,0l2.7-2.7l2.7,2.7c0.4,0.4,1.1,0.4,1.5,0c0.4-0.4,0.4-1.1,0-1.5l-2.7-2.7l2.7-2.7
C16.5,9.4,16.5,8.7,16,8.3z"/>
<path class="st1" d="M8.3,17.3c-0.3,0-0.6-0.1-0.9-0.4C7.2,16.7,7,16.4,7,16.1c0-0.3,0.1-0.6,0.4-0.9l2.6-2.7L7.4,9.9
c-0.5-0.5-0.5-1.2,0-1.7c0.5-0.5,1.2-0.5,1.7,0l2.7,2.7l2.6-2.7c0.2-0.2,0.5-0.4,0.9-0.4l0,0c0.3,0,0.6,0.1,0.9,0.4l0,0
c0,0,0,0,0,0l0,0c0.2,0.2,0.4,0.5,0.4,0.9c0,0.3-0.1,0.6-0.4,0.9l-2.7,2.7l2.7,2.6c0.2,0.2,0.4,0.5,0.4,0.9c0,0.3-0.1,0.6-0.4,0.9
c-0.5,0.5-1.3,0.5-1.7,0l-2.7-2.6l-2.7,2.7C8.9,17.2,8.6,17.3,8.3,17.3z M8.3,8.4C8.3,8.4,8.3,8.4,8.3,8.4C8,8.4,7.7,8.3,7.6,8.5
C7.4,8.7,7.3,8.9,7.3,9.1c0,0.3,0.1,0.5,0.3,0.6l2.8,2.8l-2.8,2.8c-0.4,0.4-0.4,1,0,1.4c0.4,0.4,1,0.4,1.4,0l2.8-2.8l2.8,2.8
c0.4,0.4,1,0.4,1.4,0c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7l-2.8-2.8L16,9.7c0.2-0.2,0.3-0.4,0.3-0.7
c0-0.3-0.1-0.5-0.3-0.7l0,0c-0.2-0.2-0.4-0.3-0.7-0.3l0,0c-0.3,0-0.5,0.1-0.7,0.3l-2.8,2.8L8.9,8.5C8.8,8.3,8.5,8.4,8.3,8.4z"/>
</g>
<g>
<path class="st2" d="M23,12c0-6.2-5-11.2-11.2-11.2C5.7,0.8,0.7,5.9,0.7,12c0,5.2,3.6,9.6,8.4,10.8L12.3,33L15,22.8
C19.6,21.4,23,17.1,23,12z M11.9,21.8c-5.4,0-9.8-4.4-9.8-9.8c0-5.4,4.4-9.8,9.8-9.8c5.4,0,9.8,4.4,9.8,9.8
C21.7,17.4,17.3,21.8,11.9,21.8z"/>
<path class="st2" d="M16.1,7.8c-0.4-0.4-1.1-0.4-1.5,0l-2.7,2.7L9,7.8c-0.4-0.4-1.1-0.4-1.5,0C7.1,8.3,7.1,9,7.5,9.4l2.7,2.7
l-2.7,2.7c-0.4,0.4-0.4,1.1,0,1.5c0.4,0.4,1.1,0.4,1.5,0l2.7-2.7l2.7,2.7c0.4,0.4,1.1,0.4,1.5,0c0.4-0.4,0.4-1.1,0-1.5l-2.7-2.7
l2.7-2.7C16.5,9,16.5,8.3,16.1,7.8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 50 200.1" style="enable-background:new 0 0 50 200.1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#414042;}
.st1{fill:#FFFFFF;}
.st2{fill:#1E1E1E;}
.st3{fill:#333333;}
</style>
<g id="Layer_2">
<g>
<g>
<path class="st0" d="M50.1,146.1c0,2.2-1.8,4-4,4h-42c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V146.1z"/>
</g>
</g>
<g>
<g>
<path class="st0" d="M50,196.1c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V196.1z"/>
</g>
</g>
<g>
<g>
<path class="st1" d="M50,46c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4V4c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V46z"/>
</g>
</g>
<g>
<path class="st2" d="M50,96.1c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V96.1z"/>
</g>
</g>
<path class="st1" d="M24.7,81.2c-6.2,0-11.2-5-11.2-11.2c0-6.2,5-11.2,11.2-11.2c6.2,0,11.2,5,11.2,11.2
C35.9,76.2,30.9,81.2,24.7,81.2z M24.7,60.3c-5.4,0-9.8,4.4-9.8,9.8c0,5.4,4.4,9.8,9.8,9.8c5.4,0,9.8-4.4,9.8-9.8
C34.5,64.6,30.1,60.3,24.7,60.3z"/>
<g>
<path class="st3" d="M7.7,42.5v-6.4h1.2v6.4H7.7z"/>
<path class="st3" d="M14.7,41.8c-0.5,0.5-1.1,0.8-1.7,0.8c-0.4,0-0.8-0.1-1.2-0.3c-0.4-0.2-0.7-0.4-0.9-0.7c-0.3-0.3-0.5-0.7-0.6-1
s-0.2-0.8-0.2-1.2c0-0.4,0.1-0.9,0.2-1.2c0.2-0.4,0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7c0.4-0.2,0.8-0.3,1.2-0.3
c0.6,0,1.1,0.1,1.5,0.4s0.7,0.6,0.9,1l-0.9,0.7c-0.2-0.3-0.4-0.6-0.6-0.7s-0.6-0.3-0.9-0.3c-0.3,0-0.5,0.1-0.7,0.2
c-0.2,0.1-0.4,0.3-0.5,0.5c-0.2,0.2-0.3,0.4-0.4,0.7c-0.1,0.3-0.1,0.5-0.1,0.8c0,0.3,0,0.6,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7
c0.2,0.2,0.4,0.3,0.6,0.5c0.2,0.1,0.5,0.2,0.7,0.2c0.6,0,1.1-0.3,1.6-0.9v-0.5h-1.3v-0.9h2.3v3.3h-1V41.8z"/>
<path class="st3" d="M18.3,38.4v4.1h-1.2v-6.4h1l3.3,4.2v-4.2h1.2v6.4h-1L18.3,38.4z"/>
<path class="st3" d="M26.8,42.5c-0.5,0-0.9-0.1-1.2-0.3s-0.7-0.4-1-0.7c-0.3-0.3-0.5-0.6-0.6-1c-0.1-0.4-0.2-0.8-0.2-1.2
c0-0.4,0.1-0.8,0.2-1.2s0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7s0.8-0.3,1.2-0.3c0.5,0,0.9,0.1,1.2,0.3s0.7,0.4,1,0.7
c0.3,0.3,0.5,0.7,0.6,1c0.1,0.4,0.2,0.8,0.2,1.2c0,0.4-0.1,0.8-0.2,1.2c-0.2,0.4-0.4,0.7-0.6,1c-0.3,0.3-0.6,0.5-1,0.7
C27.7,42.4,27.2,42.5,26.8,42.5z M25,39.3c0,0.3,0,0.5,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7c0.2,0.2,0.3,0.4,0.6,0.5s0.5,0.2,0.8,0.2
c0.3,0,0.5-0.1,0.8-0.2s0.4-0.3,0.6-0.5c0.1-0.2,0.3-0.4,0.3-0.7s0.1-0.5,0.1-0.8c0-0.3,0-0.5-0.1-0.8c-0.1-0.3-0.2-0.5-0.4-0.7
c-0.2-0.2-0.3-0.4-0.6-0.5c-0.2-0.1-0.5-0.2-0.7-0.2c-0.3,0-0.5,0.1-0.8,0.2s-0.4,0.3-0.6,0.5c-0.2,0.2-0.3,0.4-0.3,0.7
C25.1,38.8,25,39,25,39.3z"/>
<path class="st3" d="M31,42.5v-6.4h2.8c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.4-0.1,0.8-0.3,1.1c-0.2,0.3-0.5,0.6-0.8,0.7l1.5,2.4h-1.4l-1.3-2.1h-1.2v2.1H31z M32.3,39.3h1.6c0.1,0,0.2,0,0.3-0.1
c0.1-0.1,0.2-0.1,0.3-0.2c0.1-0.1,0.1-0.2,0.2-0.3s0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4s-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1-0.1-0.2-0.1-0.3-0.1h-1.5V39.3z"/>
<path class="st3" d="M41.8,41.4v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H41.8z"/>
</g>
<path class="st1" d="M27.1,79.5c-0.8,0.2-1.6,0.3-2.4,0.3c-5.4,0-9.8-4.4-9.8-9.8c0-5.4,4.4-9.8,9.8-9.8c5.4,0,9.8,4.4,9.8,9.8
c0,0.1,0,0.2,0,0.3c0.4-0.4,0.8-0.6,1.4-0.9c-0.3-5.9-5.2-10.6-11.2-10.6c-6.2,0-11.2,5-11.2,11.2c0,6.2,5,11.2,11.2,11.2
c1,0,2-0.2,3-0.4C27.5,80.4,27.3,80,27.1,79.5z"/>
<path class="st1" d="M31.2,66.5L31.2,66.5c-0.3-0.3-0.5-0.3-0.8-0.2c0,0-4,0.5-5.7,0.5c0,0-0.1,0-0.1,0c-1.7,0-5.8-0.6-5.8-0.6
c-0.3-0.1-0.6,0-0.8,0.3l-0.1,0.2c-0.1,0.2-0.1,0.4-0.1,0.7c0.1,0.2,0.2,0.4,0.4,0.5c0.7,0.3,3.3,1.2,4,1.4c0.1,0,0.4,0.1,0.4,0.6
c0,0.6-0.2,3.1-0.5,4.3c-0.3,1.2-0.8,2.7-0.8,2.7c-0.1,0.4,0.1,0.9,0.5,1l0.5,0.2c0.2,0.1,0.4,0.1,0.6,0c0.2-0.1,0.3-0.3,0.4-0.5
l1.4-4.3l1.3,4.4c0.1,0.2,0.2,0.4,0.4,0.5c0.1,0.1,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.3-0.1l0.5-0.2c0.4-0.1,0.6-0.5,0.5-0.9
c0,0-0.4-1.6-0.7-2.9c-0.2-0.8-0.3-2-0.3-2.9c0-0.6-0.1-1.1-0.1-1.5c0-0.2,0.1-0.4,0.4-0.5c0.1,0,3.7-1.3,3.7-1.3
c0.3-0.1,0.4-0.3,0.5-0.6C31.4,66.9,31.4,66.7,31.2,66.5z"/>
<circle class="st1" cx="24.7" cy="64" r="1.7"/>
<g>
<path class="st1" d="M7.7,92.3V86h1.2v6.4H7.7z"/>
<path class="st1" d="M14.7,91.6c-0.5,0.5-1.1,0.8-1.7,0.8c-0.4,0-0.8-0.1-1.2-0.3c-0.4-0.2-0.7-0.4-0.9-0.7c-0.3-0.3-0.5-0.7-0.6-1
s-0.2-0.8-0.2-1.2c0-0.4,0.1-0.9,0.2-1.2c0.2-0.4,0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7c0.4-0.2,0.8-0.3,1.2-0.3
c0.6,0,1.1,0.1,1.5,0.4s0.7,0.6,0.9,1L14.6,88c-0.2-0.3-0.4-0.6-0.6-0.7S13.4,87,13.1,87c-0.3,0-0.5,0.1-0.7,0.2
c-0.2,0.1-0.4,0.3-0.5,0.5c-0.2,0.2-0.3,0.4-0.4,0.7c-0.1,0.3-0.1,0.5-0.1,0.8c0,0.3,0,0.6,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7
c0.2,0.2,0.4,0.3,0.6,0.5c0.2,0.1,0.5,0.2,0.7,0.2c0.6,0,1.1-0.3,1.6-0.9V90h-1.3v-0.9h2.3v3.3h-1V91.6z"/>
<path class="st1" d="M18.3,88.2v4.1h-1.2V86h1l3.3,4.2V86h1.2v6.4h-1L18.3,88.2z"/>
<path class="st1" d="M26.8,92.4c-0.5,0-0.9-0.1-1.2-0.3s-0.7-0.4-1-0.7c-0.3-0.3-0.5-0.6-0.6-1c-0.1-0.4-0.2-0.8-0.2-1.2
c0-0.4,0.1-0.8,0.2-1.2s0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7s0.8-0.3,1.2-0.3c0.5,0,0.9,0.1,1.2,0.3s0.7,0.4,1,0.7
c0.3,0.3,0.5,0.7,0.6,1c0.1,0.4,0.2,0.8,0.2,1.2c0,0.4-0.1,0.8-0.2,1.2c-0.2,0.4-0.4,0.7-0.6,1c-0.3,0.3-0.6,0.5-1,0.7
C27.7,92.3,27.2,92.4,26.8,92.4z M25,89.1c0,0.3,0,0.5,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7c0.2,0.2,0.3,0.4,0.6,0.5s0.5,0.2,0.8,0.2
c0.3,0,0.5-0.1,0.8-0.2s0.4-0.3,0.6-0.5c0.1-0.2,0.3-0.4,0.3-0.7s0.1-0.5,0.1-0.8c0-0.3,0-0.5-0.1-0.8c-0.1-0.3-0.2-0.5-0.4-0.7
c-0.2-0.2-0.3-0.4-0.6-0.5c-0.2-0.1-0.5-0.2-0.7-0.2c-0.3,0-0.5,0.1-0.8,0.2s-0.4,0.3-0.6,0.5c-0.2,0.2-0.3,0.4-0.3,0.7
C25.1,88.6,25,88.9,25,89.1z"/>
<path class="st1" d="M31,92.3V86h2.8c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.4-0.1,0.8-0.3,1.1c-0.2,0.3-0.5,0.6-0.8,0.7l1.5,2.4h-1.4l-1.3-2.1h-1.2v2.1H31z M32.3,89.1h1.6c0.1,0,0.2,0,0.3-0.1
c0.1-0.1,0.2-0.1,0.3-0.2c0.1-0.1,0.1-0.2,0.2-0.3s0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4s-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
C34,87.1,33.9,87,33.8,87h-1.5V89.1z"/>
<path class="st1" d="M41.8,91.3v1.1h-4.4V86h4.4V87h-3.1v1.5h2.7v1h-2.7v1.7H41.8z"/>
</g>
<path class="st3" d="M27.1,29.7c-0.8,0.2-1.6,0.3-2.4,0.3c-5.4,0-9.8-4.4-9.8-9.8c0-5.4,4.4-9.8,9.8-9.8c5.4,0,9.8,4.4,9.8,9.8
c0,0.1,0,0.2,0,0.3c0.4-0.4,0.8-0.6,1.4-0.9C35.6,13.7,30.7,9,24.7,9c-6.2,0-11.2,5-11.2,11.2c0,6.2,5,11.2,11.2,11.2
c1,0,2-0.2,3-0.4C27.5,30.5,27.3,30.1,27.1,29.7z"/>
<path class="st3" d="M31.2,16.6L31.2,16.6c-0.3-0.3-0.5-0.3-0.8-0.2c0,0-4,0.5-5.7,0.5c0,0-0.1,0-0.1,0c-1.7,0-5.8-0.6-5.8-0.6
c-0.3-0.1-0.6,0-0.8,0.3l-0.1,0.2c-0.1,0.2-0.1,0.4-0.1,0.7c0.1,0.2,0.2,0.4,0.4,0.5c0.7,0.3,3.3,1.2,4,1.4c0.1,0,0.4,0.1,0.4,0.6
c0,0.6-0.2,3.1-0.5,4.3c-0.3,1.2-0.8,2.7-0.8,2.7c-0.1,0.4,0.1,0.9,0.5,1l0.5,0.2c0.2,0.1,0.4,0.1,0.6,0c0.2-0.1,0.3-0.3,0.4-0.5
l1.4-4.3l1.3,4.4c0.1,0.2,0.2,0.4,0.4,0.5c0.1,0.1,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.3-0.1l0.5-0.2c0.4-0.1,0.6-0.5,0.5-0.9
c0,0-0.4-1.6-0.7-2.9c-0.2-0.8-0.3-2-0.3-2.9c0-0.6-0.1-1.1-0.1-1.5c0-0.2,0.1-0.4,0.4-0.5c0.1,0,3.7-1.3,3.7-1.3
c0.3-0.1,0.4-0.3,0.5-0.6C31.4,17.1,31.4,16.8,31.2,16.6z"/>
<circle class="st3" cx="24.7" cy="14.1" r="1.7"/>
<g>
<polygon class="st3" points="36.4,30.1 36.4,30.1 36.4,30.1 "/>
<path class="st3" d="M35.2,25.8l2.7-2.7c0.4-0.4,0.4-1.1,0-1.5c-0.4-0.4-1.1-0.4-1.5,0l-2.7,2.7l-2.7-2.7c-0.4-0.4-1.1-0.4-1.5,0
c-0.4,0.4-0.4,1.1,0,1.5l2.7,2.7l-2.7,2.7c-0.4,0.4-0.4,1.1,0,1.5c0.4,0.4,1.1,0.4,1.5,0l2.7-2.7l2.7,2.7c0.4,0.4,1.1,0.4,1.5,0
c0.4-0.4,0.4-1.1,0-1.5L35.2,25.8z"/>
</g>
<path class="st1" d="M27.3,129.6c-0.8,0.2-1.6,0.3-2.4,0.3c-5.4,0-9.8-4.4-9.8-9.8c0-5.4,4.4-9.8,9.8-9.8c5.4,0,9.8,4.4,9.8,9.8
c0,0.1,0,0.2,0,0.3c0.4-0.4,0.8-0.6,1.4-0.9c-0.3-5.9-5.2-10.6-11.2-10.6c-6.2,0-11.2,5-11.2,11.2c0,6.2,5,11.2,11.2,11.2
c1,0,2-0.2,3-0.4C27.6,130.5,27.4,130.1,27.3,129.6z"/>
<path class="st1" d="M31.3,116.6L31.3,116.6c-0.3-0.3-0.5-0.3-0.8-0.2c0,0-4,0.5-5.7,0.5c0,0-0.1,0-0.1,0c-1.7,0-5.8-0.6-5.8-0.6
c-0.3-0.1-0.6,0-0.8,0.3l-0.1,0.2c-0.1,0.2-0.1,0.4-0.1,0.7c0.1,0.2,0.2,0.4,0.4,0.5c0.7,0.3,3.3,1.2,4,1.4c0.1,0,0.4,0.1,0.4,0.6
c0,0.6-0.2,3.1-0.5,4.3c-0.3,1.2-0.8,2.7-0.8,2.7c-0.1,0.4,0.1,0.9,0.5,1l0.5,0.2c0.2,0.1,0.4,0.1,0.6,0c0.2-0.1,0.3-0.3,0.4-0.5
l1.4-4.3l1.3,4.4c0.1,0.2,0.2,0.4,0.4,0.5c0.1,0.1,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.3-0.1l0.5-0.2c0.4-0.1,0.6-0.5,0.5-0.9
c0,0-0.4-1.6-0.7-2.9c-0.2-0.8-0.3-2-0.3-2.9c0-0.6-0.1-1.1-0.1-1.5c0-0.2,0.1-0.4,0.4-0.5c0.1,0,3.7-1.3,3.7-1.3
c0.3-0.1,0.4-0.3,0.5-0.6C31.6,117,31.5,116.8,31.3,116.6z"/>
<circle class="st1" cx="24.9" cy="114.1" r="1.7"/>
<g>
<path class="st1" d="M7.8,142.5v-6.4H9v6.4H7.8z"/>
<path class="st1" d="M14.9,141.7c-0.5,0.5-1.1,0.8-1.7,0.8c-0.4,0-0.8-0.1-1.2-0.3c-0.4-0.2-0.7-0.4-0.9-0.7
c-0.3-0.3-0.5-0.7-0.6-1s-0.2-0.8-0.2-1.2c0-0.4,0.1-0.9,0.2-1.2c0.2-0.4,0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7
c0.4-0.2,0.8-0.3,1.2-0.3c0.6,0,1.1,0.1,1.5,0.4s0.7,0.6,0.9,1l-0.9,0.7c-0.2-0.3-0.4-0.6-0.6-0.7s-0.6-0.3-0.9-0.3
c-0.3,0-0.5,0.1-0.7,0.2c-0.2,0.1-0.4,0.3-0.5,0.5c-0.2,0.2-0.3,0.4-0.4,0.7c-0.1,0.3-0.1,0.5-0.1,0.8c0,0.3,0,0.6,0.1,0.8
c0.1,0.3,0.2,0.5,0.4,0.7c0.2,0.2,0.4,0.3,0.6,0.5c0.2,0.1,0.5,0.2,0.7,0.2c0.6,0,1.1-0.3,1.6-0.9v-0.5h-1.3v-0.9h2.3v3.3h-1V141.7
z"/>
<path class="st1" d="M18.4,138.4v4.1h-1.2v-6.4h1l3.3,4.2v-4.2h1.2v6.4h-1L18.4,138.4z"/>
<path class="st1" d="M26.9,142.5c-0.5,0-0.9-0.1-1.2-0.3s-0.7-0.4-1-0.7c-0.3-0.3-0.5-0.6-0.6-1c-0.1-0.4-0.2-0.8-0.2-1.2
c0-0.4,0.1-0.8,0.2-1.2s0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7s0.8-0.3,1.2-0.3c0.5,0,0.9,0.1,1.2,0.3s0.7,0.4,1,0.7
c0.3,0.3,0.5,0.7,0.6,1c0.1,0.4,0.2,0.8,0.2,1.2c0,0.4-0.1,0.8-0.2,1.2c-0.2,0.4-0.4,0.7-0.6,1c-0.3,0.3-0.6,0.5-1,0.7
C27.8,142.4,27.4,142.5,26.9,142.5z M25.2,139.3c0,0.3,0,0.5,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7c0.2,0.2,0.3,0.4,0.6,0.5
s0.5,0.2,0.8,0.2c0.3,0,0.5-0.1,0.8-0.2s0.4-0.3,0.6-0.5c0.1-0.2,0.3-0.4,0.3-0.7s0.1-0.5,0.1-0.8c0-0.3,0-0.5-0.1-0.8
c-0.1-0.3-0.2-0.5-0.4-0.7c-0.2-0.2-0.3-0.4-0.6-0.5c-0.2-0.1-0.5-0.2-0.7-0.2c-0.3,0-0.5,0.1-0.8,0.2s-0.4,0.3-0.6,0.5
c-0.2,0.2-0.3,0.4-0.3,0.7C25.2,138.7,25.2,139,25.2,139.3z"/>
<path class="st1" d="M31.2,142.5v-6.4H34c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.4-0.1,0.8-0.3,1.1c-0.2,0.3-0.5,0.6-0.8,0.7l1.5,2.4H35l-1.3-2.1h-1.2v2.1H31.2z M32.4,139.2H34c0.1,0,0.2,0,0.3-0.1
c0.1-0.1,0.2-0.1,0.3-0.2c0.1-0.1,0.1-0.2,0.2-0.3s0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4s-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1-0.1-0.2-0.1-0.3-0.1h-1.5V139.2z"/>
<path class="st1" d="M41.9,141.4v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H41.9z"/>
</g>
<g>
<polygon class="st1" points="36.5,130.1 36.5,130.1 36.5,130.1 "/>
<path class="st1" d="M35.3,125.8l2.7-2.7c0.4-0.4,0.4-1.1,0-1.5c-0.4-0.4-1.1-0.4-1.5,0l-2.7,2.7l-2.7-2.7c-0.4-0.4-1.1-0.4-1.5,0
c-0.4,0.4-0.4,1.1,0,1.5l2.7,2.7l-2.7,2.7c-0.4,0.4-0.4,1.1,0,1.5c0.4,0.4,1.1,0.4,1.5,0l2.7-2.7l2.7,2.7c0.4,0.4,1.1,0.4,1.5,0
c0.4-0.4,0.4-1.1,0-1.5L35.3,125.8z"/>
</g>
<g>
<path class="st1" d="M7.7,192.7v-6.4h1.2v6.4H7.7z"/>
<path class="st1" d="M14.7,192c-0.5,0.5-1.1,0.8-1.7,0.8c-0.4,0-0.8-0.1-1.2-0.3c-0.4-0.2-0.7-0.4-0.9-0.7c-0.3-0.3-0.5-0.7-0.6-1
s-0.2-0.8-0.2-1.2c0-0.4,0.1-0.9,0.2-1.2c0.2-0.4,0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7c0.4-0.2,0.8-0.3,1.2-0.3
c0.6,0,1.1,0.1,1.5,0.4s0.7,0.6,0.9,1l-0.9,0.7c-0.2-0.3-0.4-0.6-0.6-0.7s-0.6-0.3-0.9-0.3c-0.3,0-0.5,0.1-0.7,0.2
c-0.2,0.1-0.4,0.3-0.5,0.5c-0.2,0.2-0.3,0.4-0.4,0.7c-0.1,0.3-0.1,0.5-0.1,0.8c0,0.3,0,0.6,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7
c0.2,0.2,0.4,0.3,0.6,0.5c0.2,0.1,0.5,0.2,0.7,0.2c0.6,0,1.1-0.3,1.6-0.9v-0.5h-1.3v-0.9h2.3v3.3h-1V192z"/>
<path class="st1" d="M18.3,188.6v4.1h-1.2v-6.4h1l3.3,4.2v-4.2h1.2v6.4h-1L18.3,188.6z"/>
<path class="st1" d="M26.8,192.7c-0.5,0-0.9-0.1-1.2-0.3s-0.7-0.4-1-0.7c-0.3-0.3-0.5-0.6-0.6-1c-0.1-0.4-0.2-0.8-0.2-1.2
c0-0.4,0.1-0.8,0.2-1.2s0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7s0.8-0.3,1.2-0.3c0.5,0,0.9,0.1,1.2,0.3s0.7,0.4,1,0.7
c0.3,0.3,0.5,0.7,0.6,1c0.1,0.4,0.2,0.8,0.2,1.2c0,0.4-0.1,0.8-0.2,1.2c-0.2,0.4-0.4,0.7-0.6,1c-0.3,0.3-0.6,0.5-1,0.7
C27.7,192.6,27.2,192.7,26.8,192.7z M25,189.5c0,0.3,0,0.5,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7c0.2,0.2,0.3,0.4,0.6,0.5
s0.5,0.2,0.8,0.2c0.3,0,0.5-0.1,0.8-0.2s0.4-0.3,0.6-0.5c0.1-0.2,0.3-0.4,0.3-0.7s0.1-0.5,0.1-0.8c0-0.3,0-0.5-0.1-0.8
c-0.1-0.3-0.2-0.5-0.4-0.7c-0.2-0.2-0.3-0.4-0.6-0.5c-0.2-0.1-0.5-0.2-0.7-0.2c-0.3,0-0.5,0.1-0.8,0.2s-0.4,0.3-0.6,0.5
c-0.2,0.2-0.3,0.4-0.3,0.7C25.1,189,25,189.2,25,189.5z"/>
<path class="st1" d="M31,192.7v-6.4h2.8c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.4-0.1,0.8-0.3,1.1c-0.2,0.3-0.5,0.6-0.8,0.7l1.5,2.4h-1.4l-1.3-2.1h-1.2v2.1H31z M32.3,189.5h1.6c0.1,0,0.2,0,0.3-0.1
c0.1-0.1,0.2-0.1,0.3-0.2c0.1-0.1,0.1-0.2,0.2-0.3s0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4s-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1-0.1-0.2-0.1-0.3-0.1h-1.5V189.5z"/>
<path class="st1" d="M41.8,191.6v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H41.8z"/>
</g>
<path class="st1" d="M27.1,179.9c-0.8,0.2-1.6,0.3-2.4,0.3c-5.4,0-9.8-4.4-9.8-9.8c0-5.4,4.4-9.8,9.8-9.8c5.4,0,9.8,4.4,9.8,9.8
c0,0.1,0,0.2,0,0.3c0.4-0.4,0.8-0.6,1.4-0.9c-0.3-5.9-5.2-10.6-11.2-10.6c-6.2,0-11.2,5-11.2,11.2c0,6.2,5,11.2,11.2,11.2
c1,0,2-0.2,3-0.4C27.5,180.7,27.3,180.3,27.1,179.9z"/>
<path class="st1" d="M31.2,166.8L31.2,166.8c-0.3-0.3-0.5-0.3-0.8-0.2c0,0-4,0.5-5.7,0.5c0,0-0.1,0-0.1,0c-1.7,0-5.8-0.6-5.8-0.6
c-0.3-0.1-0.6,0-0.8,0.3l-0.1,0.2c-0.1,0.2-0.1,0.4-0.1,0.7c0.1,0.2,0.2,0.4,0.4,0.5c0.7,0.3,3.3,1.2,4,1.4c0.1,0,0.4,0.1,0.4,0.6
c0,0.6-0.2,3.1-0.5,4.3c-0.3,1.2-0.8,2.7-0.8,2.7c-0.1,0.4,0.1,0.9,0.5,1l0.5,0.2c0.2,0.1,0.4,0.1,0.6,0c0.2-0.1,0.3-0.3,0.4-0.5
l1.4-4.3l1.3,4.4c0.1,0.2,0.2,0.4,0.4,0.5c0.1,0.1,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.3-0.1l0.5-0.2c0.4-0.1,0.6-0.5,0.5-0.9
c0,0-0.4-1.6-0.7-2.9c-0.2-0.8-0.3-2-0.3-2.9c0-0.6-0.1-1.1-0.1-1.5c0-0.2,0.1-0.4,0.4-0.5c0.1,0,3.7-1.3,3.7-1.3
c0.3-0.1,0.4-0.3,0.5-0.6C31.4,167.3,31.4,167,31.2,166.8z"/>
<circle class="st1" cx="24.7" cy="164.3" r="1.7"/>
<g>
<polygon class="st1" points="36.4,180.3 36.4,180.3 36.4,180.3 "/>
<path class="st1" d="M35.2,176l2.7-2.7c0.4-0.4,0.4-1.1,0-1.5c-0.4-0.4-1.1-0.4-1.5,0l-2.7,2.7l-2.7-2.7c-0.4-0.4-1.1-0.4-1.5,0
c-0.4,0.4-0.4,1.1,0,1.5l2.7,2.7l-2.7,2.7c-0.4,0.4-0.4,1.1,0,1.5c0.4,0.4,1.1,0.4,1.5,0l2.7-2.7l2.7,2.7c0.4,0.4,1.1,0.4,1.5,0
c0.4-0.4,0.4-1.1,0-1.5L35.2,176z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

210
scripts/system/ignore.js Normal file
View file

@ -0,0 +1,210 @@
//
// ignore.js
// scripts/system/
//
// Created by Stephen Birarda on 07/11/2016
// Copyright 2016 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
//
// grab the toolbar
var toolbar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
// setup the ignore button and add it to the toolbar
var button = toolbar.addButton({
objectName: 'ignore',
imageURL: Script.resolvePath("assets/images/tools/ignore.svg"),
visible: true,
buttonState: 1,
alpha: 0.9
});
var isShowingOverlays = false;
var ignoreOverlays = {};
function removeOverlays() {
// enumerate the overlays and remove them
var ignoreOverlayKeys = Object.keys(ignoreOverlays);
for (i = 0; i < ignoreOverlayKeys.length; ++i) {
var avatarID = ignoreOverlayKeys[i];
Overlays.deleteOverlay(ignoreOverlays[avatarID]);
}
ignoreOverlays = {};
}
// handle clicks on the toolbar button
function buttonClicked(){
if (isShowingOverlays) {
removeOverlays();
isShowingOverlays = false;
} else {
isShowingOverlays = true;
}
button.writeProperty('buttonState', isShowingOverlays ? 0 : 1);
}
button.clicked.connect(buttonClicked);
function updateOverlays() {
if (isShowingOverlays) {
var identifiers = AvatarList.getAvatarIdentifiers();
for (i = 0; i < identifiers.length; ++i) {
var avatarID = identifiers[i];
if (avatarID === null) {
// this is our avatar, skip it
continue;
}
// get the position for this avatar
var avatar = AvatarList.getAvatar(avatarID);
var avatarPosition = avatar && avatar.position;
if (!avatarPosition) {
// we don't have a valid position for this avatar, skip it
continue;
}
// setup a position for the overlay that is just above this avatar's head
var overlayPosition = avatar.getJointPosition("Head");
overlayPosition.y += 0.45;
if (avatarID in ignoreOverlays) {
// keep the overlay above the current position of this avatar
Overlays.editOverlay(ignoreOverlays[avatarID], {
position: overlayPosition
});
} else {
// add the overlay above this avatar
var newOverlay = Overlays.addOverlay("image3d", {
url: Script.resolvePath("assets/images/ignore-target-01.svg"),
position: overlayPosition,
size: 0.4,
scale: 0.4,
color: { red: 255, green: 255, blue: 255},
alpha: 1,
solid: true,
isFacingAvatar: true,
drawInFront: true
});
// push this overlay to our array of overlays
ignoreOverlays[avatarID] = newOverlay;
}
}
}
}
Script.update.connect(updateOverlays);
AvatarList.avatarRemovedEvent.connect(function(avatarID){
if (isShowingOverlays) {
// we are currently showing overlays and an avatar just went away
// first remove the rendered overlay
Overlays.deleteOverlay(ignoreOverlays[avatarID]);
// delete the saved ID of the overlay from our ignored overlays object
delete ignoreOverlays[avatarID];
}
});
function handleSelectedOverlay(clickedOverlay) {
// see this is one of our ignore overlays
var ignoreOverlayKeys = Object.keys(ignoreOverlays)
for (i = 0; i < ignoreOverlayKeys.length; ++i) {
var avatarID = ignoreOverlayKeys[i];
var ignoreOverlay = ignoreOverlays[avatarID];
if (clickedOverlay.overlayID == ignoreOverlay) {
// matched to an overlay, ask for the matching avatar to be ignored
Users.ignore(avatarID);
// cleanup of the overlay is handled by the connection to avatarRemovedEvent
}
}
}
Controller.mousePressEvent.connect(function(event){
if (isShowingOverlays) {
// handle click events so we can detect when our overlays are clicked
if (!event.isLeftButton) {
// if another mouse button than left is pressed ignore it
return false;
}
// compute the pick ray from the event
var pickRay = Camera.computePickRay(event.x, event.y);
// grab the clicked overlay for the given pick ray
var clickedOverlay = Overlays.findRayIntersection(pickRay);
if (clickedOverlay.intersects) {
handleSelectedOverlay(clickedOverlay);
}
}
});
// We get mouseMoveEvents from the handControllers, via handControllerPointer.
// But we dont' get mousePressEvents.
var triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click');
var TRIGGER_GRAB_VALUE = 0.85; // From handControllerGrab/Pointer.js. Should refactor.
var TRIGGER_ON_VALUE = 0.4;
var TRIGGER_OFF_VALUE = 0.15;
var triggered = false;
var activeHand = Controller.Standard.RightHand;
function controllerComputePickRay() {
var controllerPose = Controller.getPoseValue(activeHand);
if (controllerPose.valid && triggered) {
var controllerPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, controllerPose.translation),
MyAvatar.position);
// This gets point direction right, but if you want general quaternion it would be more complicated:
var controllerDirection = Quat.getUp(Quat.multiply(MyAvatar.orientation, controllerPose.rotation));
return { origin: controllerPosition, direction: controllerDirection };
}
}
function makeTriggerHandler(hand) {
return function (value) {
if (isShowingOverlays) {
if (!triggered && (value > TRIGGER_GRAB_VALUE)) { // should we smooth?
triggered = true;
if (activeHand !== hand) {
// No switching while the other is already triggered, so no need to release.
activeHand = (activeHand === Controller.Standard.RightHand) ? Controller.Standard.LeftHand : Controller.Standard.RightHand;
}
var pickRay = controllerComputePickRay();
if (pickRay) {
var overlayIntersection = Overlays.findRayIntersection(pickRay);
if (overlayIntersection.intersects) {
handleSelectedOverlay(overlayIntersection);
}
}
} else if (triggered && (value < TRIGGER_OFF_VALUE)) {
triggered = false;
}
}
};
}
triggerMapping.from(Controller.Standard.RT).peek().to(makeTriggerHandler(Controller.Standard.RightHand));
triggerMapping.from(Controller.Standard.LT).peek().to(makeTriggerHandler(Controller.Standard.LeftHand));
triggerMapping.enable();
// cleanup the toolbar button and overlays when script is stopped
Script.scriptEnding.connect(function() {
toolbar.removeButton('ignore');
removeOverlays();
triggerMapping.disable();
});