mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 22:36:57 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into blocks
This commit is contained in:
commit
d81c16ddb1
41 changed files with 282 additions and 112 deletions
|
@ -54,6 +54,7 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessag
|
||||||
if (message->getSize() == 0) {
|
if (message->getSize() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream packetStream(message->getMessage());
|
QDataStream packetStream(message->getMessage());
|
||||||
|
|
||||||
// read a NodeConnectionData object from the packet so we can pass around this data while we're inspecting it
|
// read a NodeConnectionData object from the packet so we can pass around this data while we're inspecting it
|
||||||
|
|
|
@ -458,7 +458,7 @@ const QString DISABLED_AUTOMATIC_NETWORKING_VALUE = "disabled";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool DomainServer::packetVersionMatch(const udt::Packet& packet) {
|
bool DomainServer::isPacketVerified(const udt::Packet& packet) {
|
||||||
PacketType headerType = NLPacket::typeInHeader(packet);
|
PacketType headerType = NLPacket::typeInHeader(packet);
|
||||||
PacketVersion headerVersion = NLPacket::versionInHeader(packet);
|
PacketVersion headerVersion = NLPacket::versionInHeader(packet);
|
||||||
|
|
||||||
|
@ -471,7 +471,48 @@ bool DomainServer::packetVersionMatch(const udt::Packet& packet) {
|
||||||
DomainGatekeeper::sendProtocolMismatchConnectionDenial(packet.getSenderSockAddr());
|
DomainGatekeeper::sendProtocolMismatchConnectionDenial(packet.getSenderSockAddr());
|
||||||
}
|
}
|
||||||
|
|
||||||
// let the normal nodeList implementation handle all other packets.
|
if (!PacketTypeEnum::getNonSourcedPackets().contains(headerType)) {
|
||||||
|
// this is a sourced packet - first check if we have a node that matches
|
||||||
|
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
|
||||||
|
SharedNodePointer sourceNode = nodeList->nodeWithUUID(sourceID);
|
||||||
|
|
||||||
|
if (sourceNode) {
|
||||||
|
// unverified DS packets (due to a lack of connection secret between DS + node)
|
||||||
|
// must come either from the same public IP address or a local IP address (set by RFC 1918)
|
||||||
|
|
||||||
|
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(sourceNode->getLinkedData());
|
||||||
|
|
||||||
|
bool exactAddressMatch = nodeData->getSendingSockAddr() == packet.getSenderSockAddr();
|
||||||
|
bool bothPrivateAddresses = nodeData->getSendingSockAddr().hasPrivateAddress()
|
||||||
|
&& packet.getSenderSockAddr().hasPrivateAddress();
|
||||||
|
|
||||||
|
if (nodeData && (exactAddressMatch || bothPrivateAddresses)) {
|
||||||
|
// to the best of our ability we've verified that this packet comes from the right place
|
||||||
|
// let the NodeList do its checks now (but pass it the sourceNode so it doesn't need to look it up again)
|
||||||
|
return nodeList->isPacketVerifiedWithSource(packet, sourceNode.data());
|
||||||
|
} else {
|
||||||
|
static const QString UNKNOWN_REGEX = "Packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unmatched IP for UUID";
|
||||||
|
static QString repeatedMessage
|
||||||
|
= LogHandler::getInstance().addRepeatedMessageRegex(UNKNOWN_REGEX);
|
||||||
|
|
||||||
|
qDebug() << "Packet of type" << headerType
|
||||||
|
<< "received from unmatched IP for UUID" << uuidStringWithoutCurlyBraces(sourceID);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
static const QString UNKNOWN_REGEX = "Packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unknown node with UUID";
|
||||||
|
static QString repeatedMessage
|
||||||
|
= LogHandler::getInstance().addRepeatedMessageRegex(UNKNOWN_REGEX);
|
||||||
|
|
||||||
|
qDebug() << "Packet of type" << headerType
|
||||||
|
<< "received from unknown node with UUID" << uuidStringWithoutCurlyBraces(sourceID);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback to allow the normal NodeList implementation to verify packets
|
||||||
return nodeList->isPacketVerified(packet);
|
return nodeList->isPacketVerified(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,7 +611,7 @@ void DomainServer::setupNodeListAndAssignments() {
|
||||||
addStaticAssignmentsToQueue();
|
addStaticAssignmentsToQueue();
|
||||||
|
|
||||||
// set a custom packetVersionMatch as the verify packet operator for the udt::Socket
|
// set a custom packetVersionMatch as the verify packet operator for the udt::Socket
|
||||||
nodeList->setPacketFilterOperator(&DomainServer::packetVersionMatch);
|
nodeList->setPacketFilterOperator(&DomainServer::isPacketVerified);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString ACCESS_TOKEN_KEY_PATH = "metaverse.access_token";
|
const QString ACCESS_TOKEN_KEY_PATH = "metaverse.access_token";
|
||||||
|
@ -853,7 +894,6 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Ass
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||||
|
|
||||||
QDataStream packetStream(message->getMessage());
|
QDataStream packetStream(message->getMessage());
|
||||||
NodeConnectionData nodeRequestData = NodeConnectionData::fromDataStream(packetStream, message->getSenderSockAddr(), false);
|
NodeConnectionData nodeRequestData = NodeConnectionData::fromDataStream(packetStream, message->getSenderSockAddr(), false);
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ public slots:
|
||||||
|
|
||||||
void restart();
|
void restart();
|
||||||
|
|
||||||
|
private slots:
|
||||||
void processRequestAssignmentPacket(QSharedPointer<ReceivedMessage> packet);
|
void processRequestAssignmentPacket(QSharedPointer<ReceivedMessage> packet);
|
||||||
void processListRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
void processListRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
void processNodeJSONStatsPacket(QSharedPointer<ReceivedMessage> packetList, SharedNodePointer sendingNode);
|
void processNodeJSONStatsPacket(QSharedPointer<ReceivedMessage> packetList, SharedNodePointer sendingNode);
|
||||||
|
@ -79,7 +80,6 @@ public slots:
|
||||||
void processICEServerHeartbeatDenialPacket(QSharedPointer<ReceivedMessage> message);
|
void processICEServerHeartbeatDenialPacket(QSharedPointer<ReceivedMessage> message);
|
||||||
void processICEServerHeartbeatACK(QSharedPointer<ReceivedMessage> message);
|
void processICEServerHeartbeatACK(QSharedPointer<ReceivedMessage> message);
|
||||||
|
|
||||||
private slots:
|
|
||||||
void setupPendingAssignmentCredits();
|
void setupPendingAssignmentCredits();
|
||||||
void sendPendingTransactionsToServer();
|
void sendPendingTransactionsToServer();
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ private:
|
||||||
|
|
||||||
void getTemporaryName(bool force = false);
|
void getTemporaryName(bool force = false);
|
||||||
|
|
||||||
static bool packetVersionMatch(const udt::Packet& packet);
|
static bool isPacketVerified(const udt::Packet& packet);
|
||||||
|
|
||||||
bool resetAccountManagerAccessToken();
|
bool resetAccountManagerAccessToken();
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@ Column {
|
||||||
property string metaverseServerUrl: '';
|
property string metaverseServerUrl: '';
|
||||||
property string actions: 'snapshot';
|
property string actions: 'snapshot';
|
||||||
// sendToScript doesn't get wired until after everything gets created. So we have to queue fillDestinations on nextTick.
|
// sendToScript doesn't get wired until after everything gets created. So we have to queue fillDestinations on nextTick.
|
||||||
Component.onCompleted: delay.start();
|
|
||||||
property string labelText: actions;
|
property string labelText: actions;
|
||||||
property string filter: '';
|
property string filter: '';
|
||||||
onFilterChanged: filterChoicesByText();
|
onFilterChanged: filterChoicesByText();
|
||||||
|
@ -125,11 +124,9 @@ Column {
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
property var delay: Timer { // No setTimeout or nextTick in QML.
|
|
||||||
interval: 0;
|
|
||||||
onTriggered: fillDestinations();
|
|
||||||
}
|
|
||||||
function fillDestinations() { // Public
|
function fillDestinations() { // Public
|
||||||
|
console.debug('Feed::fillDestinations()')
|
||||||
|
|
||||||
function report(label, error) {
|
function report(label, error) {
|
||||||
console.log(label, actions, error || 'ok', allStories.length, 'filtered to', suggestions.count);
|
console.log(label, actions, error || 'ok', allStories.length, 'filtered to', suggestions.count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,11 +39,24 @@ StackView {
|
||||||
property var rpcCounter: 0;
|
property var rpcCounter: 0;
|
||||||
signal sendToScript(var message);
|
signal sendToScript(var message);
|
||||||
function rpc(method, parameters, callback) {
|
function rpc(method, parameters, callback) {
|
||||||
|
console.debug('TabletAddressDialog: rpc: method = ', method, 'parameters = ', parameters, 'callback = ', callback)
|
||||||
|
|
||||||
rpcCalls[rpcCounter] = callback;
|
rpcCalls[rpcCounter] = callback;
|
||||||
var message = {method: method, params: parameters, id: rpcCounter++, jsonrpc: "2.0"};
|
var message = {method: method, params: parameters, id: rpcCounter++, jsonrpc: "2.0"};
|
||||||
sendToScript(message);
|
sendToScript(message);
|
||||||
}
|
}
|
||||||
function fromScript(message) {
|
function fromScript(message) {
|
||||||
|
if (message.method === 'refreshFeeds') {
|
||||||
|
var feeds = [happeningNow, places, snapshots];
|
||||||
|
console.debug('TabletAddressDialog::fromScript: refreshFeeds', 'feeds = ', feeds);
|
||||||
|
|
||||||
|
feeds.forEach(function(feed) {
|
||||||
|
Qt.callLater(feed.fillDestinations);
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var callback = rpcCalls[message.id];
|
var callback = rpcCalls[message.id];
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
console.log('No callback for message fromScript', JSON.stringify(message));
|
console.log('No callback for message fromScript', JSON.stringify(message));
|
||||||
|
|
|
@ -1735,6 +1735,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
|
|
||||||
connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
|
connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
|
||||||
|
|
||||||
|
// Setup the mouse ray pick and related operators
|
||||||
|
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(_rayPickManager.createRayPick(
|
||||||
|
RayPickFilter(DependencyManager::get<RayPickScriptingInterface>()->PICK_ENTITIES() | DependencyManager::get<RayPickScriptingInterface>()->PICK_INCLUDE_NONCOLLIDABLE()),
|
||||||
|
0.0f, true));
|
||||||
|
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([&](QUuid rayPickID) {
|
||||||
|
RayToEntityIntersectionResult entityResult;
|
||||||
|
RayPickResult result = _rayPickManager.getPrevRayPickResult(rayPickID);
|
||||||
|
entityResult.intersects = result.type != DependencyManager::get<RayPickScriptingInterface>()->INTERSECTED_NONE();
|
||||||
|
if (entityResult.intersects) {
|
||||||
|
entityResult.intersection = result.intersection;
|
||||||
|
entityResult.distance = result.distance;
|
||||||
|
entityResult.surfaceNormal = result.surfaceNormal;
|
||||||
|
entityResult.entityID = result.objectID;
|
||||||
|
entityResult.entity = DependencyManager::get<EntityTreeRenderer>()->getTree()->findEntityByID(entityResult.entityID);
|
||||||
|
}
|
||||||
|
return entityResult;
|
||||||
|
});
|
||||||
|
DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([&](QUuid rayPickID, bool value) {
|
||||||
|
_rayPickManager.setPrecisionPicking(rayPickID, value);
|
||||||
|
});
|
||||||
|
|
||||||
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
|
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
// You cannot use editRenderState to change the overlay type of any part of the laser pointer. You can only edit the properties of the existing overlays.
|
// You cannot use editRenderState to change the overlay type of any part of the laser pointer. You can only edit the properties of the existing overlays.
|
||||||
void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
|
void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
|
||||||
|
|
||||||
|
void setPrecisionPicking(const bool precisionPicking) { DependencyManager::get<RayPickScriptingInterface>()->setPrecisionPicking(_rayPickUID, precisionPicking); }
|
||||||
void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get<RayPickScriptingInterface>()->setIgnoreEntities(_rayPickUID, ignoreEntities); }
|
void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get<RayPickScriptingInterface>()->setIgnoreEntities(_rayPickUID, ignoreEntities); }
|
||||||
void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get<RayPickScriptingInterface>()->setIncludeEntities(_rayPickUID, includeEntities); }
|
void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get<RayPickScriptingInterface>()->setIncludeEntities(_rayPickUID, includeEntities); }
|
||||||
void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { DependencyManager::get<RayPickScriptingInterface>()->setIgnoreOverlays(_rayPickUID, ignoreOverlays); }
|
void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { DependencyManager::get<RayPickScriptingInterface>()->setIgnoreOverlays(_rayPickUID, ignoreOverlays); }
|
||||||
|
|
|
@ -97,6 +97,14 @@ void LaserPointerManager::update() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LaserPointerManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
|
||||||
|
QReadLocker lock(&_containsLock);
|
||||||
|
if (_laserPointers.contains(uid)) {
|
||||||
|
QWriteLocker laserLock(_laserPointerLocks[uid].get());
|
||||||
|
_laserPointers[uid]->setPrecisionPicking(precisionPicking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
||||||
QReadLocker lock(&_containsLock);
|
QReadLocker lock(&_containsLock);
|
||||||
if (_laserPointers.contains(uid)) {
|
if (_laserPointers.contains(uid)) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
void editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
|
void editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
|
||||||
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
||||||
|
|
||||||
|
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||||
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||||
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||||
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||||
|
|
|
@ -30,6 +30,7 @@ public slots:
|
||||||
Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
|
Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
|
||||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
|
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
|
||||||
|
|
||||||
|
Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking) { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); }
|
||||||
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); }
|
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); }
|
||||||
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { qApp->getLaserPointerManager().setIncludeEntities(uid, includeEntities); }
|
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { qApp->getLaserPointerManager().setIncludeEntities(uid, includeEntities); }
|
||||||
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { qApp->getLaserPointerManager().setIgnoreOverlays(uid, ignoreOverlays); }
|
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { qApp->getLaserPointerManager().setIgnoreOverlays(uid, ignoreOverlays); }
|
||||||
|
|
|
@ -41,12 +41,14 @@ public:
|
||||||
// The key is the Flags
|
// The key is the Flags
|
||||||
Flags _flags;
|
Flags _flags;
|
||||||
|
|
||||||
RayPickFilter() : _flags(PICK_NOTHING) {}
|
RayPickFilter() : _flags(getBitMask(PICK_NOTHING)) {}
|
||||||
RayPickFilter(const Flags& flags) : _flags(flags) {}
|
RayPickFilter(const Flags& flags) : _flags(flags) {}
|
||||||
|
|
||||||
bool operator== (const RayPickFilter& rhs) const { return _flags == rhs._flags; }
|
bool operator== (const RayPickFilter& rhs) const { return _flags == rhs._flags; }
|
||||||
bool operator!= (const RayPickFilter& rhs) const { return _flags != rhs._flags; }
|
bool operator!= (const RayPickFilter& rhs) const { return _flags != rhs._flags; }
|
||||||
|
|
||||||
|
void setFlag(FlagBit flag, bool value) { _flags[flag] = value; }
|
||||||
|
|
||||||
bool doesPickNothing() const { return _flags[PICK_NOTHING]; }
|
bool doesPickNothing() const { return _flags[PICK_NOTHING]; }
|
||||||
bool doesPickEntities() const { return _flags[PICK_ENTITIES]; }
|
bool doesPickEntities() const { return _flags[PICK_ENTITIES]; }
|
||||||
bool doesPickOverlays() const { return _flags[PICK_OVERLAYS]; }
|
bool doesPickOverlays() const { return _flags[PICK_OVERLAYS]; }
|
||||||
|
@ -61,27 +63,27 @@ public:
|
||||||
|
|
||||||
// Helpers for RayPickManager
|
// Helpers for RayPickManager
|
||||||
Flags getEntityFlags() const {
|
Flags getEntityFlags() const {
|
||||||
Flags toReturn(PICK_ENTITIES);
|
unsigned int toReturn = getBitMask(PICK_ENTITIES);
|
||||||
if (doesPickInvisible()) {
|
if (doesPickInvisible()) {
|
||||||
toReturn |= Flags(PICK_INCLUDE_INVISIBLE);
|
toReturn |= getBitMask(PICK_INCLUDE_INVISIBLE);
|
||||||
}
|
}
|
||||||
if (doesPickNonCollidable()) {
|
if (doesPickNonCollidable()) {
|
||||||
toReturn |= Flags(PICK_INCLUDE_NONCOLLIDABLE);
|
toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
|
||||||
}
|
}
|
||||||
return toReturn;
|
return Flags(toReturn);
|
||||||
}
|
}
|
||||||
Flags getOverlayFlags() const {
|
Flags getOverlayFlags() const {
|
||||||
Flags toReturn(PICK_OVERLAYS);
|
unsigned int toReturn = getBitMask(PICK_OVERLAYS);
|
||||||
if (doesPickInvisible()) {
|
if (doesPickInvisible()) {
|
||||||
toReturn |= Flags(PICK_INCLUDE_INVISIBLE);
|
toReturn |= getBitMask(PICK_INCLUDE_INVISIBLE);
|
||||||
}
|
}
|
||||||
if (doesPickNonCollidable()) {
|
if (doesPickNonCollidable()) {
|
||||||
toReturn |= Flags(PICK_INCLUDE_NONCOLLIDABLE);
|
toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
|
||||||
}
|
}
|
||||||
return toReturn;
|
return Flags(toReturn);
|
||||||
}
|
}
|
||||||
Flags getAvatarFlags() const { return Flags(PICK_AVATARS); }
|
Flags getAvatarFlags() const { return Flags(getBitMask(PICK_AVATARS)); }
|
||||||
Flags getHUDFlags() const { return Flags(PICK_HUD); }
|
Flags getHUDFlags() const { return Flags(getBitMask(PICK_HUD)); }
|
||||||
|
|
||||||
static unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
|
static unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
|
||||||
|
|
||||||
|
@ -98,10 +100,12 @@ public:
|
||||||
void disable() { _enabled = false; }
|
void disable() { _enabled = false; }
|
||||||
|
|
||||||
const RayPickFilter& getFilter() { return _filter; }
|
const RayPickFilter& getFilter() { return _filter; }
|
||||||
const float& getMaxDistance() { return _maxDistance; }
|
float getMaxDistance() { return _maxDistance; }
|
||||||
const bool& isEnabled() { return _enabled; }
|
bool isEnabled() { return _enabled; }
|
||||||
const RayPickResult& getPrevRayPickResult() { return _prevResult; }
|
const RayPickResult& getPrevRayPickResult() { return _prevResult; }
|
||||||
|
|
||||||
|
void setPrecisionPicking(bool precisionPicking) { _filter.setFlag(RayPickFilter::PICK_COURSE, !precisionPicking); }
|
||||||
|
|
||||||
void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; }
|
void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; }
|
||||||
|
|
||||||
const QVector<EntityItemID>& getIgnoreEntites() { return _ignoreEntities; }
|
const QVector<EntityItemID>& getIgnoreEntites() { return _ignoreEntities; }
|
||||||
|
|
|
@ -64,10 +64,11 @@ void RayPickManager::update() {
|
||||||
RayToEntityIntersectionResult entityRes;
|
RayToEntityIntersectionResult entityRes;
|
||||||
bool fromCache = true;
|
bool fromCache = true;
|
||||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
bool invisible = rayPick->getFilter().doesPickInvisible();
|
||||||
bool noncollidable = rayPick->getFilter().doesPickNonCollidable();
|
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||||
RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags();
|
RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags();
|
||||||
if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) {
|
if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) {
|
||||||
entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, true, rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !noncollidable);
|
entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
|
||||||
|
rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !nonCollidable);
|
||||||
fromCache = false;
|
fromCache = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,10 +82,11 @@ void RayPickManager::update() {
|
||||||
RayToOverlayIntersectionResult overlayRes;
|
RayToOverlayIntersectionResult overlayRes;
|
||||||
bool fromCache = true;
|
bool fromCache = true;
|
||||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
bool invisible = rayPick->getFilter().doesPickInvisible();
|
||||||
bool noncollidable = rayPick->getFilter().doesPickNonCollidable();
|
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||||
RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags();
|
RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags();
|
||||||
if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) {
|
if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) {
|
||||||
overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, true, rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !noncollidable);
|
overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
|
||||||
|
rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !nonCollidable);
|
||||||
fromCache = false;
|
fromCache = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +206,14 @@ const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) {
|
||||||
return RayPickResult();
|
return RayPickResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RayPickManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
|
||||||
|
QReadLocker containsLock(&_containsLock);
|
||||||
|
if (_rayPicks.contains(uid)) {
|
||||||
|
QWriteLocker lock(_rayPickLocks[uid].get());
|
||||||
|
_rayPicks[uid]->setPrecisionPicking(precisionPicking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
||||||
QReadLocker containsLock(&_containsLock);
|
QReadLocker containsLock(&_containsLock);
|
||||||
if (_rayPicks.contains(uid)) {
|
if (_rayPicks.contains(uid)) {
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
void disableRayPick(const QUuid uid);
|
void disableRayPick(const QUuid uid);
|
||||||
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
||||||
|
|
||||||
|
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||||
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||||
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||||
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||||
|
|
|
@ -82,6 +82,10 @@ RayPickResult RayPickScriptingInterface::getPrevRayPickResult(QUuid uid) {
|
||||||
return qApp->getRayPickManager().getPrevRayPickResult(uid);
|
return qApp->getRayPickManager().getPrevRayPickResult(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RayPickScriptingInterface::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
|
||||||
|
qApp->getRayPickManager().setPrecisionPicking(uid, precisionPicking);
|
||||||
|
}
|
||||||
|
|
||||||
void RayPickScriptingInterface::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
void RayPickScriptingInterface::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
||||||
qApp->getRayPickManager().setIgnoreEntities(uid, ignoreEntities);
|
qApp->getRayPickManager().setIgnoreEntities(uid, ignoreEntities);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ public slots:
|
||||||
Q_INVOKABLE void removeRayPick(QUuid uid);
|
Q_INVOKABLE void removeRayPick(QUuid uid);
|
||||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid);
|
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid);
|
||||||
|
|
||||||
|
Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||||
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||||
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||||
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||||
|
@ -50,7 +51,6 @@ public slots:
|
||||||
Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
|
Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
|
||||||
Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
|
Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); }
|
unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); }
|
||||||
unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); }
|
unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); }
|
||||||
unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); }
|
unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); }
|
||||||
|
|
|
@ -264,7 +264,7 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
const render::ShapeKey Circle3DOverlay::getShapeKey() {
|
const render::ShapeKey Circle3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit();
|
auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit();
|
||||||
if (getAlpha() != 1.0f) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||||
|
|
|
@ -117,7 +117,7 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
const render::ShapeKey Cube3DOverlay::getShapeKey() {
|
const render::ShapeKey Cube3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder();
|
auto builder = render::ShapeKey::Builder();
|
||||||
if (getAlpha() != 1.0f) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "GeometryUtil.h"
|
#include "GeometryUtil.h"
|
||||||
|
|
||||||
|
#include "AbstractViewStateInterface.h"
|
||||||
|
|
||||||
QString const Image3DOverlay::TYPE = "image3d";
|
QString const Image3DOverlay::TYPE = "image3d";
|
||||||
|
|
||||||
|
@ -58,12 +59,29 @@ void Image3DOverlay::render(RenderArgs* args) {
|
||||||
if (!_isLoaded) {
|
if (!_isLoaded) {
|
||||||
_isLoaded = true;
|
_isLoaded = true;
|
||||||
_texture = DependencyManager::get<TextureCache>()->getTexture(_url);
|
_texture = DependencyManager::get<TextureCache>()->getTexture(_url);
|
||||||
|
_textureIsLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_visible || !getParentVisible() || !_texture || !_texture->isLoaded()) {
|
if (!_visible || !getParentVisible() || !_texture || !_texture->isLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Once the texture has loaded, check if we need to update the render item because of transparency
|
||||||
|
if (!_textureIsLoaded && _texture && _texture->getGPUTexture()) {
|
||||||
|
_textureIsLoaded = true;
|
||||||
|
bool prevAlphaTexture = _alphaTexture;
|
||||||
|
_alphaTexture = _texture->getGPUTexture()->getUsage().isAlpha();
|
||||||
|
if (_alphaTexture != prevAlphaTexture) {
|
||||||
|
auto itemID = getRenderItemID();
|
||||||
|
if (render::Item::isValidID(itemID)) {
|
||||||
|
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||||
|
render::Transaction transaction;
|
||||||
|
transaction.updateItem(itemID);
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
gpu::Batch* batch = args->_batch;
|
gpu::Batch* batch = args->_batch;
|
||||||
|
|
||||||
|
@ -92,9 +110,9 @@ void Image3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
glm::vec2 topLeft(-x, -y);
|
glm::vec2 topLeft(-x, -y);
|
||||||
glm::vec2 bottomRight(x, y);
|
glm::vec2 bottomRight(x, y);
|
||||||
glm::vec2 texCoordTopLeft(fromImage.x() / imageWidth, fromImage.y() / imageHeight);
|
glm::vec2 texCoordTopLeft((fromImage.x() + 0.5f) / imageWidth, (fromImage.y() + 0.5f) / imageHeight);
|
||||||
glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width()) / imageWidth,
|
glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth,
|
||||||
(fromImage.y() + fromImage.height()) / imageHeight);
|
(fromImage.y() + fromImage.height() - 0.5f) / imageHeight);
|
||||||
|
|
||||||
const float MAX_COLOR = 255.0f;
|
const float MAX_COLOR = 255.0f;
|
||||||
xColor color = getColor();
|
xColor color = getColor();
|
||||||
|
@ -126,7 +144,7 @@ const render::ShapeKey Image3DOverlay::getShapeKey() {
|
||||||
if (_emissive || shouldDrawHUDLayer()) {
|
if (_emissive || shouldDrawHUDLayer()) {
|
||||||
builder.withUnlit();
|
builder.withUnlit();
|
||||||
}
|
}
|
||||||
if (getAlpha() != 1.0f) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
|
|
||||||
void setProperties(const QVariantMap& properties) override;
|
void setProperties(const QVariantMap& properties) override;
|
||||||
QVariant getProperty(const QString& property) override;
|
QVariant getProperty(const QString& property) override;
|
||||||
|
bool isTransparent() override { return Base3DOverlay::isTransparent() || _alphaTexture; }
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
BoxFace& face, glm::vec3& surfaceNormal) override;
|
BoxFace& face, glm::vec3& surfaceNormal) override;
|
||||||
|
@ -48,6 +49,8 @@ public:
|
||||||
private:
|
private:
|
||||||
QString _url;
|
QString _url;
|
||||||
NetworkTexturePointer _texture;
|
NetworkTexturePointer _texture;
|
||||||
|
bool _textureIsLoaded { false };
|
||||||
|
bool _alphaTexture { false };
|
||||||
bool _emissive { false };
|
bool _emissive { false };
|
||||||
|
|
||||||
QRect _fromImage; // where from in the image to sample
|
QRect _fromImage; // where from in the image to sample
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
|
|
||||||
|
#include "AbstractViewStateInterface.h"
|
||||||
|
|
||||||
QString const Line3DOverlay::TYPE = "line3d";
|
QString const Line3DOverlay::TYPE = "line3d";
|
||||||
|
|
||||||
|
@ -149,7 +150,7 @@ void Line3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
const render::ShapeKey Line3DOverlay::getShapeKey() {
|
const render::ShapeKey Line3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||||
if (getAlpha() != 1.0f || _glow > 0.0f) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
@ -222,9 +223,17 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) {
|
||||||
|
|
||||||
auto glow = properties["glow"];
|
auto glow = properties["glow"];
|
||||||
if (glow.isValid()) {
|
if (glow.isValid()) {
|
||||||
|
float prevGlow = _glow;
|
||||||
setGlow(glow.toFloat());
|
setGlow(glow.toFloat());
|
||||||
if (_glow > 0.0f) {
|
// Update our payload key if necessary to handle transparency
|
||||||
_alpha = 0.5f;
|
if ((prevGlow <= 0.0f && _glow > 0.0f) || (prevGlow > 0.0f && _glow <= 0.0f)) {
|
||||||
|
auto itemID = getRenderItemID();
|
||||||
|
if (render::Item::isValidID(itemID)) {
|
||||||
|
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||||
|
render::Transaction transaction;
|
||||||
|
transaction.updateItem(itemID);
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
|
|
||||||
void setProperties(const QVariantMap& properties) override;
|
void setProperties(const QVariantMap& properties) override;
|
||||||
QVariant getProperty(const QString& property) override;
|
QVariant getProperty(const QString& property) override;
|
||||||
|
bool isTransparent() override { return Base3DOverlay::isTransparent() || _glow > 0.0f; }
|
||||||
|
|
||||||
virtual Line3DOverlay* createClone() const override;
|
virtual Line3DOverlay* createClone() const override;
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ public:
|
||||||
bool isLoaded() { return _isLoaded; }
|
bool isLoaded() { return _isLoaded; }
|
||||||
bool getVisible() const { return _visible; }
|
bool getVisible() const { return _visible; }
|
||||||
bool shouldDrawHUDLayer() const { return _drawHUDLayer; }
|
bool shouldDrawHUDLayer() const { return _drawHUDLayer; }
|
||||||
|
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
|
||||||
xColor getColor();
|
xColor getColor();
|
||||||
float getAlpha();
|
float getAlpha();
|
||||||
Anchor getAnchor() const { return _anchor; }
|
Anchor getAnchor() const { return _anchor; }
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace render {
|
||||||
if (std::static_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront()) {
|
if (std::static_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront()) {
|
||||||
builder.withLayered();
|
builder.withLayered();
|
||||||
}
|
}
|
||||||
if (overlay->getAlphaPulse() != 0.0f || overlay->getAlpha() != 1.0f) {
|
if (overlay->isTransparent()) {
|
||||||
builder.withTransparent();
|
builder.withTransparent();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -110,7 +110,7 @@ void Rectangle3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||||
if (getAlpha() != 1.0f) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -62,7 +62,7 @@ void Shape3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
const render::ShapeKey Shape3DOverlay::getShapeKey() {
|
const render::ShapeKey Shape3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder();
|
auto builder = render::ShapeKey::Builder();
|
||||||
if (getAlpha() != 1.0f) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||||
|
|
|
@ -59,7 +59,7 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
const render::ShapeKey Sphere3DOverlay::getShapeKey() {
|
const render::ShapeKey Sphere3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder();
|
auto builder = render::ShapeKey::Builder();
|
||||||
if (getAlpha() != 1.0f) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||||
|
|
|
@ -143,7 +143,7 @@ void Text3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
const render::ShapeKey Text3DOverlay::getShapeKey() {
|
const render::ShapeKey Text3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder();
|
auto builder = render::ShapeKey::Builder();
|
||||||
if (getAlpha() != 1.0f) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -318,8 +318,8 @@ void Web3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const render::ShapeKey Web3DOverlay::getShapeKey() {
|
const render::ShapeKey Web3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
|
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline();
|
||||||
if (getAlpha() != 1.0f) {
|
if (isTransparent()) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
#include "AnimUtil.h"
|
#include "AnimUtil.h"
|
||||||
#include "IKTarget.h"
|
#include "IKTarget.h"
|
||||||
|
|
||||||
|
static int nextRigId = 1;
|
||||||
|
static std::map<int, Rig*> rigRegistry;
|
||||||
|
static std::mutex rigRegistryMutex;
|
||||||
|
|
||||||
static bool isEqual(const glm::vec3& u, const glm::vec3& v) {
|
static bool isEqual(const glm::vec3& u, const glm::vec3& v) {
|
||||||
const float EPSILON = 0.0001f;
|
const float EPSILON = 0.0001f;
|
||||||
return glm::length(u - v) / glm::length(u) <= EPSILON;
|
return glm::length(u - v) / glm::length(u) <= EPSILON;
|
||||||
|
@ -49,6 +53,26 @@ const glm::vec3 DEFAULT_RIGHT_EYE_POS(-0.3f, 0.9f, 0.0f);
|
||||||
const glm::vec3 DEFAULT_LEFT_EYE_POS(0.3f, 0.9f, 0.0f);
|
const glm::vec3 DEFAULT_LEFT_EYE_POS(0.3f, 0.9f, 0.0f);
|
||||||
const glm::vec3 DEFAULT_HEAD_POS(0.0f, 0.75f, 0.0f);
|
const glm::vec3 DEFAULT_HEAD_POS(0.0f, 0.75f, 0.0f);
|
||||||
|
|
||||||
|
Rig::Rig() {
|
||||||
|
// Ensure thread-safe access to the rigRegistry.
|
||||||
|
std::lock_guard<std::mutex> guard(rigRegistryMutex);
|
||||||
|
|
||||||
|
// Insert this newly allocated rig into the rig registry
|
||||||
|
_rigId = nextRigId;
|
||||||
|
rigRegistry[_rigId] = this;
|
||||||
|
nextRigId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rig::~Rig() {
|
||||||
|
// Ensure thread-safe access to the rigRegstry, but also prevent the rig from being deleted
|
||||||
|
// while Rig::animationStateHandlerResult is being invoked on a script thread.
|
||||||
|
std::lock_guard<std::mutex> guard(rigRegistryMutex);
|
||||||
|
auto iter = rigRegistry.find(_rigId);
|
||||||
|
if (iter != rigRegistry.end()) {
|
||||||
|
rigRegistry.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||||
|
|
||||||
UserAnimState::ClipNodeEnum clipNodeEnum;
|
UserAnimState::ClipNodeEnum clipNodeEnum;
|
||||||
|
@ -935,8 +959,19 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
|
||||||
int identifier = data.key();
|
int identifier = data.key();
|
||||||
StateHandler& value = data.value();
|
StateHandler& value = data.value();
|
||||||
QScriptValue& function = value.function;
|
QScriptValue& function = value.function;
|
||||||
auto handleResult = [this, identifier](QScriptValue result) { // called in script thread to get the result back to us.
|
int rigId = _rigId;
|
||||||
animationStateHandlerResult(identifier, result);
|
auto handleResult = [rigId, identifier](QScriptValue result) { // called in script thread to get the result back to us.
|
||||||
|
// Hold the rigRegistryMutex to ensure thread-safe access to the rigRegistry, but
|
||||||
|
// also to prevent the rig from being deleted while this lambda is being executed.
|
||||||
|
std::lock_guard<std::mutex> guard(rigRegistryMutex);
|
||||||
|
|
||||||
|
// if the rig pointer is in the registry, it has not been deleted yet.
|
||||||
|
auto iter = rigRegistry.find(rigId);
|
||||||
|
if (iter != rigRegistry.end()) {
|
||||||
|
Rig* rig = iter->second;
|
||||||
|
assert(rig);
|
||||||
|
rig->animationStateHandlerResult(identifier, result);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// invokeMethod makes a copy of the args, and copies of AnimVariantMap do copy the underlying map, so this will correctly capture
|
// invokeMethod makes a copy of the args, and copies of AnimVariantMap do copy the underlying map, so this will correctly capture
|
||||||
// the state of _animVars and allow continued changes to _animVars in this thread without conflict.
|
// the state of _animVars and allow continued changes to _animVars in this thread without conflict.
|
||||||
|
|
|
@ -97,8 +97,8 @@ public:
|
||||||
Hover
|
Hover
|
||||||
};
|
};
|
||||||
|
|
||||||
Rig() {}
|
Rig();
|
||||||
virtual ~Rig() {}
|
virtual ~Rig();
|
||||||
|
|
||||||
void destroyAnimGraph();
|
void destroyAnimGraph();
|
||||||
|
|
||||||
|
@ -372,6 +372,8 @@ protected:
|
||||||
|
|
||||||
glm::vec3 _prevLeftHandPoleVector { -Vectors::UNIT_Z };
|
glm::vec3 _prevLeftHandPoleVector { -Vectors::UNIT_Z };
|
||||||
bool _prevLeftHandPoleVectorValid { false };
|
bool _prevLeftHandPoleVectorValid { false };
|
||||||
|
|
||||||
|
int _rigId;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__Rig__) */
|
#endif /* defined(__hifi__Rig__) */
|
||||||
|
|
|
@ -53,7 +53,6 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
||||||
_viewState(viewState),
|
_viewState(viewState),
|
||||||
_scriptingServices(scriptingServices),
|
_scriptingServices(scriptingServices),
|
||||||
_displayModelBounds(false),
|
_displayModelBounds(false),
|
||||||
_dontDoPrecisionPicking(false),
|
|
||||||
_layeredZones(this)
|
_layeredZones(this)
|
||||||
{
|
{
|
||||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory)
|
REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory)
|
||||||
|
@ -428,28 +427,6 @@ void EntityTreeRenderer::deleteReleasedModels() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
|
|
||||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude,
|
|
||||||
const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly) {
|
|
||||||
RayToEntityIntersectionResult result;
|
|
||||||
if (_tree) {
|
|
||||||
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_tree);
|
|
||||||
|
|
||||||
OctreeElementPointer element;
|
|
||||||
EntityItemPointer intersectedEntity = NULL;
|
|
||||||
result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction,
|
|
||||||
entityIdsToInclude, entityIdsToDiscard, visibleOnly, collidableOnly, precisionPicking,
|
|
||||||
element, result.distance, result.face, result.surfaceNormal,
|
|
||||||
(void**)&intersectedEntity, lockType, &result.accurate);
|
|
||||||
if (result.intersects && intersectedEntity) {
|
|
||||||
result.entityID = intersectedEntity->getEntityItemID();
|
|
||||||
result.intersection = ray.origin + (ray.direction * result.distance);
|
|
||||||
result.entity = intersectedEntity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) {
|
void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) {
|
||||||
|
|
||||||
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
||||||
|
@ -530,11 +507,10 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
|
||||||
if (!_tree || _shuttingDown) {
|
if (!_tree || _shuttingDown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
||||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||||
|
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
|
||||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
|
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
|
||||||
|
|
||||||
|
@ -579,11 +555,10 @@ void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
|
||||||
if (!_tree || _shuttingDown) {
|
if (!_tree || _shuttingDown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent");
|
||||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||||
|
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
|
||||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
//qCDebug(entitiesrenderer) << "mouseDoublePressEvent over entity:" << rayPickResult.entityID;
|
//qCDebug(entitiesrenderer) << "mouseDoublePressEvent over entity:" << rayPickResult.entityID;
|
||||||
|
|
||||||
|
@ -622,8 +597,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
|
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
|
||||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
//qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
|
//qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
|
||||||
|
|
||||||
|
@ -671,14 +645,11 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
||||||
if (!_tree || _shuttingDown) {
|
if (!_tree || _shuttingDown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
|
||||||
|
|
||||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||||
|
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||||
bool precisionPicking = false; // for mouse moves we do not do precision picking
|
|
||||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking);
|
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
|
|
||||||
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
||||||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
||||||
pos2D, rayPickResult.intersection,
|
pos2D, rayPickResult.intersection,
|
||||||
|
|
|
@ -59,6 +59,10 @@ public:
|
||||||
float getEntityLoadingPriority(const EntityItem& item) const { return _calculateEntityLoadingPriorityFunc(item); }
|
float getEntityLoadingPriority(const EntityItem& item) const { return _calculateEntityLoadingPriorityFunc(item); }
|
||||||
void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { this->_calculateEntityLoadingPriorityFunc = fn; }
|
void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { this->_calculateEntityLoadingPriorityFunc = fn; }
|
||||||
|
|
||||||
|
void setMouseRayPickID(QUuid rayPickID) { _mouseRayPickID = rayPickID; }
|
||||||
|
void setMouseRayPickResultOperator(std::function<RayToEntityIntersectionResult(QUuid)> getPrevRayPickResultOperator) { _getPrevRayPickResultOperator = getPrevRayPickResultOperator; }
|
||||||
|
void setSetPrecisionPickingOperator(std::function<void(QUuid, bool)> setPrecisionPickingOperator) { _setPrecisionPickingOperator = setPrecisionPickingOperator; }
|
||||||
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
@ -130,7 +134,7 @@ public slots:
|
||||||
|
|
||||||
// optional slots that can be wired to menu items
|
// optional slots that can be wired to menu items
|
||||||
void setDisplayModelBounds(bool value) { _displayModelBounds = value; }
|
void setDisplayModelBounds(bool value) { _displayModelBounds = value; }
|
||||||
void setDontDoPrecisionPicking(bool value) { _dontDoPrecisionPicking = value; }
|
void setPrecisionPicking(bool value) { _setPrecisionPickingOperator(_mouseRayPickID, value); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual OctreePointer createTree() override {
|
virtual OctreePointer createTree() override {
|
||||||
|
@ -150,10 +154,6 @@ private:
|
||||||
void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false);
|
void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false);
|
||||||
|
|
||||||
QList<ModelPointer> _releasedModels;
|
QList<ModelPointer> _releasedModels;
|
||||||
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
|
|
||||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude = QVector<EntityItemID>(),
|
|
||||||
const QVector<EntityItemID>& entityIdsToDiscard = QVector<EntityItemID>(), bool visibleOnly=false,
|
|
||||||
bool collidableOnly = false);
|
|
||||||
|
|
||||||
EntityItemID _currentHoverOverEntityID;
|
EntityItemID _currentHoverOverEntityID;
|
||||||
EntityItemID _currentClickingOnEntityID;
|
EntityItemID _currentClickingOnEntityID;
|
||||||
|
@ -176,12 +176,15 @@ private:
|
||||||
AbstractViewStateInterface* _viewState;
|
AbstractViewStateInterface* _viewState;
|
||||||
AbstractScriptingServicesInterface* _scriptingServices;
|
AbstractScriptingServicesInterface* _scriptingServices;
|
||||||
bool _displayModelBounds;
|
bool _displayModelBounds;
|
||||||
bool _dontDoPrecisionPicking;
|
|
||||||
|
|
||||||
bool _shuttingDown { false };
|
bool _shuttingDown { false };
|
||||||
|
|
||||||
QMultiMap<QUrl, EntityItemID> _waitingOnPreload;
|
QMultiMap<QUrl, EntityItemID> _waitingOnPreload;
|
||||||
|
|
||||||
|
QUuid _mouseRayPickID;
|
||||||
|
std::function<RayToEntityIntersectionResult(QUuid)> _getPrevRayPickResultOperator;
|
||||||
|
std::function<void(QUuid, bool)> _setPrecisionPickingOperator;
|
||||||
|
|
||||||
class LayeredZone {
|
class LayeredZone {
|
||||||
public:
|
public:
|
||||||
LayeredZone(std::shared_ptr<ZoneEntityItem> zone, QUuid id, float volume) : zone(zone), id(id), volume(volume) {}
|
LayeredZone(std::shared_ptr<ZoneEntityItem> zone, QUuid id, float volume) : zone(zone), id(id), volume(volume) {}
|
||||||
|
|
|
@ -280,24 +280,24 @@ void EntitySimulation::moveSimpleKinematics(const quint64& now) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntitySimulation::addDynamic(EntityDynamicPointer dynamic) {
|
void EntitySimulation::addDynamic(EntityDynamicPointer dynamic) {
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_dynamicsMutex);
|
||||||
_dynamicsToAdd += dynamic;
|
_dynamicsToAdd += dynamic;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntitySimulation::removeDynamic(const QUuid dynamicID) {
|
void EntitySimulation::removeDynamic(const QUuid dynamicID) {
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_dynamicsMutex);
|
||||||
_dynamicsToRemove += dynamicID;
|
_dynamicsToRemove += dynamicID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntitySimulation::removeDynamics(QList<QUuid> dynamicIDsToRemove) {
|
void EntitySimulation::removeDynamics(QList<QUuid> dynamicIDsToRemove) {
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_dynamicsMutex);
|
||||||
foreach(QUuid uuid, dynamicIDsToRemove) {
|
foreach(QUuid uuid, dynamicIDsToRemove) {
|
||||||
_dynamicsToRemove.insert(uuid);
|
_dynamicsToRemove.insert(uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntitySimulation::applyDynamicChanges() {
|
void EntitySimulation::applyDynamicChanges() {
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_dynamicsMutex);
|
||||||
_dynamicsToAdd.clear();
|
_dynamicsToAdd.clear();
|
||||||
_dynamicsToRemove.clear();
|
_dynamicsToRemove.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,7 @@ protected:
|
||||||
SetOfEntities _simpleKinematicEntities; // entities undergoing non-colliding kinematic motion
|
SetOfEntities _simpleKinematicEntities; // entities undergoing non-colliding kinematic motion
|
||||||
QList<EntityDynamicPointer> _dynamicsToAdd;
|
QList<EntityDynamicPointer> _dynamicsToAdd;
|
||||||
QSet<QUuid> _dynamicsToRemove;
|
QSet<QUuid> _dynamicsToRemove;
|
||||||
|
QMutex _dynamicsMutex { QMutex::Recursive };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SetOfEntities _entitiesToDelete; // entities simulation decided needed to be deleted (EntityTree will actually delete)
|
SetOfEntities _entitiesToDelete; // entities simulation decided needed to be deleted (EntityTree will actually delete)
|
||||||
|
|
|
@ -113,6 +113,18 @@ QString HifiSockAddr::toString() const {
|
||||||
return _address.toString() + ":" + QString::number(_port);
|
return _address.toString() + ":" + QString::number(_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HifiSockAddr::hasPrivateAddress() const {
|
||||||
|
// an address is private if it is loopback or falls in any of the RFC1918 address spaces
|
||||||
|
const QPair<QHostAddress, int> TWENTY_FOUR_BIT_BLOCK = { QHostAddress("10.0.0.0"), 8 };
|
||||||
|
const QPair<QHostAddress, int> TWENTY_BIT_BLOCK = { QHostAddress("172.16.0.0") , 12 };
|
||||||
|
const QPair<QHostAddress, int> SIXTEEN_BIT_BLOCK = { QHostAddress("192.168.0.0"), 16 };
|
||||||
|
|
||||||
|
return _address.isLoopback()
|
||||||
|
|| _address.isInSubnet(TWENTY_FOUR_BIT_BLOCK)
|
||||||
|
|| _address.isInSubnet(TWENTY_BIT_BLOCK)
|
||||||
|
|| _address.isInSubnet(SIXTEEN_BIT_BLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr) {
|
QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr) {
|
||||||
debug.nospace() << sockAddr._address.toString().toLocal8Bit().constData() << ":" << sockAddr._port;
|
debug.nospace() << sockAddr._address.toString().toLocal8Bit().constData() << ":" << sockAddr._port;
|
||||||
return debug.space();
|
return debug.space();
|
||||||
|
|
|
@ -55,6 +55,8 @@ public:
|
||||||
|
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
|
||||||
|
bool hasPrivateAddress() const; // checks if the address behind this sock addr is private per RFC 1918
|
||||||
|
|
||||||
friend QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr);
|
friend QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr);
|
||||||
friend QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr);
|
friend QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr);
|
||||||
friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr);
|
friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr);
|
||||||
|
|
|
@ -202,12 +202,12 @@ QUdpSocket& LimitedNodeList::getDTLSSocket() {
|
||||||
return *_dtlsSocket;
|
return *_dtlsSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LimitedNodeList::isPacketVerified(const udt::Packet& packet) {
|
bool LimitedNodeList::isPacketVerifiedWithSource(const udt::Packet& packet, Node* sourceNode) {
|
||||||
// We track bandwidth when doing packet verification to avoid needing to do a node lookup
|
// We track bandwidth when doing packet verification to avoid needing to do a node lookup
|
||||||
// later when we already do it in packetSourceAndHashMatchAndTrackBandwidth. A node lookup
|
// later when we already do it in packetSourceAndHashMatchAndTrackBandwidth. A node lookup
|
||||||
// incurs a lock, so it is ideal to avoid needing to do it 2+ times for each packet
|
// incurs a lock, so it is ideal to avoid needing to do it 2+ times for each packet
|
||||||
// received.
|
// received.
|
||||||
return packetVersionMatch(packet) && packetSourceAndHashMatchAndTrackBandwidth(packet);
|
return packetVersionMatch(packet) && packetSourceAndHashMatchAndTrackBandwidth(packet, sourceNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LimitedNodeList::packetVersionMatch(const udt::Packet& packet) {
|
bool LimitedNodeList::packetVersionMatch(const udt::Packet& packet) {
|
||||||
|
@ -256,7 +256,7 @@ bool LimitedNodeList::packetVersionMatch(const udt::Packet& packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet) {
|
bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet, Node* sourceNode) {
|
||||||
|
|
||||||
PacketType headerType = NLPacket::typeInHeader(packet);
|
PacketType headerType = NLPacket::typeInHeader(packet);
|
||||||
|
|
||||||
|
@ -298,14 +298,18 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
||||||
} else {
|
} else {
|
||||||
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
|
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
|
||||||
|
|
||||||
// figure out which node this is from
|
// check if we were passed a sourceNode hint or if we need to look it up
|
||||||
SharedNodePointer matchingNode = nodeWithUUID(sourceID);
|
if (!sourceNode) {
|
||||||
|
// figure out which node this is from
|
||||||
|
SharedNodePointer matchingNode = nodeWithUUID(sourceID);
|
||||||
|
sourceNode = matchingNode.data();
|
||||||
|
}
|
||||||
|
|
||||||
if (matchingNode) {
|
if (sourceNode) {
|
||||||
if (!PacketTypeEnum::getNonVerifiedPackets().contains(headerType)) {
|
if (!PacketTypeEnum::getNonVerifiedPackets().contains(headerType)) {
|
||||||
|
|
||||||
QByteArray packetHeaderHash = NLPacket::verificationHashInHeader(packet);
|
QByteArray packetHeaderHash = NLPacket::verificationHashInHeader(packet);
|
||||||
QByteArray expectedHash = NLPacket::hashForPacketAndSecret(packet, matchingNode->getConnectionSecret());
|
QByteArray expectedHash = NLPacket::hashForPacketAndSecret(packet, sourceNode->getConnectionSecret());
|
||||||
|
|
||||||
// check if the md5 hash in the header matches the hash we would expect
|
// check if the md5 hash in the header matches the hash we would expect
|
||||||
if (packetHeaderHash != expectedHash) {
|
if (packetHeaderHash != expectedHash) {
|
||||||
|
@ -323,9 +327,9 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
||||||
|
|
||||||
// No matter if this packet is handled or not, we update the timestamp for the last time we heard
|
// No matter if this packet is handled or not, we update the timestamp for the last time we heard
|
||||||
// from this sending node
|
// from this sending node
|
||||||
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
|
sourceNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||||
|
|
||||||
emit dataReceived(matchingNode->getType(), packet.getPayloadSize());
|
emit dataReceived(sourceNode->getType(), packet.getPayloadSize());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -286,7 +286,9 @@ public:
|
||||||
|
|
||||||
void setPacketFilterOperator(udt::PacketFilterOperator filterOperator) { _nodeSocket.setPacketFilterOperator(filterOperator); }
|
void setPacketFilterOperator(udt::PacketFilterOperator filterOperator) { _nodeSocket.setPacketFilterOperator(filterOperator); }
|
||||||
bool packetVersionMatch(const udt::Packet& packet);
|
bool packetVersionMatch(const udt::Packet& packet);
|
||||||
bool isPacketVerified(const udt::Packet& packet);
|
|
||||||
|
bool isPacketVerifiedWithSource(const udt::Packet& packet, Node* sourceNode = nullptr);
|
||||||
|
bool isPacketVerified(const udt::Packet& packet) { return isPacketVerifiedWithSource(packet); }
|
||||||
|
|
||||||
static void makeSTUNRequestPacket(char* stunRequestPacket);
|
static void makeSTUNRequestPacket(char* stunRequestPacket);
|
||||||
|
|
||||||
|
@ -352,7 +354,7 @@ protected:
|
||||||
|
|
||||||
void setLocalSocket(const HifiSockAddr& sockAddr);
|
void setLocalSocket(const HifiSockAddr& sockAddr);
|
||||||
|
|
||||||
bool packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet);
|
bool packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet, Node* sourceNode = nullptr);
|
||||||
void processSTUNResponse(std::unique_ptr<udt::BasePacket> packet);
|
void processSTUNResponse(std::unique_ptr<udt::BasePacket> packet);
|
||||||
|
|
||||||
void handleNodeKill(const SharedNodePointer& node);
|
void handleNodeKill(const SharedNodePointer& node);
|
||||||
|
|
|
@ -348,8 +348,7 @@ void PhysicalEntitySimulation::addDynamic(EntityDynamicPointer dynamic) {
|
||||||
void PhysicalEntitySimulation::applyDynamicChanges() {
|
void PhysicalEntitySimulation::applyDynamicChanges() {
|
||||||
QList<EntityDynamicPointer> dynamicsFailedToAdd;
|
QList<EntityDynamicPointer> dynamicsFailedToAdd;
|
||||||
if (_physicsEngine) {
|
if (_physicsEngine) {
|
||||||
// FIXME put fine grain locking into _physicsEngine
|
QMutexLocker lock(&_dynamicsMutex);
|
||||||
QMutexLocker lock(&_mutex);
|
|
||||||
foreach(QUuid dynamicToRemove, _dynamicsToRemove) {
|
foreach(QUuid dynamicToRemove, _dynamicsToRemove) {
|
||||||
_physicsEngine->removeDynamic(dynamicToRemove);
|
_physicsEngine->removeDynamic(dynamicToRemove);
|
||||||
}
|
}
|
||||||
|
@ -360,9 +359,10 @@ void PhysicalEntitySimulation::applyDynamicChanges() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// applyDynamicChanges will clear _dynamicsToRemove and _dynamicsToAdd
|
||||||
|
EntitySimulation::applyDynamicChanges();
|
||||||
}
|
}
|
||||||
// applyDynamicChanges will clear _dynamicsToRemove and _dynamicsToAdd
|
|
||||||
EntitySimulation::applyDynamicChanges();
|
|
||||||
// put back the ones that couldn't yet be added
|
// put back the ones that couldn't yet be added
|
||||||
foreach (EntityDynamicPointer dynamicFailedToAdd, dynamicsFailedToAdd) {
|
foreach (EntityDynamicPointer dynamicFailedToAdd, dynamicsFailedToAdd) {
|
||||||
addDynamic(dynamicFailedToAdd);
|
addDynamic(dynamicFailedToAdd);
|
||||||
|
|
|
@ -1182,7 +1182,7 @@ function MyController(hand) {
|
||||||
this.fullEnd = fullEnd;
|
this.fullEnd = fullEnd;
|
||||||
this.laserPointer = LaserPointers.createLaserPointer({
|
this.laserPointer = LaserPointers.createLaserPointer({
|
||||||
joint: (hand == RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
joint: (hand == RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
||||||
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS,
|
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS | RayPick.PICK_INCLUDE_NONCOLLIDABLE,
|
||||||
maxDistance: PICK_MAX_DISTANCE,
|
maxDistance: PICK_MAX_DISTANCE,
|
||||||
posOffset: getGrabPointSphereOffset(this.handToController()),
|
posOffset: getGrabPointSphereOffset(this.handToController()),
|
||||||
renderStates: renderStates,
|
renderStates: renderStates,
|
||||||
|
@ -1191,7 +1191,7 @@ function MyController(hand) {
|
||||||
});
|
});
|
||||||
this.headLaserPointer = LaserPointers.createLaserPointer({
|
this.headLaserPointer = LaserPointers.createLaserPointer({
|
||||||
joint: "Avatar",
|
joint: "Avatar",
|
||||||
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS,
|
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS | RayPick.PICK_INCLUDE_NONCOLLIDABLE,
|
||||||
maxDistance: PICK_MAX_DISTANCE,
|
maxDistance: PICK_MAX_DISTANCE,
|
||||||
renderStates: headRenderStates,
|
renderStates: headRenderStates,
|
||||||
faceAvatar: true,
|
faceAvatar: true,
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
function fromQml(message) {
|
function fromQml(message) {
|
||||||
|
console.debug('tablet-goto::fromQml: message = ', JSON.stringify(message));
|
||||||
|
|
||||||
var response = {id: message.id, jsonrpc: "2.0"};
|
var response = {id: message.id, jsonrpc: "2.0"};
|
||||||
switch (message.method) {
|
switch (message.method) {
|
||||||
case 'request':
|
case 'request':
|
||||||
|
@ -98,6 +100,8 @@
|
||||||
button.editProperties({isActive: shouldActivateButton});
|
button.editProperties({isActive: shouldActivateButton});
|
||||||
wireEventBridge(true);
|
wireEventBridge(true);
|
||||||
messagesWaiting(false);
|
messagesWaiting(false);
|
||||||
|
tablet.sendToQml({ method: 'refreshFeeds' })
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
shouldActivateButton = false;
|
shouldActivateButton = false;
|
||||||
onGotoScreen = false;
|
onGotoScreen = false;
|
||||||
|
|
Loading…
Reference in a new issue