From 77ede81fc906adb51abe68a9ef77c37a36a60520 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 13:27:13 -0800 Subject: [PATCH] limit MyAvatar scale to limits from domain settings --- .../src/avatars/ScriptableAvatar.h | 4 +- .../resources/describe-settings.json | 12 +-- interface/src/avatar/MyAvatar.cpp | 78 +++++++++++++++++-- interface/src/avatar/MyAvatar.h | 3 + libraries/avatars/src/AvatarData.cpp | 8 +- libraries/avatars/src/AvatarData.h | 6 ++ 6 files changed, 92 insertions(+), 19 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 56707de471..18d64f4ac5 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -17,7 +17,7 @@ #include #include -class ScriptableAvatar : public AvatarData, public Dependency{ +class ScriptableAvatar : public AvatarData, public Dependency { Q_OBJECT public: @@ -39,4 +39,4 @@ private: std::shared_ptr _animSkeleton; }; -#endif // hifi_ScriptableAvatar_h \ No newline at end of file +#endif // hifi_ScriptableAvatar_h diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 6c4ab9fd77..b5c612881f 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -874,17 +874,17 @@ "name": "min_avatar_scale", "type": "double", "label": "Minimum Avatar Scale (meters)", - "help": "Limits the scale of avatars in your domain", - "placeholder": 0.01, - "default": 0.01 + "help": "Limits the scale of avatars in your domain. Must be at least than 0.005.", + "placeholder": 0.25, + "default": 0.25 }, { "name": "max_avatar_scale", "type": "double", "label": "Maximum Avatar Scale (meters)", - "help": "Limits the scale of avatars in your domain", - "placeholder": 4.0, - "default": 4.0 + "help": "Limits the scale of avatars in your domain. Cannot be greater than 1000.", + "placeholder": 3.0, + "default": 3.0 } ] }, diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 735ba05810..e1f0bd3a68 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -130,6 +130,15 @@ MyAvatar::MyAvatar(RigPointer rig) : connect(DependencyManager::get().data(), &AddressManager::locationChangeRequired, this, static_cast(&MyAvatar::goToLocation)); + // handle scale constraints imposed on us by the domain-server + auto& domainHandler = DependencyManager::get()->getDomainHandler(); + + // when we connect to a domain and retrieve its settings, we restrict our max/min scale based on those settings + connect(&domainHandler, &DomainHandler::settingsReceived, this, &MyAvatar::restrictScaleFromDomainSettings); + + // when we leave a domain we lift whatever restrictions that domain may have placed on our scale + connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &MyAvatar::clearScaleRestriction); + _characterController.setEnabled(true); _bodySensorMatrix = deriveBodyFromHMDSensor(); @@ -1824,24 +1833,79 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float } void MyAvatar::increaseSize() { - if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) { - _targetScale *= (1.0f + SCALING_RATIO); - qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); + // clamp the target scale to the maximum allowable scale in the domain + + float updatedTargetScale = _targetScale * (1.0f + SCALING_RATIO); + + if (updatedTargetScale > _domainMaximumScale) { + qCDebug(interfaceapp, "Forced scale to %f since %f would be larger than allowed maximum", + _domainMaximumScale, updatedTargetScale); + + updatedTargetScale = _domainMaximumScale; } + + setTargetScale(updatedTargetScale); + qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); } void MyAvatar::decreaseSize() { - if (MIN_AVATAR_SCALE < (1.0f - SCALING_RATIO) * _targetScale) { - _targetScale *= (1.0f - SCALING_RATIO); - qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); + // clamp the target scale to the minimum allowable scale in the domain + float updatedTargetScale = _targetScale * (1.0f - SCALING_RATIO); + + if (updatedTargetScale < _domainMinimumScale) { + qCDebug(interfaceapp, "Forced scale to %f since %f would be smaller than allowed minimum", + _domainMinimumScale, updatedTargetScale); + + updatedTargetScale = _domainMinimumScale; } + + + setTargetScale(updatedTargetScale); + qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); } void MyAvatar::resetSize() { - _targetScale = 1.0f; + // if the default + const float DEFAULT_AVATAR_SCALE = 1.0f; + + float allowedDefaultScale = glm::clamp(DEFAULT_AVATAR_SCALE, _domainMinimumScale, _domainMaximumScale); + + if (allowedDefaultScale != DEFAULT_AVATAR_SCALE) { + qCDebug(interfaceapp, "Forcing scale to %f since %f is not an allowed avatar scale by the domain", + allowedDefaultScale, DEFAULT_AVATAR_SCALE); + } + + setTargetScale(allowedDefaultScale); qCDebug(interfaceapp, "Reset scale to %f", (double)_targetScale); } +void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettingsObject) { + // pull out the minimum and maximum scale and set them to restrict our scale + + static const QString AVATAR_SETTINGS_KEY = "avatars"; + auto avatarsObject = domainSettingsObject[AVATAR_SETTINGS_KEY].toObject(); + + static const QString MIN_SCALE_OPTION = "min_avatar_scale"; + float settingMinScale = avatarsObject[MIN_SCALE_OPTION].toDouble(MIN_AVATAR_SCALE); + setDomainMinimumScale(settingMinScale); + + static const QString MAX_SCALE_OPTION = "max_avatar_scale"; + float settingMaxScale = avatarsObject[MAX_SCALE_OPTION].toDouble(MAX_AVATAR_SCALE); + setDomainMaximumScale(settingMaxScale); + + // debug to log if this avatar's scale in this domain will be clamped + auto clampedScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); + + if (_targetScale != clampedScale) { + qCDebug(interfaceapp, "Avatar scale will be clamped to %f because %f is not allowed by current domain", + clampedScale, _targetScale); + } +} + +void MyAvatar::clearScaleRestriction() { + _domainMinimumScale = MIN_AVATAR_SCALE; + _domainMaximumScale = MAX_AVATAR_SCALE; +} void MyAvatar::goToLocation(const QVariant& propertiesVar) { qCDebug(interfaceapp, "MyAvatar QML goToLocation"); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 71f185c6ed..d9c88621d2 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -292,6 +292,9 @@ public slots: bool shouldFaceLocation = false); void goToLocation(const QVariant& properties); + void restrictScaleFromDomainSettings(const QJsonObject& domainSettingsObject); + void clearScaleRestriction(); + // Set/Get update the thrust that will move the avatar around void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; glm::vec3 getThrust() { return _thrust; }; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 9df23dad2c..2469d0df04 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -210,7 +210,7 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) { packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 0), bodyEulerAngles.y); packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 1), bodyEulerAngles.x); packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 2), bodyEulerAngles.z); - packFloatRatioToTwoByte((uint8_t*)(&header->scale), _targetScale); + packFloatRatioToTwoByte((uint8_t*)(&header->scale), getDomainLimitedScale()); header->lookAtPosition[0] = _headData->_lookAtPosition.x; header->lookAtPosition[1] = _headData->_lookAtPosition.y; header->lookAtPosition[2] = _headData->_lookAtPosition.z; @@ -516,7 +516,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } return buffer.size(); } - _targetScale = std::max(MIN_AVATAR_SCALE, std::min(MAX_AVATAR_SCALE, scale)); + setTargetScale(scale); glm::vec3 lookAt = glm::vec3(header->lookAtPosition[0], header->lookAtPosition[1], header->lookAtPosition[2]); if (isNaN(lookAt)) { @@ -1439,7 +1439,7 @@ QJsonObject AvatarData::toJson() const { if (!success) { qDebug() << "Warning -- AvatarData::toJson couldn't get avatar transform"; } - avatarTransform.setScale(getTargetScale()); + avatarTransform.setScale(getDomainLimitedScale()); if (recordingBasis) { root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis); // Find the relative transform @@ -1451,7 +1451,7 @@ QJsonObject AvatarData::toJson() const { root[JSON_AVATAR_RELATIVE] = Transform::toJson(avatarTransform); } - auto scale = getTargetScale(); + auto scale = getDomainLimitedScale(); if (scale != 1.0f) { root[JSON_AVATAR_SCALE] = scale; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index cb3ef0c40e..018833283a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -243,6 +243,10 @@ public: void setTargetScale(float targetScale); void setTargetScaleVerbose(float targetScale); + float getDomainLimitedScale() const { return glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); } + void setDomainMinimumScale(float domainMinimumScale) { _domainMinimumScale = std::max(domainMinimumScale, MIN_AVATAR_SCALE); } + void setDomainMaximumScale(float domainMaximumScale) { _domainMaximumScale = std::min(domainMaximumScale, MAX_AVATAR_SCALE); } + // Hand State Q_INVOKABLE void setHandState(char s) { _handState = s; } Q_INVOKABLE char getHandState() const { return _handState; } @@ -377,6 +381,8 @@ protected: // Body scale float _targetScale; + float _domainMinimumScale { MIN_AVATAR_SCALE }; + float _domainMaximumScale { MAX_AVATAR_SCALE }; // Hand state (are we grabbing something or not) char _handState;