diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index dbc82fd70e..230f8aa64b 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -48,6 +48,10 @@ AvatarActionHold::~AvatarActionHold() { myAvatar->removeHoldAction(this); } } + auto ownerEntity = _ownerEntity.lock(); + if (ownerEntity) { + ownerEntity->setTransitingWithAvatar(false); + } #if WANT_DEBUG qDebug() << "AvatarActionHold::~AvatarActionHold" << (void*)this; @@ -131,6 +135,15 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm:: glm::vec3 palmPosition; glm::quat palmRotation; + bool isTransitingWithAvatar = holdingAvatar->getTransit()->isTransiting(); + if (isTransitingWithAvatar != _isTransitingWithAvatar) { + _isTransitingWithAvatar = isTransitingWithAvatar; + auto ownerEntity = _ownerEntity.lock(); + if (ownerEntity) { + ownerEntity->setTransitingWithAvatar(_isTransitingWithAvatar); + } + } + if (holdingAvatar->isMyAvatar()) { std::shared_ptr myAvatar = avatarManager->getMyAvatar(); @@ -404,11 +417,14 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { _kinematicSetVelocity = kinematicSetVelocity; _ignoreIK = ignoreIK; _active = true; + + auto myAvatar = DependencyManager::get()->getMyAvatar(); auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { ownerEntity->setDynamicDataDirty(true); - ownerEntity->setDynamicDataNeedsTransmit(true); + ownerEntity->setDynamicDataNeedsTransmit(true); + ownerEntity->setTransitingWithAvatar(myAvatar->getTransit()->isTransiting()); } }); } diff --git a/interface/src/avatar/AvatarActionHold.h b/interface/src/avatar/AvatarActionHold.h index 6acc71b45c..ddc5808d67 100644 --- a/interface/src/avatar/AvatarActionHold.h +++ b/interface/src/avatar/AvatarActionHold.h @@ -59,6 +59,8 @@ private: bool _kinematicSetVelocity { false }; bool _previousSet { false }; bool _ignoreIK { false }; + bool _isTransitingWithAvatar { false }; + glm::vec3 _previousPositionalTarget; glm::quat _previousRotationalTarget; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 0263cc1c1e..bd0113aadf 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -94,8 +94,7 @@ AvatarManager::AvatarManager(QObject* parent) : _transitConfig._startTransitAnimation = AvatarTransit::TransitAnimation(START_ANIMATION_URL, 0, 14); _transitConfig._middleTransitAnimation = AvatarTransit::TransitAnimation(MIDDLE_ANIMATION_URL, 15, 0); - _transitConfig._endTransitAnimation = AvatarTransit::TransitAnimation(END_ANIMATION_URL, 16, 38); - + _transitConfig._endTransitAnimation = AvatarTransit::TransitAnimation(END_ANIMATION_URL, 16, 38); } AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer) { @@ -180,14 +179,21 @@ void AvatarManager::updateMyAvatar(float deltaTime) { PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()"); AvatarTransit::Status status = _myAvatar->updateTransit(deltaTime, _myAvatar->getNextPosition(), _transitConfig); - if (status != AvatarTransit::Status::IDLE && status != AvatarTransit::Status::TRANSITING) { - QUuid& transitEffectID = _myAvatar->getTransitEffectID(); - changeAvatarTransitState(status, _myAvatar->getID(), transitEffectID); - } - if (_transitConfig._playAnimation) { - playTransitAnimations(status); - } + bool sendFirstTransitPackage = (status == AvatarTransit::Status::START_TRANSIT); + bool sendAllTransitPackages = (status == AvatarTransit::Status::TRANSITING && _transitConfig._showAnimation); + bool blockTransitData = (status == AvatarTransit::Status::TRANSITING && !_transitConfig._showAnimation); + if (status != AvatarTransit::Status::IDLE) { + if (_transitConfig._showAnimation) { + blockTransitData = false; + playTransitAnimations(status); + } + if (status != AvatarTransit::Status::TRANSITING) { + QUuid& transitEffectID = _myAvatar->getTransitEffectID(); + changeAvatarTransitState(status, _myAvatar->getID(), transitEffectID); + } + } + _myAvatar->update(deltaTime); render::Transaction transaction; _myAvatar->updateRenderItem(transaction); @@ -196,9 +202,15 @@ void AvatarManager::updateMyAvatar(float deltaTime) { quint64 now = usecTimestampNow(); quint64 dt = now - _lastSendAvatarDataTime; - if (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS && !_myAvatarDataPacketsPaused) { + + if (sendFirstTransitPackage || (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS && !_myAvatarDataPacketsPaused && !blockTransitData)) { // send head/hand data to the avatar mixer and voxel server PerformanceTimer perfTimer("send"); + if (sendFirstTransitPackage) { + _myAvatar->overrideNextPackagePositionData(_myAvatar->getTransit()->getEndPosition()); + } else if (sendAllTransitPackages) { + _myAvatar->overrideNextPackagePositionData(_myAvatar->getTransit()->getCurrentPosition()); + } _myAvatar->sendAvatarDataPacket(); _lastSendAvatarDataTime = now; _myAvatarSendRate.increment(); @@ -315,6 +327,8 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { if (inView && avatar->hasNewJointData()) { numAvatarsUpdated++; } + + // smooth other avatars positions { auto status = avatar->_transit.update(deltaTime, avatar->_globalPosition, _transitConfig); @@ -324,6 +338,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { } } + avatar->simulate(deltaTime, inView); avatar->updateRenderItem(renderTransaction); @@ -924,9 +939,9 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV result["framesPerMeter"] = _transitConfig._framesPerMeter; result["isDistanceBased"] = _transitConfig._isDistanceBased; result["triggerDistance"] = _transitConfig._triggerDistance; - result["playAnimation"] = _transitConfig._playAnimation; + result["showAnimation"] = _transitConfig._showAnimation; result["easeType"] = (int)_transitConfig._easeType; - result["showEffect"] = _transitConfig._showEffect; + result["showParticles"] = _transitConfig._showParticles; return result; } @@ -943,14 +958,14 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV if (data.contains("triggerDistance")) { _transitConfig._triggerDistance = data["triggerDistance"].toDouble(); } - if (data.contains("playAnimation")) { - _transitConfig._playAnimation = data["playAnimation"].toBool(); + if (data.contains("showAnimation")) { + _transitConfig._showAnimation = data["showAnimation"].toBool(); } if (data.contains("easeType")) { _transitConfig._easeType = (AvatarTransit::EaseType)data["easeType"].toInt(); } - if (data.contains("showEffect")) { - _transitConfig._showEffect = data["showEffect"].toBool(); + if (data.contains("showParticles")) { + _transitConfig._showParticles = data["showParticles"].toBool(); } } @@ -989,7 +1004,7 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV void AvatarManager::changeAvatarTransitState(AvatarTransit::Status status, const QUuid& avatarID, QUuid& effectID) { - if (!_transitConfig._showEffect) { + if (!_transitConfig._showParticles) { return; } EntityItemProperties props = getAvatarTransitEffectProperties(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index fd463e6b8e..cd64fdb017 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -616,7 +616,9 @@ void MyAvatar::updateChildCauterization(SpatiallyNestablePointer object, bool ca void MyAvatar::simulate(float deltaTime) { PerformanceTimer perfTimer("simulate"); animateScaleChanges(deltaTime); - if (_transit.isTransiting()) { + // CameraMode mode = qApp->getCamera().getMode(); + // bool shouldTransit = (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT); + if (_transit.isTransiting() && _showTransit) { glm::vec3 nextPosition; if (_transit.getNextPosition(nextPosition)) { _globalPosition = nextPosition; @@ -626,6 +628,7 @@ void MyAvatar::simulate(float deltaTime) { } } } + setFlyingEnabled(getFlyingEnabled()); if (_cauterizationNeedsUpdate) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 40683f5848..d7bbe64fb4 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1115,6 +1115,8 @@ public: virtual void setAttachmentsVariant(const QVariantList& variant) override; glm::vec3 getNextPosition() { return _goToPending ? _goToPosition : getWorldPosition(); }; + bool getShowTransit() { return _showTransit; }; + void setShowTransit(bool value) { _showTransit = value; }; public slots: @@ -1796,6 +1798,8 @@ private: void updateChildCauterization(SpatiallyNestablePointer object, bool cauterize); void playTransitAnimations(AvatarTransit::Status status); + + bool _showTransit { false }; // max unscaled forward movement speed ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; ThreadSafeValueCache _walkBackwardSpeed { DEFAULT_AVATAR_MAX_WALKING_BACKWARD_SPEED }; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 951925214c..4b45b32403 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -248,6 +248,15 @@ void setupPreferences() { preference->setItems(items); preferences->addPreference(preference); } + { + auto getter = [myAvatar]()->int { return myAvatar->getShowTransit() ? 0 : 1; }; + auto setter = [myAvatar](int value) { myAvatar->setShowTransit(value == 0); }; + auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Show transit / Hide transit", getter, setter); + QStringList items; + items << "Show transit" << "Hide Transit"; + preference->setItems(items); + preferences->addPreference(preference); + } { auto getter = [=]()->float { return myAvatar->getUserHeight(); }; auto setter = [=](float value) { myAvatar->setUserHeight(value); }; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 9c9eae2cca..80537f84a4 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -121,7 +121,8 @@ AvatarTransit::Status AvatarTransit::update(float deltaTime, const glm::vec3& av start(deltaTime, _lastPosition, currentPosition, config); } _lastPosition = currentPosition; - return updatePosition(deltaTime); + _status = updatePosition(deltaTime); + return _status; } void AvatarTransit::start(float deltaTime, const glm::vec3& startPosition, const glm::vec3& endPosition, const AvatarTransit::TransitConfig& config) { @@ -131,10 +132,12 @@ void AvatarTransit::start(float deltaTime, const glm::vec3& startPosition, const _transitLine = endPosition - startPosition; _totalDistance = glm::length(_transitLine); _easeType = config._easeType; + _showAnimation = config._showAnimation; + _showParticles = config._showParticles; const float REFERENCE_FRAMES_PER_SECOND = 30.0f; - int framesBefore = config._playAnimation ? config._startTransitAnimation._frameCount : 0; - int framesAfter = config._playAnimation ? config._endTransitAnimation._frameCount : 0; + int framesBefore = _showAnimation ? config._startTransitAnimation._frameCount : 0; + int framesAfter = _showAnimation ? config._endTransitAnimation._frameCount : 0; _timeBefore = (float)framesBefore / REFERENCE_FRAMES_PER_SECOND; _timeAfter = (float)framesAfter / REFERENCE_FRAMES_PER_SECOND; @@ -537,7 +540,7 @@ void Avatar::relayJointDataToChildren() { void Avatar::simulate(float deltaTime, bool inView) { PROFILE_RANGE(simulation, "simulate"); - + if (_transit.isTransiting()) { glm::vec3 nextPosition; if (_transit.getNextPosition(nextPosition)) { @@ -548,7 +551,7 @@ void Avatar::simulate(float deltaTime, bool inView) { } } } - + _simulationRate.increment(); if (inView) { _simulationInViewRate.increment(); @@ -1985,6 +1988,12 @@ AvatarTransit::Status Avatar::updateTransit(float deltaTime, const glm::vec3& av return _transit.update(deltaTime, avatarPosition, config); } +void Avatar::overrideNextPackagePositionData(const glm::vec3& position) { + std::lock_guard lock(_transitLock); + _overrideGlobalPosition = true; + _globalPositionOverride = position; +} + void Avatar::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) { std::lock_guard lock(_materialsLock); _materials[parentMaterialName].push(material); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 1234ab897a..ebb51a8851 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -83,9 +83,9 @@ public: int _framesPerMeter { 0 }; bool _isDistanceBased { false }; float _triggerDistance { 0 }; - bool _playAnimation { true }; + bool _showAnimation { false }; EaseType _easeType { EaseType::EASE_OUT }; - bool _showEffect { true }; + bool _showParticles { false }; TransitAnimation _startTransitAnimation; TransitAnimation _middleTransitAnimation; TransitAnimation _endTransitAnimation; @@ -93,15 +93,17 @@ public: AvatarTransit() {}; Status update(float deltaTime, const glm::vec3& avatarPosition, const TransitConfig& config); - bool isTransiting() { return _isTransiting; }; - glm::vec3 getCurrentPosition() { return _currentPosition; }; + Status getStatus() { return _status; } + bool isTransiting() { return _isTransiting; } + glm::vec3 getCurrentPosition() { return _currentPosition; } bool getNextPosition(glm::vec3& nextPosition); + glm::vec3 getEndPosition() { return _endPosition; } private: Status updatePosition(float deltaTime); void start(float deltaTime, const glm::vec3& startPosition, const glm::vec3& endPosition, const TransitConfig& config); float getEaseValue(AvatarTransit::EaseType type, float value); - bool _isTransiting{ false }; + bool _isTransiting { false }; glm::vec3 _startPosition; glm::vec3 _endPosition; @@ -117,7 +119,9 @@ private: float _timeBefore { 0.0f }; float _timeAfter { 0.0f }; EaseType _easeType { EaseType::EASE_OUT }; - + Status _status { Status::IDLE }; + bool _showAnimation { false }; + bool _showParticles { false }; }; class Avatar : public AvatarData, public scriptable::ModelProvider { @@ -444,6 +448,7 @@ public: AvatarTransit::Status updateTransit(float deltaTime, const glm::vec3& avatarPosition, const AvatarTransit::TransitConfig& config); QUuid& getTransitEffectID() { return _transitEffectID; }; + void overrideNextPackagePositionData(const glm::vec3& position); signals: void targetScaleChanged(float targetScale); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index acf5696d65..2168dff1f6 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -369,7 +369,12 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent if (hasAvatarGlobalPosition) { auto startSection = destinationBuffer; - AVATAR_MEMCPY(_globalPosition); + if (_overrideGlobalPosition) { + AVATAR_MEMCPY(_globalPositionOverride); + } else { + AVATAR_MEMCPY(_globalPosition); + } + int numBytes = destinationBuffer - startSection; @@ -2088,6 +2093,10 @@ void AvatarData::sendAvatarDataPacket(bool sendAll) { } } + if (_overrideGlobalPosition) { + _overrideGlobalPosition = false; + } + doneEncoding(cullSmallData); static AvatarDataSequenceNumber sequenceNumber = 0; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 39f0ea34f6..a890482e9a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1372,7 +1372,8 @@ protected: // where Entities are located. This is currently only used by the mixer to decide how often to send // updates about one avatar to another. glm::vec3 _globalPosition { 0, 0, 0 }; - + glm::vec3 _globalPositionOverride { 0, 0, 0 }; + bool _overrideGlobalPosition { false }; quint64 _globalPositionChanged { 0 }; quint64 _avatarBoundingBoxChanged { 0 }; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 490f9b9e6b..15c6f6d75e 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -441,6 +441,8 @@ public: void setDynamicDataNeedsTransmit(bool value) const { _dynamicDataNeedsTransmit = value; } bool dynamicDataNeedsTransmit() const { return _dynamicDataNeedsTransmit; } + void setTransitingWithAvatar(bool value) { _transitingWithAvatar = value; } + bool getTransitingWithAvatar() { return _transitingWithAvatar; } bool shouldSuppressLocationEdits() const; @@ -666,6 +668,7 @@ protected: QUuid _sourceUUID; /// the server node UUID we came from bool _clientOnly { false }; + bool _transitingWithAvatar{ false }; QUuid _owningAvatarID; // physics related changes from the network to suppress any duplicates and make diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 5478221607..8162bf4e18 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -432,6 +432,9 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { // this case is prevented by setting _ownershipState to UNOWNABLE in EntityMotionState::ctor assert(!(_entity->getClientOnly() && _entity->getOwningAvatarID() != Physics::getSessionUUID())); + if (_entity->getTransitingWithAvatar()) { + return false; + } if (_entity->dynamicDataNeedsTransmit()) { return true; }