Skip to content

Commit

Permalink
Merge pull request #3951 from mozilla/fix/space-bubble-opacity
Browse files Browse the repository at this point in the history
Fix personal space bubble opacity
  • Loading branch information
robertlong authored Feb 24, 2021
2 parents a9b4136 + bd35ecc commit c86bb49
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 15 deletions.
3 changes: 2 additions & 1 deletion src/components/tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ AFRAME.registerComponent("tags", {
isHoverMenuChild: { default: false },
isStatic: { default: false },
inspectable: { default: false },
preventAudioBoost: { default: false }
preventAudioBoost: { default: false },
ignoreSpaceBubble: { default: false }
},
update() {
if (this.didUpdateOnce) {
Expand Down
6 changes: 3 additions & 3 deletions src/hub.html
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
</template>

<template data-name="Neck">
<a-entity>
<a-entity tags="ignoreSpaceBubble: true;">
<a-entity
billboard
class="nametag"
Expand Down Expand Up @@ -174,9 +174,9 @@

<template data-name="Spine">
<a-entity is-remote-hover-target personal-space-invader="radius: 0.2; useMaterial: true;" bone-visibility>
<a-entity class="avatar-inspect-collider" avatar-inspect-collider tags="togglesHoveredActionSet: true;" is-remote-hover-target inspect-button></a-entity>
<a-entity class="avatar-inspect-collider" avatar-inspect-collider tags="togglesHoveredActionSet: true; ignoreSpaceBubble: true;" is-remote-hover-target inspect-button></a-entity>
<a-entity class="chest-image" scale="0.18 0.18 0.18" position="0 -0.025 0.13"></a-entity>
<a-entity class="interactable ui interactable-ui">
<a-entity tags="ignoreSpaceBubble: true;" class="interactable ui interactable-ui">
<a-entity billboard class="freeze-menu" visibility-while-frozen="withinDistance: 100; requireHoverOnNonMobile: false;" avatar-volume-controls>
<a-entity class="avatar-volume-label" text="value: 0%; anchor: center; align: center; color: #ff3464; letterSpacing: 4; width:1.5;" text-raycast-hack position="0.0 0.675 0.35" scale="1.25 1.25 1.25"></a-entity>
<a-entity mixin="rounded-button" is-remote-hover-target tags="singleActionButton: true;" position="-0.45 0.675 0.35" class="avatar-volume-down-button">
Expand Down
48 changes: 37 additions & 11 deletions src/systems/personal-space-bubble.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { forEachMaterial } from "../utils/material-utils";
import qsTruthy from "../utils/qs_truthy";
import traverseFilteredSubtrees from "../utils/traverseFilteredSubtrees";

const invaderPos = new AFRAME.THREE.Vector3();
const bubblePos = new AFRAME.THREE.Vector3();
Expand Down Expand Up @@ -151,12 +152,12 @@ function createSphereGizmo(radius) {
return line;
}

function findInvaderMesh(entity) {
function getGLTFModelRoot(entity) {
while (entity && !(entity.components && entity.components["gltf-model-plus"])) {
entity = entity.parentNode;
}
// TODO this assumes a single skinned mesh, should be some way for avatar to override this
return entity && entity.object3D.getObjectByProperty("type", "SkinnedMesh");

return entity;
}

const DEBUG_OBJ = "psb-debug";
Expand All @@ -177,12 +178,11 @@ AFRAME.registerComponent("personal-space-invader", {
init() {
const system = this.el.sceneEl.systems["personal-space-bubble"];
system.registerInvader(this);

if (this.data.useMaterial) {
const mesh = findInvaderMesh(this.el);
if (mesh) {
this.targetMesh = mesh;
}
this.gltfRootEl = getGLTFModelRoot(this.el);
}

this.invading = false;
this.alwaysHidden = false;
},
Expand Down Expand Up @@ -234,10 +234,36 @@ AFRAME.registerComponent("personal-space-invader", {
applyInvasionToMesh(invading) {
if (this.disabled) return;

if (this.targetMesh && this.targetMesh.material && !this.alwaysHidden) {
forEachMaterial(this.targetMesh, material => {
material.opacity = invading ? this.data.invadingOpacity : 1;
material.transparent = invading;
// Note: Model isn't loaded on init because this object is inflated before the root is.
// object3DMap.mesh is not initially set and must be checked before traversing.
if (this.gltfRootEl && this.gltfRootEl.object3DMap.mesh && !this.alwaysHidden) {
traverseFilteredSubtrees(this.gltfRootEl.object3DMap.mesh, obj => {
// Prevents changing the opacity of ui elements
if (obj.el && obj.el.components.tags && obj.el.components.tags.data.ignoreSpaceBubble) {
// Skip all objects under this branch by returning false
return false;
}

if (!obj.material) {
return;
}

forEachMaterial(obj, material => {
let originalProps = material.userData.originalProps;

if (!material.userData.originalProps) {
originalProps = material.userData.originalProps = {
opacity: material.opacity,
transparent: material.transparent
};
}

// Note: Sharing materials will cause all objects with the material to turn transparent / opaque
// This is generally fine for avatars since a material will only be shared within a glTF model,
// not across avatars in the room.
material.opacity = invading ? this.data.invadingOpacity : originalProps.opacity;
material.transparent = invading || originalProps.transparent;
});
});
} else {
this.el.object3D.visible = !invading && !this.alwaysHidden;
Expand Down
11 changes: 11 additions & 0 deletions src/utils/traverseFilteredSubtrees.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default function traverseFilteredSubtrees(object, cb) {
if (cb(object) === false) {
return;
}

const children = object.children;

for (let i = 0; i < children.length; i++) {
traverseFilteredSubtrees(children[i], cb);
}
}

0 comments on commit c86bb49

Please sign in to comment.