mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 03:13:51 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into black
This commit is contained in:
commit
b6a4ec910c
44 changed files with 312 additions and 127 deletions
|
@ -54,6 +54,7 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessag
|
|||
if (message->getSize() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDataStream packetStream(message->getMessage());
|
||||
|
||||
// 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);
|
||||
PacketVersion headerVersion = NLPacket::versionInHeader(packet);
|
||||
|
||||
|
@ -471,7 +471,48 @@ bool DomainServer::packetVersionMatch(const udt::Packet& packet) {
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -570,7 +611,7 @@ void DomainServer::setupNodeListAndAssignments() {
|
|||
addStaticAssignmentsToQueue();
|
||||
|
||||
// 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";
|
||||
|
@ -853,7 +894,6 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Ass
|
|||
}
|
||||
|
||||
void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||
|
||||
QDataStream packetStream(message->getMessage());
|
||||
NodeConnectionData nodeRequestData = NodeConnectionData::fromDataStream(packetStream, message->getSenderSockAddr(), false);
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ public slots:
|
|||
|
||||
void restart();
|
||||
|
||||
private slots:
|
||||
void processRequestAssignmentPacket(QSharedPointer<ReceivedMessage> packet);
|
||||
void processListRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||
void processNodeJSONStatsPacket(QSharedPointer<ReceivedMessage> packetList, SharedNodePointer sendingNode);
|
||||
|
@ -79,7 +80,6 @@ public slots:
|
|||
void processICEServerHeartbeatDenialPacket(QSharedPointer<ReceivedMessage> message);
|
||||
void processICEServerHeartbeatACK(QSharedPointer<ReceivedMessage> message);
|
||||
|
||||
private slots:
|
||||
void setupPendingAssignmentCredits();
|
||||
void sendPendingTransactionsToServer();
|
||||
|
||||
|
@ -129,7 +129,7 @@ private:
|
|||
|
||||
void getTemporaryName(bool force = false);
|
||||
|
||||
static bool packetVersionMatch(const udt::Packet& packet);
|
||||
static bool isPacketVerified(const udt::Packet& packet);
|
||||
|
||||
bool resetAccountManagerAccessToken();
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ find_package(Qt5LinguistTools REQUIRED)
|
|||
find_package(Qt5LinguistToolsMacros)
|
||||
|
||||
if (WIN32)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -bigobj")
|
||||
add_definitions(-D_USE_MATH_DEFINES) # apparently needed to get M_PI and other defines from cmath/math.h
|
||||
add_definitions(-DWINDOWS_LEAN_AND_MEAN) # needed to make sure windows doesn't go to crazy with its defines
|
||||
endif()
|
||||
|
|
|
@ -35,7 +35,6 @@ Column {
|
|||
property string metaverseServerUrl: '';
|
||||
property string actions: 'snapshot';
|
||||
// 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 filter: '';
|
||||
onFilterChanged: filterChoicesByText();
|
||||
|
@ -125,11 +124,9 @@ Column {
|
|||
cb();
|
||||
});
|
||||
}
|
||||
property var delay: Timer { // No setTimeout or nextTick in QML.
|
||||
interval: 0;
|
||||
onTriggered: fillDestinations();
|
||||
}
|
||||
function fillDestinations() { // Public
|
||||
console.debug('Feed::fillDestinations()')
|
||||
|
||||
function report(label, error) {
|
||||
console.log(label, actions, error || 'ok', allStories.length, 'filtered to', suggestions.count);
|
||||
}
|
||||
|
|
|
@ -39,11 +39,24 @@ StackView {
|
|||
property var rpcCounter: 0;
|
||||
signal sendToScript(var message);
|
||||
function rpc(method, parameters, callback) {
|
||||
console.debug('TabletAddressDialog: rpc: method = ', method, 'parameters = ', parameters, 'callback = ', callback)
|
||||
|
||||
rpcCalls[rpcCounter] = callback;
|
||||
var message = {method: method, params: parameters, id: rpcCounter++, jsonrpc: "2.0"};
|
||||
sendToScript(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];
|
||||
if (!callback) {
|
||||
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);
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
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 setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get<RayPickScriptingInterface>()->setIncludeEntities(_rayPickUID, includeEntities); }
|
||||
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) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
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);
|
||||
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
||||
|
||||
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||
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 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 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); }
|
||||
|
|
|
@ -41,12 +41,14 @@ public:
|
|||
// The key is the Flags
|
||||
Flags _flags;
|
||||
|
||||
RayPickFilter() : _flags(PICK_NOTHING) {}
|
||||
RayPickFilter() : _flags(getBitMask(PICK_NOTHING)) {}
|
||||
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; }
|
||||
|
||||
void setFlag(FlagBit flag, bool value) { _flags[flag] = value; }
|
||||
|
||||
bool doesPickNothing() const { return _flags[PICK_NOTHING]; }
|
||||
bool doesPickEntities() const { return _flags[PICK_ENTITIES]; }
|
||||
bool doesPickOverlays() const { return _flags[PICK_OVERLAYS]; }
|
||||
|
@ -61,27 +63,27 @@ public:
|
|||
|
||||
// Helpers for RayPickManager
|
||||
Flags getEntityFlags() const {
|
||||
Flags toReturn(PICK_ENTITIES);
|
||||
unsigned int toReturn = getBitMask(PICK_ENTITIES);
|
||||
if (doesPickInvisible()) {
|
||||
toReturn |= Flags(PICK_INCLUDE_INVISIBLE);
|
||||
toReturn |= getBitMask(PICK_INCLUDE_INVISIBLE);
|
||||
}
|
||||
if (doesPickNonCollidable()) {
|
||||
toReturn |= Flags(PICK_INCLUDE_NONCOLLIDABLE);
|
||||
toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
|
||||
}
|
||||
return toReturn;
|
||||
return Flags(toReturn);
|
||||
}
|
||||
Flags getOverlayFlags() const {
|
||||
Flags toReturn(PICK_OVERLAYS);
|
||||
unsigned int toReturn = getBitMask(PICK_OVERLAYS);
|
||||
if (doesPickInvisible()) {
|
||||
toReturn |= Flags(PICK_INCLUDE_INVISIBLE);
|
||||
toReturn |= getBitMask(PICK_INCLUDE_INVISIBLE);
|
||||
}
|
||||
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 getHUDFlags() const { return Flags(PICK_HUD); }
|
||||
Flags getAvatarFlags() const { return Flags(getBitMask(PICK_AVATARS)); }
|
||||
Flags getHUDFlags() const { return Flags(getBitMask(PICK_HUD)); }
|
||||
|
||||
static unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
|
||||
|
||||
|
@ -98,10 +100,12 @@ public:
|
|||
void disable() { _enabled = false; }
|
||||
|
||||
const RayPickFilter& getFilter() { return _filter; }
|
||||
const float& getMaxDistance() { return _maxDistance; }
|
||||
const bool& isEnabled() { return _enabled; }
|
||||
float getMaxDistance() { return _maxDistance; }
|
||||
bool isEnabled() { return _enabled; }
|
||||
const RayPickResult& getPrevRayPickResult() { return _prevResult; }
|
||||
|
||||
void setPrecisionPicking(bool precisionPicking) { _filter.setFlag(RayPickFilter::PICK_COURSE, !precisionPicking); }
|
||||
|
||||
void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; }
|
||||
|
||||
const QVector<EntityItemID>& getIgnoreEntites() { return _ignoreEntities; }
|
||||
|
|
|
@ -64,10 +64,11 @@ void RayPickManager::update() {
|
|||
RayToEntityIntersectionResult entityRes;
|
||||
bool fromCache = true;
|
||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
||||
bool noncollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||
RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags();
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -81,10 +82,11 @@ void RayPickManager::update() {
|
|||
RayToOverlayIntersectionResult overlayRes;
|
||||
bool fromCache = true;
|
||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
||||
bool noncollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||
RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags();
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -204,6 +206,14 @@ const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) {
|
|||
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) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
if (_rayPicks.contains(uid)) {
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
void disableRayPick(const QUuid uid);
|
||||
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
||||
|
||||
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||
|
|
|
@ -82,6 +82,10 @@ RayPickResult RayPickScriptingInterface::getPrevRayPickResult(QUuid 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) {
|
||||
qApp->getRayPickManager().setIgnoreEntities(uid, ignoreEntities);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ public slots:
|
|||
Q_INVOKABLE void removeRayPick(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 setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||
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 setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
|
||||
|
||||
private:
|
||||
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_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); }
|
||||
|
|
|
@ -264,7 +264,7 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
const render::ShapeKey Circle3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit();
|
||||
if (getAlpha() != 1.0f) {
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||
|
|
|
@ -117,7 +117,7 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
const render::ShapeKey Cube3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (getAlpha() != 1.0f) {
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "GeometryUtil.h"
|
||||
|
||||
#include "AbstractViewStateInterface.h"
|
||||
|
||||
QString const Image3DOverlay::TYPE = "image3d";
|
||||
|
||||
|
@ -58,12 +59,29 @@ void Image3DOverlay::render(RenderArgs* args) {
|
|||
if (!_isLoaded) {
|
||||
_isLoaded = true;
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(_url);
|
||||
_textureIsLoaded = false;
|
||||
}
|
||||
|
||||
if (!_visible || !getParentVisible() || !_texture || !_texture->isLoaded()) {
|
||||
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);
|
||||
gpu::Batch* batch = args->_batch;
|
||||
|
||||
|
@ -92,9 +110,9 @@ void Image3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
glm::vec2 topLeft(-x, -y);
|
||||
glm::vec2 bottomRight(x, y);
|
||||
glm::vec2 texCoordTopLeft(fromImage.x() / imageWidth, fromImage.y() / imageHeight);
|
||||
glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width()) / imageWidth,
|
||||
(fromImage.y() + fromImage.height()) / imageHeight);
|
||||
glm::vec2 texCoordTopLeft((fromImage.x() + 0.5f) / imageWidth, (fromImage.y() + 0.5f) / imageHeight);
|
||||
glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth,
|
||||
(fromImage.y() + fromImage.height() - 0.5f) / imageHeight);
|
||||
|
||||
const float MAX_COLOR = 255.0f;
|
||||
xColor color = getColor();
|
||||
|
@ -126,7 +144,7 @@ const render::ShapeKey Image3DOverlay::getShapeKey() {
|
|||
if (_emissive || shouldDrawHUDLayer()) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
if (getAlpha() != 1.0f) {
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
|
||||
void setProperties(const QVariantMap& properties) 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,
|
||||
BoxFace& face, glm::vec3& surfaceNormal) override;
|
||||
|
@ -48,6 +49,8 @@ public:
|
|||
private:
|
||||
QString _url;
|
||||
NetworkTexturePointer _texture;
|
||||
bool _textureIsLoaded { false };
|
||||
bool _alphaTexture { false };
|
||||
bool _emissive { false };
|
||||
|
||||
QRect _fromImage; // where from in the image to sample
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <GeometryCache.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "AbstractViewStateInterface.h"
|
||||
|
||||
QString const Line3DOverlay::TYPE = "line3d";
|
||||
|
||||
|
@ -149,7 +150,7 @@ void Line3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
const render::ShapeKey Line3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||
if (getAlpha() != 1.0f || _glow > 0.0f) {
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
|
@ -222,9 +223,17 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) {
|
|||
|
||||
auto glow = properties["glow"];
|
||||
if (glow.isValid()) {
|
||||
float prevGlow = _glow;
|
||||
setGlow(glow.toFloat());
|
||||
if (_glow > 0.0f) {
|
||||
_alpha = 0.5f;
|
||||
// Update our payload key if necessary to handle transparency
|
||||
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;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
bool isTransparent() override { return Base3DOverlay::isTransparent() || _glow > 0.0f; }
|
||||
|
||||
virtual Line3DOverlay* createClone() const override;
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ public:
|
|||
bool isLoaded() { return _isLoaded; }
|
||||
bool getVisible() const { return _visible; }
|
||||
bool shouldDrawHUDLayer() const { return _drawHUDLayer; }
|
||||
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
|
||||
xColor getColor();
|
||||
float getAlpha();
|
||||
Anchor getAnchor() const { return _anchor; }
|
||||
|
|
|
@ -300,7 +300,12 @@ OverlayID Overlays::cloneOverlay(OverlayID id) {
|
|||
}
|
||||
|
||||
bool Overlays::editOverlay(OverlayID id, const QVariant& properties) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
auto thisOverlay = getOverlay(id);
|
||||
if (!thisOverlay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!thisOverlay->is3D() && QThread::currentThread() != thread()) {
|
||||
// NOTE editOverlay can be called very frequently in scripts and can't afford to
|
||||
// block waiting on the main thread. Additionally, no script actually
|
||||
// examines the return value and does something useful with it, so use a non-blocking
|
||||
|
@ -309,22 +314,15 @@ bool Overlays::editOverlay(OverlayID id, const QVariant& properties) {
|
|||
return true;
|
||||
}
|
||||
|
||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||
if (thisOverlay) {
|
||||
thisOverlay->setProperties(properties.toMap());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
thisOverlay->setProperties(properties.toMap());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Overlays::editOverlays(const QVariant& propertiesById) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
// NOTE see comment on editOverlay for why this is not a blocking call
|
||||
QMetaObject::invokeMethod(this, "editOverlays", Q_ARG(QVariant, propertiesById));
|
||||
return true;
|
||||
}
|
||||
bool defer2DOverlays = QThread::currentThread() != thread();
|
||||
|
||||
QVariantMap map = propertiesById.toMap();
|
||||
QVariantMap deferrred;
|
||||
const QVariantMap map = propertiesById.toMap();
|
||||
bool success = true;
|
||||
for (const auto& key : map.keys()) {
|
||||
OverlayID id = OverlayID(key);
|
||||
|
@ -333,9 +331,21 @@ bool Overlays::editOverlays(const QVariant& propertiesById) {
|
|||
success = false;
|
||||
continue;
|
||||
}
|
||||
QVariant properties = map[key];
|
||||
|
||||
const QVariant& properties = map[key];
|
||||
if (defer2DOverlays && !thisOverlay->is3D()) {
|
||||
deferrred[key] = properties;
|
||||
continue;
|
||||
}
|
||||
thisOverlay->setProperties(properties.toMap());
|
||||
}
|
||||
|
||||
// For 2D/QML overlays, we need to perform the edit on the main thread
|
||||
if (defer2DOverlays && !deferrred.empty()) {
|
||||
// NOTE see comment on editOverlay for why this is not a blocking call
|
||||
QMetaObject::invokeMethod(this, "editOverlays", Q_ARG(QVariant, deferrred));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace render {
|
|||
if (std::static_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront()) {
|
||||
builder.withLayered();
|
||||
}
|
||||
if (overlay->getAlphaPulse() != 0.0f || overlay->getAlpha() != 1.0f) {
|
||||
if (overlay->isTransparent()) {
|
||||
builder.withTransparent();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -110,7 +110,7 @@ void Rectangle3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||
if (getAlpha() != 1.0f) {
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
|
|
|
@ -62,7 +62,7 @@ void Shape3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
const render::ShapeKey Shape3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (getAlpha() != 1.0f) {
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||
|
|
|
@ -59,7 +59,7 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
const render::ShapeKey Sphere3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (getAlpha() != 1.0f) {
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||
|
|
|
@ -143,7 +143,7 @@ void Text3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
const render::ShapeKey Text3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (getAlpha() != 1.0f) {
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
|
|
|
@ -318,8 +318,8 @@ void Web3DOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
const render::ShapeKey Web3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
|
||||
if (getAlpha() != 1.0f) {
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
#include "AnimUtil.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) {
|
||||
const float EPSILON = 0.0001f;
|
||||
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_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) {
|
||||
|
||||
UserAnimState::ClipNodeEnum clipNodeEnum;
|
||||
|
@ -935,8 +959,19 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
|
|||
int identifier = data.key();
|
||||
StateHandler& value = data.value();
|
||||
QScriptValue& function = value.function;
|
||||
auto handleResult = [this, identifier](QScriptValue result) { // called in script thread to get the result back to us.
|
||||
animationStateHandlerResult(identifier, result);
|
||||
int rigId = _rigId;
|
||||
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
|
||||
// the state of _animVars and allow continued changes to _animVars in this thread without conflict.
|
||||
|
|
|
@ -97,8 +97,8 @@ public:
|
|||
Hover
|
||||
};
|
||||
|
||||
Rig() {}
|
||||
virtual ~Rig() {}
|
||||
Rig();
|
||||
virtual ~Rig();
|
||||
|
||||
void destroyAnimGraph();
|
||||
|
||||
|
@ -372,6 +372,8 @@ protected:
|
|||
|
||||
glm::vec3 _prevLeftHandPoleVector { -Vectors::UNIT_Z };
|
||||
bool _prevLeftHandPoleVectorValid { false };
|
||||
|
||||
int _rigId;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Rig__) */
|
||||
|
|
|
@ -53,7 +53,6 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
|||
_viewState(viewState),
|
||||
_scriptingServices(scriptingServices),
|
||||
_displayModelBounds(false),
|
||||
_dontDoPrecisionPicking(false),
|
||||
_layeredZones(this)
|
||||
{
|
||||
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) {
|
||||
|
||||
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
||||
|
@ -530,11 +507,10 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
|
|||
if (!_tree || _shuttingDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
|
||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||
if (rayPickResult.intersects) {
|
||||
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
|
||||
|
||||
|
@ -579,11 +555,10 @@ void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
|
|||
if (!_tree || _shuttingDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent");
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
|
||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||
if (rayPickResult.intersects) {
|
||||
//qCDebug(entitiesrenderer) << "mouseDoublePressEvent over entity:" << rayPickResult.entityID;
|
||||
|
||||
|
@ -622,8 +597,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
|
|||
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||
if (rayPickResult.intersects) {
|
||||
//qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
|
||||
|
||||
|
@ -671,14 +645,11 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
|||
if (!_tree || _shuttingDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
|
||||
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
|
||||
bool precisionPicking = false; // for mouse moves we do not do precision picking
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking);
|
||||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||
if (rayPickResult.intersects) {
|
||||
|
||||
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
||||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
|
|
|
@ -59,6 +59,10 @@ public:
|
|||
float getEntityLoadingPriority(const EntityItem& item) const { return _calculateEntityLoadingPriorityFunc(item); }
|
||||
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 update();
|
||||
|
||||
|
@ -130,7 +134,7 @@ public slots:
|
|||
|
||||
// optional slots that can be wired to menu items
|
||||
void setDisplayModelBounds(bool value) { _displayModelBounds = value; }
|
||||
void setDontDoPrecisionPicking(bool value) { _dontDoPrecisionPicking = value; }
|
||||
void setPrecisionPicking(bool value) { _setPrecisionPickingOperator(_mouseRayPickID, value); }
|
||||
|
||||
protected:
|
||||
virtual OctreePointer createTree() override {
|
||||
|
@ -150,10 +154,6 @@ private:
|
|||
void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false);
|
||||
|
||||
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 _currentClickingOnEntityID;
|
||||
|
@ -176,12 +176,15 @@ private:
|
|||
AbstractViewStateInterface* _viewState;
|
||||
AbstractScriptingServicesInterface* _scriptingServices;
|
||||
bool _displayModelBounds;
|
||||
bool _dontDoPrecisionPicking;
|
||||
|
||||
bool _shuttingDown { false };
|
||||
|
||||
QMultiMap<QUrl, EntityItemID> _waitingOnPreload;
|
||||
|
||||
QUuid _mouseRayPickID;
|
||||
std::function<RayToEntityIntersectionResult(QUuid)> _getPrevRayPickResultOperator;
|
||||
std::function<void(QUuid, bool)> _setPrecisionPickingOperator;
|
||||
|
||||
class LayeredZone {
|
||||
public:
|
||||
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) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
QMutexLocker lock(&_dynamicsMutex);
|
||||
_dynamicsToAdd += dynamic;
|
||||
}
|
||||
|
||||
void EntitySimulation::removeDynamic(const QUuid dynamicID) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
QMutexLocker lock(&_dynamicsMutex);
|
||||
_dynamicsToRemove += dynamicID;
|
||||
}
|
||||
|
||||
void EntitySimulation::removeDynamics(QList<QUuid> dynamicIDsToRemove) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
QMutexLocker lock(&_dynamicsMutex);
|
||||
foreach(QUuid uuid, dynamicIDsToRemove) {
|
||||
_dynamicsToRemove.insert(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
void EntitySimulation::applyDynamicChanges() {
|
||||
QMutexLocker lock(&_mutex);
|
||||
QMutexLocker lock(&_dynamicsMutex);
|
||||
_dynamicsToAdd.clear();
|
||||
_dynamicsToRemove.clear();
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ protected:
|
|||
SetOfEntities _simpleKinematicEntities; // entities undergoing non-colliding kinematic motion
|
||||
QList<EntityDynamicPointer> _dynamicsToAdd;
|
||||
QSet<QUuid> _dynamicsToRemove;
|
||||
QMutex _dynamicsMutex { QMutex::Recursive };
|
||||
|
||||
protected:
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
debug.nospace() << sockAddr._address.toString().toLocal8Bit().constData() << ":" << sockAddr._port;
|
||||
return debug.space();
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
|
||||
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 QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr);
|
||||
friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr);
|
||||
|
|
|
@ -202,12 +202,12 @@ QUdpSocket& LimitedNodeList::getDTLSSocket() {
|
|||
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
|
||||
// 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
|
||||
// received.
|
||||
return packetVersionMatch(packet) && packetSourceAndHashMatchAndTrackBandwidth(packet);
|
||||
return packetVersionMatch(packet) && packetSourceAndHashMatchAndTrackBandwidth(packet, sourceNode);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -298,14 +298,18 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
|||
} else {
|
||||
QUuid sourceID = NLPacket::sourceIDInHeader(packet);
|
||||
|
||||
// figure out which node this is from
|
||||
SharedNodePointer matchingNode = nodeWithUUID(sourceID);
|
||||
// check if we were passed a sourceNode hint or if we need to look it up
|
||||
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)) {
|
||||
|
||||
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
|
||||
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
|
||||
// from this sending node
|
||||
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||
sourceNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||
|
||||
emit dataReceived(matchingNode->getType(), packet.getPayloadSize());
|
||||
emit dataReceived(sourceNode->getType(), packet.getPayloadSize());
|
||||
|
||||
return true;
|
||||
|
||||
|
|
|
@ -286,7 +286,9 @@ public:
|
|||
|
||||
void setPacketFilterOperator(udt::PacketFilterOperator filterOperator) { _nodeSocket.setPacketFilterOperator(filterOperator); }
|
||||
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);
|
||||
|
||||
|
@ -352,7 +354,7 @@ protected:
|
|||
|
||||
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 handleNodeKill(const SharedNodePointer& node);
|
||||
|
|
|
@ -53,8 +53,12 @@ QVariant NodePermissions::toVariant(QHash<QUuid, GroupRank> groupRanks) {
|
|||
values["permissions_id"] = _id;
|
||||
if (_groupIDSet) {
|
||||
values["group_id"] = _groupID;
|
||||
if (groupRanks.contains(_rankID)) {
|
||||
|
||||
if (!_rankID.isNull()) {
|
||||
values["rank_id"] = _rankID;
|
||||
}
|
||||
|
||||
if (groupRanks.contains(_rankID)) {
|
||||
values["rank_name"] = groupRanks[_rankID].name;
|
||||
values["rank_order"] = groupRanks[_rankID].order;
|
||||
}
|
||||
|
|
|
@ -348,8 +348,7 @@ void PhysicalEntitySimulation::addDynamic(EntityDynamicPointer dynamic) {
|
|||
void PhysicalEntitySimulation::applyDynamicChanges() {
|
||||
QList<EntityDynamicPointer> dynamicsFailedToAdd;
|
||||
if (_physicsEngine) {
|
||||
// FIXME put fine grain locking into _physicsEngine
|
||||
QMutexLocker lock(&_mutex);
|
||||
QMutexLocker lock(&_dynamicsMutex);
|
||||
foreach(QUuid dynamicToRemove, _dynamicsToRemove) {
|
||||
_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
|
||||
foreach (EntityDynamicPointer dynamicFailedToAdd, dynamicsFailedToAdd) {
|
||||
addDynamic(dynamicFailedToAdd);
|
||||
|
|
|
@ -1182,7 +1182,7 @@ function MyController(hand) {
|
|||
this.fullEnd = fullEnd;
|
||||
this.laserPointer = LaserPointers.createLaserPointer({
|
||||
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,
|
||||
posOffset: getGrabPointSphereOffset(this.handToController()),
|
||||
renderStates: renderStates,
|
||||
|
@ -1191,7 +1191,7 @@ function MyController(hand) {
|
|||
});
|
||||
this.headLaserPointer = LaserPointers.createLaserPointer({
|
||||
joint: "Avatar",
|
||||
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS,
|
||||
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS | RayPick.PICK_INCLUDE_NONCOLLIDABLE,
|
||||
maxDistance: PICK_MAX_DISTANCE,
|
||||
renderStates: headRenderStates,
|
||||
faceAvatar: true,
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
});
|
||||
|
||||
function fromQml(message) {
|
||||
console.debug('tablet-goto::fromQml: message = ', JSON.stringify(message));
|
||||
|
||||
var response = {id: message.id, jsonrpc: "2.0"};
|
||||
switch (message.method) {
|
||||
case 'request':
|
||||
|
@ -98,6 +100,8 @@
|
|||
button.editProperties({isActive: shouldActivateButton});
|
||||
wireEventBridge(true);
|
||||
messagesWaiting(false);
|
||||
tablet.sendToQml({ method: 'refreshFeeds' })
|
||||
|
||||
} else {
|
||||
shouldActivateButton = false;
|
||||
onGotoScreen = false;
|
||||
|
|
Loading…
Reference in a new issue