diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index d55da6c848..31f224667c 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -916,6 +916,14 @@ "default": false } ] + }, + { + "name": "multi_kick_logged_in", + "type": "checkbox", + "label": "Multi-Kick for Logged In Users", + "help": "Kick logged in users by machine fingerprint (in addition to the default kick by username)", + "default": false, + "advanced": true } ] }, diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 188c420a5d..c6eaa03634 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -183,6 +183,11 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin #ifdef WANT_DEBUG qDebug() << "| user-permissions: specific MAC matches, so:" << userPerms; +#endif + } else if (_server->_settingsManager.hasPermissionsForMachineFingerprint(machineFingerprint)) { + userPerms = _server->_settingsManager.getPermissionsForMachineFingerprint(machineFingerprint); +#ifdef WANT_DEBUG + qDebug(() << "| user-permissions: specific Machine Fingerprint matches, so: " << userPerms; #endif } else if (_server->_settingsManager.hasPermissionsForIP(senderAddress)) { // this user comes from an IP we have in our permissions table, apply those permissions diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index b12e2d90f0..a4d3e675aa 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -672,7 +672,7 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointerclear(NodePermissions::Permission::canConnectToDomain); - } else { + } + + // if we didn't have a username, or this domain-server uses the "multi-kick" setting to + // kick logged in users via username AND machine fingerprint (or IP as fallback) + // then we remove connect permissions for the machine fingerprint (or IP as fallback) + const QString MULTI_KICK_SETTINGS_KEYPATH = "security.multi_kick_logged_in"; + + if (verifiedUsername.isEmpty() || valueOrDefaultValueForKeyPath(MULTI_KICK_SETTINGS_KEYPATH).toBool()) { // remove connect permissions for the machine fingerprint DomainServerNodeData* nodeData = static_cast(matchingNode->getLinkedData()); if (nodeData) { @@ -719,8 +726,8 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointergetPublicSockAddr().getAddress() || - kickAddress == limitedNodeList->getLocalSockAddr().getAddress() || - kickAddress.isLoopback() ) { + kickAddress == limitedNodeList->getLocalSockAddr().getAddress() || + kickAddress.isLoopback() ) { qWarning() << "attempt to kick node running on same machine as domain server, ignoring KickRequest"; return; } diff --git a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml index 78c10e2ffa..0978f23013 100644 --- a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml +++ b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml @@ -36,7 +36,9 @@ Rectangle { readonly property bool hmdHead: headBox.checked readonly property bool headPuck: headPuckBox.checked readonly property bool handController: handBox.checked + readonly property bool handPuck: handPuckBox.checked + readonly property bool hmdDesktop: hmdInDesktop.checked property int state: buttonState.disabled property var lastConfiguration: null @@ -53,10 +55,6 @@ Rectangle { } - - - - MouseArea { id: mouseArea @@ -99,6 +97,7 @@ Rectangle { onClicked: { if (checked) { headPuckBox.checked = false; + hmdInDesktop.checked = false; } else { checked = true; } @@ -121,6 +120,7 @@ Rectangle { onClicked: { if (checked) { headBox.checked = false; + hmdInDesktop.checked = false; } else { checked = true; } @@ -133,6 +133,36 @@ Rectangle { text: "Tracker" color: hifi.colors.lightGrayText } + + HifiControls.CheckBox { + id: hmdInDesktop + width: 15 + height: 15 + boxRadius: 7 + visible: viveInDesktop.checked + + anchors.top: viveInDesktop.bottom + anchors.topMargin: 5 + anchors.left: openVrConfiguration.left + anchors.leftMargin: leftMargin + 10 + + onClicked: { + if (checked) { + headBox.checked = false; + headPuckBox.checked = false; + } else { + checked = true; + } + sendConfigurationSettings(); + } + } + + RalewayBold { + size: 12 + visible: viveInDesktop.checked + text: "None" + color: hifi.colors.lightGrayText + } } Row { @@ -773,6 +803,11 @@ Rectangle { anchors.leftMargin: leftMargin + 10 onClicked: { + if (!checked & hmdInDesktop.checked) { + headBox.checked = true; + headPuckBox.checked = false; + hmdInDesktop.checked = false; + } sendConfigurationSettings(); } } @@ -789,6 +824,7 @@ Rectangle { verticalCenter: viveInDesktop.verticalCenter } } + NumberAnimation { id: numberAnimation @@ -797,6 +833,7 @@ Rectangle { to: 0 } + function logAction(action, status) { console.log("calibrated from ui"); var data = { @@ -877,6 +914,7 @@ Rectangle { var HmdHead = settings["HMDHead"]; var viveController = settings["handController"]; var desktopMode = settings["desktopMode"]; + var hmdDesktopPosition = settings["hmdDesktopTracking"]; armCircumference.value = settings.armCircumference; shoulderWidth.value = settings.shoulderWidth; @@ -898,6 +936,7 @@ Rectangle { } viveInDesktop.checked = desktopMode; + hmdInDesktop.checked = hmdDesktopPosition; initializeButtonState(); updateCalibrationText(); @@ -1058,7 +1097,8 @@ Rectangle { "handConfiguration": handObject, "armCircumference": armCircumference.value, "shoulderWidth": shoulderWidth.value, - "desktopMode": viveInDesktop.checked + "desktopMode": viveInDesktop.checked, + "hmdDesktopTracking": hmdInDesktop.checked } return settingsObject; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 48420c95c2..4f2b290635 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1602,7 +1602,7 @@ void EntityItem::setParentID(const QUuid& value) { QUuid oldParentID = getParentID(); if (oldParentID != value) { EntityTreePointer tree = getTree(); - if (!oldParentID.isNull()) { + if (tree && !oldParentID.isNull()) { tree->removeFromChildrenOfAvatars(getThisPointer()); } SpatiallyNestable::setParentID(value); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 63ec460de8..5a72006a8c 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -385,9 +385,9 @@ void NodeList::sendDomainServerCheckIn() { packetStream << hardwareAddress; - // now add the machine fingerprint - a null UUID if logged in, real one if not logged in + // now add the machine fingerprint auto accountManager = DependencyManager::get(); - packetStream << (accountManager->isLoggedIn() ? QUuid() : FingerprintUtils::getMachineFingerprint()); + packetStream << FingerprintUtils::getMachineFingerprint(); } // pack our data to send to the domain-server including diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index c2c1d75726..fa5028e1bb 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -57,7 +57,7 @@ PacketVersion versionForPacketType(PacketType packetType) { return static_cast(DomainConnectionDeniedVersion::IncludesExtraInfo); case PacketType::DomainConnectRequest: - return static_cast(DomainConnectRequestVersion::HasMachineFingerprint); + return static_cast(DomainConnectRequestVersion::AlwaysHasMachineFingerprint); case PacketType::DomainServerAddedNode: return static_cast(DomainServerAddedNodeVersion::PermissionsGrid); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index c4c1758ed2..e5cb87c379 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -247,7 +247,8 @@ enum class DomainConnectRequestVersion : PacketVersion { HasHostname, HasProtocolVersions, HasMACAddress, - HasMachineFingerprint + HasMachineFingerprint, + AlwaysHasMachineFingerprint }; enum class DomainConnectionDeniedVersion : PacketVersion { diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 430dc193a3..8889e58f0c 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -166,6 +166,11 @@ void ViveControllerManager::setConfigurationSettings(const QJsonObject configura _resetMatCalculated = false; } } + + if (configurationSettings.contains("hmdDesktopTracking")) { + _hmdDesktopTracking = configurationSettings["hmdDesktopTracking"].toBool(); + } + _inputDevice->configureCalibrationSettings(configurationSettings); saveSettings(); } @@ -175,6 +180,7 @@ QJsonObject ViveControllerManager::configurationSettings() { if (isSupported()) { QJsonObject configurationSettings = _inputDevice->configurationSettings(); configurationSettings["desktopMode"] = _desktopMode; + configurationSettings["hmdDesktopTracking"] = _hmdDesktopTracking; return configurationSettings; } @@ -414,6 +420,8 @@ void ViveControllerManager::InputDevice::configureCalibrationSettings(const QJso if (!configurationSettings.empty()) { auto iter = configurationSettings.begin(); auto end = configurationSettings.end(); + bool hmdDesktopTracking = true; + bool hmdDesktopMode = false; while (iter != end) { if (iter.key() == "bodyConfiguration") { setConfigFromString(iter.value().toString()); @@ -441,9 +449,15 @@ void ViveControllerManager::InputDevice::configureCalibrationSettings(const QJso _armCircumference = (float)iter.value().toDouble() * CM_TO_M; } else if (iter.key() == "shoulderWidth") { _shoulderWidth = (float)iter.value().toDouble() * CM_TO_M; + } else if (iter.key() == "hmdDesktopTracking") { + hmdDesktopTracking = iter.value().toBool(); + } else if (iter.key() == "desktopMode") { + hmdDesktopMode = iter.value().toBool(); } iter++; } + + _hmdTrackingEnabled = !(hmdDesktopMode && hmdDesktopTracking); } } @@ -735,11 +749,18 @@ void ViveControllerManager::InputDevice::handleHmd(uint32_t deviceIndex, const c _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_HMD && _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid) { - const mat4& mat = _nextSimPoseData.poses[deviceIndex]; - const vec3 linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex]; - const vec3 angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex]; + if (_hmdTrackingEnabled){ + const mat4& mat = _nextSimPoseData.poses[deviceIndex]; + const vec3 linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex]; + const vec3 angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex]; - handleHeadPoseEvent(inputCalibrationData, mat, linearVelocity, angularVelocity); + handleHeadPoseEvent(inputCalibrationData, mat, linearVelocity, angularVelocity); + } else { + const mat4& mat = mat4(); + const vec3 zero = vec3(); + + handleHeadPoseEvent(inputCalibrationData, mat, zero, zero); + } } } diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 4a7fcaf85e..6767aafad2 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -113,7 +113,6 @@ private: void emitCalibrationStatus(); void calibrateNextFrame(); - class FilteredStick { public: glm::vec2 process(float deltaTime, const glm::vec2& stick) { @@ -195,6 +194,8 @@ private: bool _overrideHands { false }; mutable std::recursive_mutex _lock; + bool _hmdTrackingEnabled { false }; + QString configToString(Config config); friend class ViveControllerManager; }; @@ -204,7 +205,10 @@ private: bool _registeredWithInputMapper { false }; bool _modelLoaded { false }; bool _resetMatCalculated { false }; + bool _desktopMode { false }; + bool _hmdDesktopTracking { false }; + glm::mat4 _resetMat { glm::mat4() }; model::Geometry _modelGeometry; gpu::TexturePointer _texture; diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index ff20d0bbde..26bebc9247 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -33,6 +33,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.lastUnequipCheckTime = 0; this.autoUnequipCounter = 0; this.lastUnexpectedChildrenCheckTime = 0; + this.robbed = false; this.parameters = makeDispatcherModuleParameters( 500, @@ -75,6 +76,14 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); return false; }; + this.getOtherModule = function() { + return this.hand === RIGHT_HAND ? leftNearParentingGrabEntity : rightNearParentingGrabEntity; + }; + + this.otherHandIsParent = function(props) { + return this.getOtherModule().thisHandIsParent(props); + }; + this.startNearParentingGrabEntity = function (controllerData, targetProps) { Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); @@ -100,6 +109,11 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); // this should never happen, but if it does, don't set previous parent to be this hand. this.previousParentID[targetProps.id] = null; this.previousParentJointIndex[targetProps.id] = -1; + } else if (this.otherHandIsParent(targetProps)) { + var otherModule = this.getOtherModule(); + this.previousParentID[this.grabbedThingID] = otherModule.previousParentID[this.grabbedThingID]; + this.previousParentJointIndex[this.grabbedThingID] = otherModule.previousParentJointIndex[this.grabbedThingID]; + otherModule.robbed = true; } else { this.previousParentID[targetProps.id] = targetProps.parentID; this.previousParentJointIndex[targetProps.id] = targetProps.parentJointIndex; @@ -119,7 +133,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.endNearParentingGrabEntity = function (controllerData) { this.hapticTargetID = null; var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; - if (this.thisHandIsParent(props)) { + if (this.thisHandIsParent(props) && !this.robbed) { if (this.previousParentID[this.targetEntityID] === Uuid.NULL || this.previousParentID === undefined) { Entities.editEntity(this.targetEntityID, { parentID: this.previousParentID[this.targetEntityID], @@ -145,6 +159,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); })); this.grabbing = false; this.targetEntityID = null; + this.robbed = false; }; this.checkForChildTooFarAway = function (controllerData) { @@ -253,12 +268,14 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { this.checkForUnexpectedChildren(controllerData); + this.robbed = false; return makeRunningValues(false, [], []); } if (targetProps) { if ((propsArePhysical(targetProps) || propsAreCloneDynamic(targetProps)) && targetProps.parentID === Uuid.NULL) { + this.robbed = false; return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it } else { this.targetEntityID = targetProps.id; @@ -266,6 +283,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); } } else { this.hapticTargetID = null; + this.robbed = false; return makeRunningValues(false, [], []); } }; @@ -284,6 +302,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.grabbing = false; this.targetEntityID = null; this.hapticTargetID = null; + this.robbed = false; return makeRunningValues(false, [], []); } @@ -300,6 +319,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); // still searching / highlighting var readiness = this.isReady(controllerData); if (!readiness.active) { + this.robbed = false; return readiness; } if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) {