Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix personal space bubble opacity #3951

Merged
merged 5 commits into from
Feb 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably warants thinking through the product implications, so maybe we don't need it in this PR, but wonder if we should expose this to gltfs like

AFRAME.GLTFModelPlus.registerComponent("ignore-space-bubble", "tags", el => {
  el.setAttribute("tags", { ignoreSpaceBubble: true });
});

So people could make things in their avatars that ignore the space bubble effect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be abused and we probably want to keep it internal. Happy to have a separate discussion about this at a later point though.

},
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);
}
}