mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 23:17:02 +02:00
Merge pull request #8232 from birarda/ignore
add a script to ignore other avatars
This commit is contained in:
commit
ff2d7addd7
25 changed files with 673 additions and 34 deletions
|
@ -93,6 +93,7 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
|
||||||
this, "handleNodeAudioPacket");
|
this, "handleNodeAudioPacket");
|
||||||
packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket");
|
packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket");
|
||||||
packetReceiver.registerListener(PacketType::NegotiateAudioFormat, this, "handleNegotiateAudioFormat");
|
packetReceiver.registerListener(PacketType::NegotiateAudioFormat, this, "handleNegotiateAudioFormat");
|
||||||
|
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
|
||||||
|
|
||||||
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
|
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
|
// loop through all other nodes that have sufficient audio to mix
|
||||||
|
|
||||||
DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& otherNode){
|
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();
|
AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData();
|
||||||
|
|
||||||
// enumerate the ARBs attached to the otherNode and add all that should be added to mix
|
// 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) {
|
void AudioMixer::removeHRTFsForFinishedInjector(const QUuid& streamID) {
|
||||||
auto injectorClientData = qobject_cast<AudioMixerClientData*>(sender());
|
auto injectorClientData = qobject_cast<AudioMixerClientData*>(sender());
|
||||||
if (injectorClientData) {
|
if (injectorClientData) {
|
||||||
|
|
|
@ -47,6 +47,7 @@ private slots:
|
||||||
void handleMuteEnvironmentPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
void handleMuteEnvironmentPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
void handleNegotiateAudioFormat(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
void handleNegotiateAudioFormat(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||||
void handleNodeKilled(SharedNodePointer killedNode);
|
void handleNodeKilled(SharedNodePointer killedNode);
|
||||||
|
void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
|
|
||||||
void removeHRTFsForFinishedInjector(const QUuid& streamID);
|
void removeHRTFsForFinishedInjector(const QUuid& streamID);
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) :
|
||||||
packetReceiver.registerListener(PacketType::AvatarData, this, "handleAvatarDataPacket");
|
packetReceiver.registerListener(PacketType::AvatarData, this, "handleAvatarDataPacket");
|
||||||
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket");
|
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket");
|
||||||
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
||||||
|
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &AvatarMixer::handlePacketVersionMismatch);
|
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
|
// send back a packet with other active node data to this node
|
||||||
nodeList->eachMatchingNode(
|
nodeList->eachMatchingNode(
|
||||||
[&](const SharedNodePointer& otherNode)->bool {
|
[&](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;
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (otherNode->getUUID() == node->getUUID()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
[&](const SharedNodePointer& otherNode) {
|
[&](const SharedNodePointer& otherNode) {
|
||||||
++numOtherAvatars;
|
++numOtherAvatars;
|
||||||
|
@ -431,6 +433,10 @@ void AvatarMixer::handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message
|
||||||
DependencyManager::get<NodeList>()->processKillNode(*message);
|
DependencyManager::get<NodeList>()->processKillNode(*message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||||
|
senderNode->parseIgnoreRequestMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
void AvatarMixer::sendStatsPacket() {
|
void AvatarMixer::sendStatsPacket() {
|
||||||
QJsonObject statsObject;
|
QJsonObject statsObject;
|
||||||
statsObject["average_listeners_last_second"] = (float) _sumListeners / (float) _numStatFrames;
|
statsObject["average_listeners_last_second"] = (float) _sumListeners / (float) _numStatFrames;
|
||||||
|
|
|
@ -37,9 +37,11 @@ private slots:
|
||||||
void handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message);
|
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message);
|
||||||
|
void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void domainSettingsRequestComplete();
|
void domainSettingsRequestComplete();
|
||||||
void handlePacketVersionMismatch(PacketType type, const HifiSockAddr& senderSockAddr, const QUuid& senderUUID);
|
void handlePacketVersionMismatch(PacketType type, const HifiSockAddr& senderSockAddr, const QUuid& senderUUID);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void broadcastAvatarData();
|
void broadcastAvatarData();
|
||||||
void parseDomainServerSettings(const QJsonObject& domainSettings);
|
void parseDomainServerSettings(const QJsonObject& domainSettings);
|
||||||
|
|
|
@ -98,6 +98,7 @@
|
||||||
#include <Tooltip.h>
|
#include <Tooltip.h>
|
||||||
#include <udt/PacketHeaders.h>
|
#include <udt/PacketHeaders.h>
|
||||||
#include <UserActivityLogger.h>
|
#include <UserActivityLogger.h>
|
||||||
|
#include <UsersScriptingInterface.h>
|
||||||
#include <recording/Deck.h>
|
#include <recording/Deck.h>
|
||||||
#include <recording/Recorder.h>
|
#include <recording/Recorder.h>
|
||||||
#include <shared/StringHelpers.h>
|
#include <shared/StringHelpers.h>
|
||||||
|
@ -440,6 +441,7 @@ bool setupEssentials(int& argc, char** argv) {
|
||||||
DependencyManager::set<FramebufferCache>();
|
DependencyManager::set<FramebufferCache>();
|
||||||
DependencyManager::set<AnimationCache>();
|
DependencyManager::set<AnimationCache>();
|
||||||
DependencyManager::set<ModelBlender>();
|
DependencyManager::set<ModelBlender>();
|
||||||
|
DependencyManager::set<UsersScriptingInterface>();
|
||||||
DependencyManager::set<AvatarManager>();
|
DependencyManager::set<AvatarManager>();
|
||||||
DependencyManager::set<LODManager>();
|
DependencyManager::set<LODManager>();
|
||||||
DependencyManager::set<StandAloneJSConsole>();
|
DependencyManager::set<StandAloneJSConsole>();
|
||||||
|
@ -4755,6 +4757,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface());
|
scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface());
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
|
scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
|
||||||
|
scriptEngine->registerGlobalObject("Users", DependencyManager::get<UsersScriptingInterface>().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::canAcceptURL(const QString& urlString) const {
|
bool Application::canAcceptURL(const QString& urlString) const {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
#include <Rig.h>
|
#include <Rig.h>
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
|
#include <UsersScriptingInterface.h>
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
|
|
||||||
#include "Application.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
|
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
||||||
qRegisterMetaType<QWeakPointer<Node> >("NodeWeakPointer");
|
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::BulkAvatarData, this, "processAvatarDataPacket");
|
||||||
packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar");
|
packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar");
|
||||||
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "processAvatarIdentityPacket");
|
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() {
|
AvatarManager::~AvatarManager() {
|
||||||
|
@ -85,7 +91,8 @@ void AvatarManager::init() {
|
||||||
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
|
_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::ScenePointer scene = qApp->getMain3DScene();
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
|
|
|
@ -78,6 +78,9 @@ public slots:
|
||||||
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
||||||
void updateAvatarRenderStatus(bool shouldRenderAvatars);
|
void updateAvatarRenderStatus(bool shouldRenderAvatars);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
virtual void removeAvatar(const QUuid& sessionUUID) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit AvatarManager(QObject* parent = 0);
|
explicit AvatarManager(QObject* parent = 0);
|
||||||
explicit AvatarManager(const AvatarManager& other);
|
explicit AvatarManager(const AvatarManager& other);
|
||||||
|
@ -88,7 +91,6 @@ private:
|
||||||
virtual AvatarSharedPointer newSharedAvatar() override;
|
virtual AvatarSharedPointer newSharedAvatar() override;
|
||||||
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) 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;
|
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) override;
|
||||||
|
|
||||||
QVector<AvatarSharedPointer> _avatarFades;
|
QVector<AvatarSharedPointer> _avatarFades;
|
||||||
|
|
|
@ -14,7 +14,7 @@ class QmlWrapper : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QmlWrapper(QObject* qmlObject, QObject* parent = nullptr)
|
QmlWrapper(QObject* qmlObject, QObject* parent = nullptr)
|
||||||
: QObject(parent), _qmlObject(qmlObject) {
|
: QObject(parent), _qmlObject(qmlObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_INVOKABLE void writeProperty(QString propertyName, QVariant propertyValue) {
|
Q_INVOKABLE void writeProperty(QString propertyName, QVariant propertyValue) {
|
||||||
|
@ -91,6 +91,10 @@ public:
|
||||||
|
|
||||||
return new ToolbarButtonProxy(rawButton, this);
|
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"
|
||||||
|
|
|
@ -19,7 +19,9 @@
|
||||||
#include "AvatarHashMap.h"
|
#include "AvatarHashMap.h"
|
||||||
|
|
||||||
AvatarHashMap::AvatarHashMap() {
|
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() {
|
QVector<QUuid> AvatarHashMap::getAvatarIdentifiers() {
|
||||||
|
@ -105,7 +107,10 @@ void AvatarHashMap::processAvatarDataPacket(QSharedPointer<ReceivedMessage> mess
|
||||||
|
|
||||||
QByteArray byteArray = message->readWithoutCopy(message->getBytesLeftToRead());
|
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);
|
auto avatar = newOrExistingAvatar(sessionUUID, sendingNode);
|
||||||
|
|
||||||
// have the matching (or new) avatar parse the data from the packet
|
// 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::Identity identity;
|
||||||
AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity);
|
AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity);
|
||||||
|
|
||||||
// mesh URL for a UUID, find avatar in our list
|
// make sure this isn't for an ignored avatar
|
||||||
auto avatar = newOrExistingAvatar(identity.uuid, sendingNode);
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
avatar->processAvatarIdentity(identity);
|
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) {
|
void AvatarHashMap::processKillAvatar(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||||
|
|
|
@ -19,12 +19,14 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <NLPacket.h>
|
#include <NLPacket.h>
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
|
|
||||||
#include "AvatarData.h"
|
#include "AvatarData.h"
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
class AvatarHashMap : public QObject, public Dependency {
|
class AvatarHashMap : public QObject, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -425,12 +425,8 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr<NLPacket> packet, const Node&
|
||||||
}
|
}
|
||||||
|
|
||||||
int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||||
QMutexLocker locker(&sendingNode->getMutex());
|
|
||||||
|
|
||||||
NodeData* linkedData = sendingNode->getLinkedData();
|
NodeData* linkedData = getOrCreateLinkedData(sendingNode);
|
||||||
if (!linkedData && linkedDataCreateCallback) {
|
|
||||||
linkedDataCreateCallback(sendingNode.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (linkedData) {
|
if (linkedData) {
|
||||||
QMutexLocker linkedDataLocker(&linkedData->getMutex());
|
QMutexLocker linkedDataLocker(&linkedData->getMutex());
|
||||||
|
@ -440,6 +436,17 @@ int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage
|
||||||
return 0;
|
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) {
|
SharedNodePointer LimitedNodeList::nodeWithUUID(const QUuid& nodeUUID) {
|
||||||
QReadLocker readLocker(&_nodeMutex);
|
QReadLocker readLocker(&_nodeMutex);
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,7 @@ public:
|
||||||
void processKillNode(ReceivedMessage& message);
|
void processKillNode(ReceivedMessage& message);
|
||||||
|
|
||||||
int updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer matchingNode);
|
int updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer matchingNode);
|
||||||
|
NodeData* getOrCreateLinkedData(SharedNodePointer node);
|
||||||
|
|
||||||
unsigned int broadcastToNodes(std::unique_ptr<NLPacket> packet, const NodeSet& destinationNodeTypes);
|
unsigned int broadcastToNodes(std::unique_ptr<NLPacket> packet, const NodeSet& destinationNodeTypes);
|
||||||
SharedNodePointer soloNodeOfType(NodeType_t nodeType);
|
SharedNodePointer soloNodeOfType(NodeType_t nodeType);
|
||||||
|
|
|
@ -12,15 +12,17 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <UUID.h>
|
|
||||||
|
|
||||||
#include "Node.h"
|
|
||||||
#include "SharedUtil.h"
|
|
||||||
#include "NodePermissions.h"
|
|
||||||
|
|
||||||
#include <QtCore/QDataStream>
|
#include <QtCore/QDataStream>
|
||||||
#include <QtCore/QDebug>
|
#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";
|
const QString UNKNOWN_NodeType_t_NAME = "Unknown";
|
||||||
|
|
||||||
int NodePtrMetaTypeId = qRegisterMetaType<Node*>("Node*");
|
int NodePtrMetaTypeId = qRegisterMetaType<Node*>("Node*");
|
||||||
|
@ -78,6 +80,27 @@ void Node::updateClockSkewUsec(qint64 clockSkewSample) {
|
||||||
_clockSkewUsec = (quint64)_clockSkewMovingPercentile.getValueAtPercentile();
|
_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) {
|
QDataStream& operator<<(QDataStream& out, const Node& node) {
|
||||||
out << node._type;
|
out << node._type;
|
||||||
out << node._uuid;
|
out << node._uuid;
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
#include <QtCore/QSharedPointer>
|
#include <QtCore/QSharedPointer>
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
|
|
||||||
|
#include <UUIDHasher.h>
|
||||||
|
|
||||||
|
#include <tbb/concurrent_unordered_set.h>
|
||||||
|
|
||||||
#include "HifiSockAddr.h"
|
#include "HifiSockAddr.h"
|
||||||
#include "NetworkPeer.h"
|
#include "NetworkPeer.h"
|
||||||
#include "NodeData.h"
|
#include "NodeData.h"
|
||||||
|
@ -66,6 +70,10 @@ public:
|
||||||
bool getCanRezTmp() const { return _permissions.canRezTemporaryEntities; }
|
bool getCanRezTmp() const { return _permissions.canRezTemporaryEntities; }
|
||||||
bool getCanWriteToAssetServer() const { return _permissions.canWriteToAssetServer; }
|
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& out, const Node& node);
|
||||||
friend QDataStream& operator>>(QDataStream& in, Node& node);
|
friend QDataStream& operator>>(QDataStream& in, Node& node);
|
||||||
|
|
||||||
|
@ -84,6 +92,7 @@ private:
|
||||||
QMutex _mutex;
|
QMutex _mutex;
|
||||||
MovingPercentile _clockSkewMovingPercentile;
|
MovingPercentile _clockSkewMovingPercentile;
|
||||||
NodePermissions _permissions;
|
NodePermissions _permissions;
|
||||||
|
tbb::concurrent_unordered_set<QUuid, UUIDHasher> _ignoredNodeIDSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Node*)
|
Q_DECLARE_METATYPE(Node*)
|
||||||
|
|
|
@ -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
|
// anytime we get a new node we will want to attempt to punch to it
|
||||||
connect(this, &LimitedNodeList::nodeAdded, this, &NodeList::startNodeHolePunch);
|
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)
|
// setup our timer to send keepalive pings (it's started and stopped on domain connect/disconnect)
|
||||||
_keepAlivePingTimer.setInterval(KEEPALIVE_PING_INTERVAL_MS);
|
_keepAlivePingTimer.setInterval(KEEPALIVE_PING_INTERVAL_MS);
|
||||||
|
@ -215,6 +218,11 @@ void NodeList::reset() {
|
||||||
|
|
||||||
_numNoReplyDomainCheckIns = 0;
|
_numNoReplyDomainCheckIns = 0;
|
||||||
|
|
||||||
|
// lock and clear our set of ignored IDs
|
||||||
|
_ignoredSetLock.lockForWrite();
|
||||||
|
_ignoredNodeIDs.clear();
|
||||||
|
_ignoredSetLock.unlock();
|
||||||
|
|
||||||
// refresh the owner UUID to the NULL UUID
|
// refresh the owner UUID to the NULL UUID
|
||||||
setSessionUUID(QUuid());
|
setSessionUUID(QUuid());
|
||||||
|
|
||||||
|
@ -692,3 +700,67 @@ void NodeList::sendKeepAlivePings() {
|
||||||
sendPacket(constructPingPacket(), *node);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include <unistd.h> // not on windows, not needed for mac or windows
|
#include <unistd.h> // not on windows, not needed for mac or windows
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <tbb/concurrent_unordered_set.h>
|
||||||
|
|
||||||
#include <QtCore/QElapsedTimer>
|
#include <QtCore/QElapsedTimer>
|
||||||
#include <QtCore/QMutex>
|
#include <QtCore/QMutex>
|
||||||
#include <QtCore/QSet>
|
#include <QtCore/QSet>
|
||||||
|
@ -68,6 +70,9 @@ public:
|
||||||
|
|
||||||
void setIsShuttingDown(bool isShuttingDown) { _isShuttingDown = isShuttingDown; }
|
void setIsShuttingDown(bool isShuttingDown) { _isShuttingDown = isShuttingDown; }
|
||||||
|
|
||||||
|
void ignoreNodeBySessionID(const QUuid& nodeID);
|
||||||
|
bool isIgnoringNode(const QUuid& nodeID) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void reset();
|
void reset();
|
||||||
void sendDomainServerCheckIn();
|
void sendDomainServerCheckIn();
|
||||||
|
@ -92,6 +97,8 @@ public slots:
|
||||||
signals:
|
signals:
|
||||||
void limitOfSilentDomainCheckInsReached();
|
void limitOfSilentDomainCheckInsReached();
|
||||||
void receivedDomainServerList();
|
void receivedDomainServerList();
|
||||||
|
void ignoredNode(const QUuid& nodeID);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void stopKeepalivePingTimer();
|
void stopKeepalivePingTimer();
|
||||||
void sendPendingDSPathQuery();
|
void sendPendingDSPathQuery();
|
||||||
|
@ -103,6 +110,8 @@ private slots:
|
||||||
void pingPunchForDomainServer();
|
void pingPunchForDomainServer();
|
||||||
|
|
||||||
void sendKeepAlivePings();
|
void sendKeepAlivePings();
|
||||||
|
|
||||||
|
void maybeSendIgnoreSetToNode(SharedNodePointer node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeList() : LimitedNodeList(0, 0) { assert(false); } // Not implemented, needed for DependencyManager templates compile
|
NodeList() : LimitedNodeList(0, 0) { assert(false); } // Not implemented, needed for DependencyManager templates compile
|
||||||
|
@ -129,6 +138,9 @@ private:
|
||||||
bool _isShuttingDown { false };
|
bool _isShuttingDown { false };
|
||||||
QTimer _keepAlivePingTimer;
|
QTimer _keepAlivePingTimer;
|
||||||
|
|
||||||
|
mutable QReadWriteLock _ignoredSetLock;
|
||||||
|
tbb::concurrent_unordered_set<QUuid, UUIDHasher> _ignoredNodeIDs;
|
||||||
|
|
||||||
#if (PR_BUILD || DEV_BUILD)
|
#if (PR_BUILD || DEV_BUILD)
|
||||||
bool _shouldSendNewerVersion { false };
|
bool _shouldSendNewerVersion { false };
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -40,8 +40,6 @@ const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
|
||||||
<< PacketType::ICEServerHeartbeatDenied << PacketType::AssignmentClientStatus << PacketType::StopNode
|
<< PacketType::ICEServerHeartbeatDenied << PacketType::AssignmentClientStatus << PacketType::StopNode
|
||||||
<< PacketType::DomainServerRemovedNode;
|
<< PacketType::DomainServerRemovedNode;
|
||||||
|
|
||||||
const QSet<PacketType> RELIABLE_PACKETS = QSet<PacketType>();
|
|
||||||
|
|
||||||
PacketVersion versionForPacketType(PacketType packetType) {
|
PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
switch (packetType) {
|
switch (packetType) {
|
||||||
case PacketType::DomainList:
|
case PacketType::DomainList:
|
||||||
|
@ -62,6 +60,8 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
case PacketType::AssetUpload:
|
case PacketType::AssetUpload:
|
||||||
// Removal of extension from Asset requests
|
// Removal of extension from Asset requests
|
||||||
return 18;
|
return 18;
|
||||||
|
case PacketType::NodeIgnoreRequest:
|
||||||
|
return 18; // Introduction of node ignore request (which replaced an unused packet tpye)
|
||||||
|
|
||||||
case PacketType::DomainConnectionDenied:
|
case PacketType::DomainConnectionDenied:
|
||||||
return static_cast<PacketVersion>(DomainConnectionDeniedVersion::IncludesReasonCode);
|
return static_cast<PacketVersion>(DomainConnectionDeniedVersion::IncludesReasonCode);
|
||||||
|
|
|
@ -61,7 +61,7 @@ public:
|
||||||
AssignmentClientStatus,
|
AssignmentClientStatus,
|
||||||
NoisyMute,
|
NoisyMute,
|
||||||
AvatarIdentity,
|
AvatarIdentity,
|
||||||
TYPE_UNUSED_1,
|
NodeIgnoreRequest,
|
||||||
DomainConnectRequest,
|
DomainConnectRequest,
|
||||||
DomainServerRequireDTLS,
|
DomainServerRequireDTLS,
|
||||||
NodeJsonStats,
|
NodeJsonStats,
|
||||||
|
@ -109,7 +109,6 @@ typedef char PacketVersion;
|
||||||
|
|
||||||
extern const QSet<PacketType> NON_VERIFIED_PACKETS;
|
extern const QSet<PacketType> NON_VERIFIED_PACKETS;
|
||||||
extern const QSet<PacketType> NON_SOURCED_PACKETS;
|
extern const QSet<PacketType> NON_SOURCED_PACKETS;
|
||||||
extern const QSet<PacketType> RELIABLE_PACKETS;
|
|
||||||
|
|
||||||
PacketVersion versionForPacketType(PacketType packetType);
|
PacketVersion versionForPacketType(PacketType packetType);
|
||||||
QByteArray protocolVersionsSignature(); /// returns a unqiue signature for all the current protocols
|
QByteArray protocolVersionsSignature(); /// returns a unqiue signature for all the current protocols
|
||||||
|
|
|
@ -65,7 +65,9 @@ void PacketQueue::queuePacket(PacketPointer packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketQueue::queuePacketList(PacketListPointer packetList) {
|
void PacketQueue::queuePacketList(PacketListPointer packetList) {
|
||||||
packetList->preparePackets(getNextMessageNumber());
|
if (packetList->isOrdered()) {
|
||||||
|
packetList->preparePackets(getNextMessageNumber());
|
||||||
|
}
|
||||||
|
|
||||||
LockGuard locker(_packetsLock);
|
LockGuard locker(_packetsLock);
|
||||||
_channels.push_back(std::move(packetList->_packets));
|
_channels.push_back(std::move(packetList->_packets));
|
||||||
|
|
19
libraries/script-engine/src/UsersScriptingInterface.cpp
Normal file
19
libraries/script-engine/src/UsersScriptingInterface.cpp
Normal 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);
|
||||||
|
}
|
28
libraries/script-engine/src/UsersScriptingInterface.h
Normal file
28
libraries/script-engine/src/UsersScriptingInterface.h
Normal 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
|
|
@ -17,6 +17,7 @@ Script.load("system/goto.js");
|
||||||
Script.load("system/hmd.js");
|
Script.load("system/hmd.js");
|
||||||
Script.load("system/examples.js");
|
Script.load("system/examples.js");
|
||||||
Script.load("system/edit.js");
|
Script.load("system/edit.js");
|
||||||
|
Script.load("system/ignore.js");
|
||||||
Script.load("system/selectAudioDevice.js");
|
Script.load("system/selectAudioDevice.js");
|
||||||
Script.load("system/notifications.js");
|
Script.load("system/notifications.js");
|
||||||
Script.load("system/controllers/handControllerGrab.js");
|
Script.load("system/controllers/handControllerGrab.js");
|
||||||
|
|
37
scripts/system/assets/images/ignore-target-01.svg
Normal file
37
scripts/system/assets/images/ignore-target-01.svg
Normal 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 |
177
scripts/system/assets/images/tools/ignore.svg
Normal file
177
scripts/system/assets/images/tools/ignore.svg
Normal 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
210
scripts/system/ignore.js
Normal 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();
|
||||||
|
});
|
Loading…
Reference in a new issue