mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Add menu checkbox to toggle collisions with other avatars
This commit is contained in:
parent
3fa1acbf87
commit
d630fe9dbd
15 changed files with 120 additions and 52 deletions
|
@ -254,7 +254,8 @@ Rectangle {
|
|||
onSaveClicked: function() {
|
||||
var avatarSettings = {
|
||||
dominantHand : settings.dominantHandIsLeft ? 'left' : 'right',
|
||||
collisionsEnabled : settings.avatarCollisionsOn,
|
||||
collisionsEnabled : settings.environmentCollisionsOn,
|
||||
otherAvatarsCollisionsEnabled : settings.otherAvatarsCollisionsOn,
|
||||
animGraphOverrideUrl : settings.avatarAnimationOverrideJSON,
|
||||
collisionSoundUrl : settings.avatarCollisionSoundUrl
|
||||
};
|
||||
|
|
|
@ -35,7 +35,8 @@ Rectangle {
|
|||
|
||||
property real scaleValue: scaleSlider.value / 10
|
||||
property alias dominantHandIsLeft: leftHandRadioButton.checked
|
||||
property alias avatarCollisionsOn: collisionsEnabledRadiobutton.checked
|
||||
property alias otherAvatarsCollisionsOn: otherAvatarsCollisionsEnabledCheckBox.checked
|
||||
property alias environmentCollisionsOn: environmentCollisionsEnabledCheckBox.checked
|
||||
property alias avatarAnimationOverrideJSON: avatarAnimationUrlInputText.text
|
||||
property alias avatarAnimationJSON: avatarAnimationUrlInputText.placeholderText
|
||||
property alias avatarCollisionSoundUrl: avatarCollisionSoundUrlInputText.text
|
||||
|
@ -54,11 +55,11 @@ Rectangle {
|
|||
} else {
|
||||
rightHandRadioButton.checked = true;
|
||||
}
|
||||
|
||||
if (settings.otherAvatarsCollisionsEnabled) {
|
||||
otherAvatarsCollisionsEnabledCheckBox.checked = true;
|
||||
}
|
||||
if (settings.collisionsEnabled) {
|
||||
collisionsEnabledRadiobutton.checked = true;
|
||||
} else {
|
||||
collisionsDisabledRadioButton.checked = true;
|
||||
environmentCollisionsEnabledCheckBox.checked = true;
|
||||
}
|
||||
|
||||
avatarAnimationJSON = settings.animGraphUrl;
|
||||
|
@ -255,55 +256,43 @@ Rectangle {
|
|||
text: "Right"
|
||||
boxSize: 20
|
||||
}
|
||||
|
||||
HifiConstants {
|
||||
id: hifi
|
||||
}
|
||||
|
||||
// TextStyle9
|
||||
RalewaySemiBold {
|
||||
size: 17;
|
||||
Layout.row: 1
|
||||
Layout.column: 0
|
||||
|
||||
text: "Avatar Collisions"
|
||||
text: "Avatar collides with other avatars"
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: onOff
|
||||
}
|
||||
|
||||
HifiControlsUit.RadioButton {
|
||||
id: collisionsEnabledRadiobutton
|
||||
|
||||
Layout.row: 1
|
||||
Layout.column: 1
|
||||
Layout.leftMargin: -40
|
||||
ButtonGroup.group: onOff
|
||||
|
||||
colorScheme: hifi.colorSchemes.light
|
||||
fontSize: 17
|
||||
letterSpacing: 1.4
|
||||
checked: true
|
||||
|
||||
text: "ON"
|
||||
boxSize: 20
|
||||
}
|
||||
|
||||
HifiConstants {
|
||||
id: hifi
|
||||
}
|
||||
|
||||
HifiControlsUit.RadioButton {
|
||||
id: collisionsDisabledRadioButton
|
||||
|
||||
HifiControlsUit.CheckBox {
|
||||
id: otherAvatarsCollisionsEnabledCheckBox;
|
||||
boxSize: 20;
|
||||
Layout.row: 1
|
||||
Layout.column: 2
|
||||
Layout.rightMargin: 20
|
||||
|
||||
ButtonGroup.group: onOff
|
||||
Layout.leftMargin: 60
|
||||
colorScheme: hifi.colorSchemes.light
|
||||
fontSize: 17
|
||||
letterSpacing: 1.4
|
||||
}
|
||||
|
||||
text: "OFF"
|
||||
boxSize: 20
|
||||
// TextStyle9
|
||||
RalewaySemiBold {
|
||||
size: 17;
|
||||
Layout.row: 2
|
||||
Layout.column: 0
|
||||
text: "Avatar collides with environment"
|
||||
}
|
||||
|
||||
HifiControlsUit.CheckBox {
|
||||
id: environmentCollisionsEnabledCheckBox;
|
||||
boxSize: 20;
|
||||
Layout.row: 2
|
||||
Layout.column: 2
|
||||
Layout.leftMargin: 60
|
||||
colorScheme: hifi.colorSchemes.light
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
if (avatar->getSkeletonModel()->isLoaded()) {
|
||||
// remove the orb if it is there
|
||||
avatar->removeOrb();
|
||||
avatar->updateCollisionGroup(_myAvatar->getOtherAvatarsCollisionsEnabled());
|
||||
if (avatar->needsPhysicsUpdate()) {
|
||||
_avatarsToChangeInPhysics.insert(avatar);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
AvatarMotionState::AvatarMotionState(OtherAvatarPointer avatar, const btCollisionShape* shape) : ObjectMotionState(shape), _avatar(avatar) {
|
||||
assert(_avatar);
|
||||
_type = MOTIONSTATE_TYPE_AVATAR;
|
||||
_collisionGroup = BULLET_COLLISION_GROUP_OTHER_AVATAR;
|
||||
cacheShapeDiameter();
|
||||
}
|
||||
|
||||
|
@ -170,8 +171,8 @@ QUuid AvatarMotionState::getSimulatorID() const {
|
|||
|
||||
// virtual
|
||||
void AvatarMotionState::computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const {
|
||||
group = BULLET_COLLISION_GROUP_OTHER_AVATAR;
|
||||
mask = Physics::getDefaultCollisionMask(group);
|
||||
group = _collisionGroup;
|
||||
mask = _collisionGroup == BULLET_COLLISION_GROUP_COLLISIONLESS ? 0 : Physics::getDefaultCollisionMask(group);
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
|
@ -66,6 +66,9 @@ public:
|
|||
|
||||
void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; }
|
||||
|
||||
void setCollisionGroup(int32_t group) { _collisionGroup = group; }
|
||||
int32_t getCollisionGroup() { return _collisionGroup; }
|
||||
|
||||
virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const override;
|
||||
|
||||
virtual float getMass() const override;
|
||||
|
@ -87,7 +90,7 @@ protected:
|
|||
|
||||
OtherAvatarPointer _avatar;
|
||||
float _diameter { 0.0f };
|
||||
|
||||
uint32_t _collisionGroup;
|
||||
uint32_t _dirtyFlags;
|
||||
};
|
||||
|
||||
|
|
|
@ -3326,7 +3326,6 @@ void MyAvatar::setCollisionsEnabled(bool enabled) {
|
|||
QMetaObject::invokeMethod(this, "setCollisionsEnabled", Q_ARG(bool, enabled));
|
||||
return;
|
||||
}
|
||||
|
||||
_characterController.setCollisionless(!enabled);
|
||||
emit collisionsEnabledChanged(enabled);
|
||||
}
|
||||
|
@ -3337,6 +3336,20 @@ bool MyAvatar::getCollisionsEnabled() {
|
|||
return _characterController.computeCollisionGroup() != BULLET_COLLISION_GROUP_COLLISIONLESS;
|
||||
}
|
||||
|
||||
void MyAvatar::setOtherAvatarsCollisionsEnabled(bool enabled) {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setOtherAvatarsCollisionsEnabled", Q_ARG(bool, enabled));
|
||||
return;
|
||||
}
|
||||
_collideWithOtherAvatars = enabled;
|
||||
emit otherAvatarsCollisionsEnabledChanged(enabled);
|
||||
}
|
||||
|
||||
bool MyAvatar::getOtherAvatarsCollisionsEnabled() {
|
||||
return _collideWithOtherAvatars;
|
||||
}
|
||||
|
||||
void MyAvatar::updateCollisionCapsuleCache() {
|
||||
glm::vec3 start, end;
|
||||
float radius;
|
||||
|
|
|
@ -225,6 +225,7 @@ class MyAvatar : public Avatar {
|
|||
Q_PROPERTY(bool centerOfGravityModelEnabled READ getCenterOfGravityModelEnabled WRITE setCenterOfGravityModelEnabled)
|
||||
Q_PROPERTY(bool hmdLeanRecenterEnabled READ getHMDLeanRecenterEnabled WRITE setHMDLeanRecenterEnabled)
|
||||
Q_PROPERTY(bool collisionsEnabled READ getCollisionsEnabled WRITE setCollisionsEnabled)
|
||||
Q_PROPERTY(bool otherAvatarsCollisionsEnabled READ getOtherAvatarsCollisionsEnabled WRITE setOtherAvatarsCollisionsEnabled)
|
||||
Q_PROPERTY(bool characterControllerEnabled READ getCharacterControllerEnabled WRITE setCharacterControllerEnabled)
|
||||
Q_PROPERTY(bool useAdvancedMovementControls READ useAdvancedMovementControls WRITE setUseAdvancedMovementControls)
|
||||
Q_PROPERTY(bool showPlayArea READ getShowPlayArea WRITE setShowPlayArea)
|
||||
|
@ -1062,6 +1063,18 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE bool getCollisionsEnabled();
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setOtherAvatarsCollisionsEnabled
|
||||
* @param {boolean} enabled
|
||||
*/
|
||||
Q_INVOKABLE void setOtherAvatarsCollisionsEnabled(bool enabled);
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getOtherAvatarsCollisionsEnabled
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool getOtherAvatarsCollisionsEnabled();
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getCollisionCapsule
|
||||
* @returns {object}
|
||||
|
@ -1489,6 +1502,14 @@ signals:
|
|||
*/
|
||||
void collisionsEnabledChanged(bool enabled);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when collisions with other avatars enabled or disabled
|
||||
* @function MyAvatar.otherAvatarsCollisionsEnabledChanged
|
||||
* @param {boolean} enabled
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void otherAvatarsCollisionsEnabledChanged(bool enabled);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when avatar's animation url changes
|
||||
* @function MyAvatar.animGraphUrlChanged
|
||||
|
|
|
@ -120,7 +120,7 @@ bool OtherAvatar::shouldBeInPhysicsSimulation() const {
|
|||
}
|
||||
|
||||
bool OtherAvatar::needsPhysicsUpdate() const {
|
||||
constexpr uint32_t FLAGS_OF_INTEREST = Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS | Simulation::DIRTY_POSITION;
|
||||
constexpr uint32_t FLAGS_OF_INTEREST = Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS | Simulation::DIRTY_POSITION | Simulation::DIRTY_COLLISION_GROUP;
|
||||
return (_motionState && (bool)(_motionState->getIncomingDirtyFlags() & FLAGS_OF_INTEREST));
|
||||
}
|
||||
|
||||
|
@ -129,3 +129,17 @@ void OtherAvatar::rebuildCollisionShape() {
|
|||
_motionState->addDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
}
|
||||
}
|
||||
|
||||
void OtherAvatar::updateCollisionGroup(bool myAvatarCollide) {
|
||||
if (_motionState) {
|
||||
bool collides = _motionState->getCollisionGroup() == BULLET_COLLISION_GROUP_OTHER_AVATAR && myAvatarCollide;
|
||||
if (_collideWithOtherAvatars != collides) {
|
||||
if (!myAvatarCollide) {
|
||||
_collideWithOtherAvatars = false;
|
||||
}
|
||||
auto newCollisionGroup = _collideWithOtherAvatars ? BULLET_COLLISION_GROUP_OTHER_AVATAR : BULLET_COLLISION_GROUP_COLLISIONLESS;
|
||||
_motionState->setCollisionGroup(newCollisionGroup);
|
||||
_motionState->addDirtyFlags(Simulation::DIRTY_COLLISION_GROUP);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,6 +45,8 @@ public:
|
|||
bool shouldBeInPhysicsSimulation() const;
|
||||
bool needsPhysicsUpdate() const;
|
||||
|
||||
void updateCollisionGroup(bool myAvatarCollide);
|
||||
|
||||
friend AvatarManager;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -552,6 +552,7 @@ protected:
|
|||
glm::vec3 getBodyRightDirection() const { return getWorldOrientation() * IDENTITY_RIGHT; }
|
||||
glm::vec3 getBodyUpDirection() const { return getWorldOrientation() * IDENTITY_UP; }
|
||||
void measureMotionDerivatives(float deltaTime);
|
||||
bool getCollideWithOtherAvatars() const { return _collideWithOtherAvatars; }
|
||||
|
||||
float getSkeletonHeight() const;
|
||||
float getHeadHeight() const;
|
||||
|
|
|
@ -540,6 +540,10 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
if (_headData->getHasProceduralBlinkFaceMovement()) {
|
||||
setAtBit16(flags, PROCEDURAL_BLINK_FACE_MOVEMENT);
|
||||
}
|
||||
// avatar collisions enabled
|
||||
if (_collideWithOtherAvatars) {
|
||||
setAtBit16(flags, COLLIDE_WITH_OTHER_AVATARS);
|
||||
}
|
||||
|
||||
data->flags = flags;
|
||||
destinationBuffer += sizeof(AvatarDataPacket::AdditionalFlags);
|
||||
|
@ -1116,7 +1120,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
auto newHasAudioEnabledFaceMovement = oneAtBit16(bitItems, AUDIO_ENABLED_FACE_MOVEMENT);
|
||||
auto newHasProceduralEyeFaceMovement = oneAtBit16(bitItems, PROCEDURAL_EYE_FACE_MOVEMENT);
|
||||
auto newHasProceduralBlinkFaceMovement = oneAtBit16(bitItems, PROCEDURAL_BLINK_FACE_MOVEMENT);
|
||||
|
||||
auto newCollideWithOtherAvatars = oneAtBit16(bitItems, COLLIDE_WITH_OTHER_AVATARS);
|
||||
|
||||
bool keyStateChanged = (_keyState != newKeyState);
|
||||
bool handStateChanged = (_handState != newHandState);
|
||||
|
@ -1125,7 +1129,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
bool audioEnableFaceMovementChanged = (_headData->getHasAudioEnabledFaceMovement() != newHasAudioEnabledFaceMovement);
|
||||
bool proceduralEyeFaceMovementChanged = (_headData->getHasProceduralEyeFaceMovement() != newHasProceduralEyeFaceMovement);
|
||||
bool proceduralBlinkFaceMovementChanged = (_headData->getHasProceduralBlinkFaceMovement() != newHasProceduralBlinkFaceMovement);
|
||||
bool somethingChanged = keyStateChanged || handStateChanged || faceStateChanged || eyeStateChanged || audioEnableFaceMovementChanged || proceduralEyeFaceMovementChanged || proceduralBlinkFaceMovementChanged;
|
||||
bool collideWithOtherAvatarsChanged = (_collideWithOtherAvatars != newCollideWithOtherAvatars);
|
||||
bool somethingChanged = keyStateChanged || handStateChanged || faceStateChanged || eyeStateChanged || audioEnableFaceMovementChanged ||
|
||||
proceduralEyeFaceMovementChanged || proceduralBlinkFaceMovementChanged || collideWithOtherAvatarsChanged;
|
||||
|
||||
_keyState = newKeyState;
|
||||
_handState = newHandState;
|
||||
|
@ -1134,6 +1140,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
_headData->setHasAudioEnabledFaceMovement(newHasAudioEnabledFaceMovement);
|
||||
_headData->setHasProceduralEyeFaceMovement(newHasProceduralEyeFaceMovement);
|
||||
_headData->setHasProceduralBlinkFaceMovement(newHasProceduralBlinkFaceMovement);
|
||||
_collideWithOtherAvatars = newCollideWithOtherAvatars;
|
||||
|
||||
sourceBuffer += sizeof(AvatarDataPacket::AdditionalFlags);
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ const int HAND_STATE_FINGER_POINTING_BIT = 7; // 8th bit
|
|||
const int AUDIO_ENABLED_FACE_MOVEMENT = 8; // 9th bit
|
||||
const int PROCEDURAL_EYE_FACE_MOVEMENT = 9; // 10th bit
|
||||
const int PROCEDURAL_BLINK_FACE_MOVEMENT = 10; // 11th bit
|
||||
const int COLLIDE_WITH_OTHER_AVATARS = 11; // 12th bit
|
||||
|
||||
|
||||
const char HAND_STATE_NULL = 0;
|
||||
|
@ -1495,6 +1496,7 @@ protected:
|
|||
int _replicaIndex { 0 };
|
||||
bool _isNewAvatar { true };
|
||||
bool _isClientAvatar { false };
|
||||
bool _collideWithOtherAvatars { true };
|
||||
|
||||
// null unless MyAvatar or ScriptableAvatar sending traits data to mixer
|
||||
std::unique_ptr<ClientTraitsHandler, LaterDeleter> _clientTraitsHandler;
|
||||
|
|
|
@ -38,6 +38,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
|
||||
case PacketType::AvatarIdentity:
|
||||
case PacketType::AvatarData:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::CollisionFlag);
|
||||
case PacketType::BulkAvatarData:
|
||||
case PacketType::KillAvatar:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::GrabTraits);
|
||||
|
|
|
@ -305,7 +305,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
|
|||
MigrateAvatarEntitiesToTraits,
|
||||
FarGrabJointsRedux,
|
||||
JointTransScaled,
|
||||
GrabTraits
|
||||
GrabTraits,
|
||||
CollisionFlag
|
||||
};
|
||||
|
||||
enum class DomainConnectRequestVersion : PacketVersion {
|
||||
|
|
|
@ -62,7 +62,8 @@ function getMyAvatar() {
|
|||
function getMyAvatarSettings() {
|
||||
return {
|
||||
dominantHand: MyAvatar.getDominantHand(),
|
||||
collisionsEnabled : MyAvatar.getCollisionsEnabled(),
|
||||
collisionsEnabled: MyAvatar.getCollisionsEnabled(),
|
||||
otherAvatarsCollisionsEnabled: MyAvatar.getOtherAvatarsCollisionsEnabled(),
|
||||
collisionSoundUrl : MyAvatar.collisionSoundURL,
|
||||
animGraphUrl: MyAvatar.getAnimGraphUrl(),
|
||||
animGraphOverrideUrl : MyAvatar.getAnimGraphOverrideUrl(),
|
||||
|
@ -135,6 +136,13 @@ function onCollisionsEnabledChanged(enabled) {
|
|||
}
|
||||
}
|
||||
|
||||
function onOtherAvatarsCollisionsEnabledChanged(enabled) {
|
||||
if (currentAvatarSettings.otherAvatarsCollisionsEnabled !== enabled) {
|
||||
currentAvatarSettings.otherAvatarsCollisionsEnabled = enabled;
|
||||
sendToQml({ 'method': 'settingChanged', 'name': 'otherAvatarsCollisionsEnabled', 'value': enabled })
|
||||
}
|
||||
}
|
||||
|
||||
function onNewCollisionSoundUrl(url) {
|
||||
if(currentAvatarSettings.collisionSoundUrl !== url) {
|
||||
currentAvatarSettings.collisionSoundUrl = url;
|
||||
|
@ -323,6 +331,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
|
|||
currentAvatar.avatarScale = message.avatarScale;
|
||||
|
||||
MyAvatar.setDominantHand(message.settings.dominantHand);
|
||||
MyAvatar.setOtherAvatarsCollisionsEnabled(message.settings.otherAvatarsCollisionsEnabled);
|
||||
MyAvatar.setCollisionsEnabled(message.settings.collisionsEnabled);
|
||||
MyAvatar.collisionSoundURL = message.settings.collisionSoundUrl;
|
||||
MyAvatar.setAnimGraphOverrideUrl(message.settings.animGraphOverrideUrl);
|
||||
|
@ -513,6 +522,7 @@ function off() {
|
|||
MyAvatar.skeletonModelURLChanged.disconnect(onSkeletonModelURLChanged);
|
||||
MyAvatar.dominantHandChanged.disconnect(onDominantHandChanged);
|
||||
MyAvatar.collisionsEnabledChanged.disconnect(onCollisionsEnabledChanged);
|
||||
MyAvatar.otherAvatarsCollisionsEnabledChanged.disconnect(onOtherAvatarsCollisionsEnabledChanged);
|
||||
MyAvatar.newCollisionSoundURL.disconnect(onNewCollisionSoundUrl);
|
||||
MyAvatar.animGraphUrlChanged.disconnect(onAnimGraphUrlChanged);
|
||||
MyAvatar.targetScaleChanged.disconnect(onTargetScaleChanged);
|
||||
|
@ -533,6 +543,7 @@ function on() {
|
|||
MyAvatar.skeletonModelURLChanged.connect(onSkeletonModelURLChanged);
|
||||
MyAvatar.dominantHandChanged.connect(onDominantHandChanged);
|
||||
MyAvatar.collisionsEnabledChanged.connect(onCollisionsEnabledChanged);
|
||||
MyAvatar.otherAvatarsCollisionsEnabledChanged.connect(onOtherAvatarsCollisionsEnabledChanged);
|
||||
MyAvatar.newCollisionSoundURL.connect(onNewCollisionSoundUrl);
|
||||
MyAvatar.animGraphUrlChanged.connect(onAnimGraphUrlChanged);
|
||||
MyAvatar.targetScaleChanged.connect(onTargetScaleChanged);
|
||||
|
|
Loading…
Reference in a new issue