Skip to content

Instantly share code, notes, and snippets.

@AndreasH96
Last active August 17, 2020 13:23
Show Gist options
  • Save AndreasH96/fd41f6d39ca8cf590447d529658a8a9a to your computer and use it in GitHub Desktop.
Save AndreasH96/fd41f6d39ca8cf590447d529658a8a9a to your computer and use it in GitHub Desktop.
This code is based on a gist made by Utophia, https://gist.github.com/Utopiah/f2b11a8026030b726ecc8c8c9430a9b4 . It's made for being able to snap videos onto other objects.
/* global AFRAME */
const COLLISION_LAYERS = require("../constants").COLLISION_LAYERS;
AFRAME.registerComponent("sticky-object", {
schema: { resetScaleWhenGrabbed: { default: true } },
init() {
this.currentSnapTarget = null;
const physicsSystem = this.el.sceneEl.systems["hubs-systems"].physicsSystem;
this.el.updateComponent("body-helper", {
gravity: { x: 0, y: 0, z: 0 },
collisionFilterMask: COLLISION_LAYERS.UNOWNED_INTERACTABLE,
collisionFilterGroup: COLLISION_LAYERS.UNOWNED_INTERACTABLE,
disableCollision: true
});
physicsSystem.activateBody(this.el.components["body-helper"].uuid);
this.el.updateComponent("floaty-object", { gravitySpeedLimit: 0, autoLockOnRelease: true });
this.initialized = true;
},
snapIfPossible() {
// Check that the object is a video loader.
if (this.el.getAttribute("media-video") != null) {
// Check if there are any snap objects in the scene
const physicsSystem = AFRAME.scenes[0].systems["hubs-systems"].physicsSystem;
const coll = physicsSystem.getCollisions(this.el.components["body-helper"].uuid);
if (coll.length > 0) {
for (let bodyHelperID of coll) {
const collision_Element = physicsSystem.bodyUuidToData.get(bodyHelperID).object3D.el;
if (collision_Element.object3D.name.substring(0, 10).toLowerCase() == "snapobject") {
this.updateSnapTarget(collision_Element);
this.snap(this, collision_Element);
this.el.setAttribute("pinnable", { pinned: true });
this.snapped = true;
}
}
}
if (
coll.length === 0 ||
this.currentSnapTarget == null ||
!coll.includes(this.currentSnapTarget.components["body-helper"].uuid)
) {
this.clearSnapTarget();
}
}
},
setLocked(locked) {
if (this.el.components.networked && !NAF.utils.isMine(this.el)) return;
this.locked = locked;
this.el.setAttribute("body-helper", { type: locked ? "kinematic" : "dynamic" });
},
snap(toSnap, snapOn) {
// Align rotation
toSnap.el.object3D.setRotationFromQuaternion(snapOn.object3D.getWorldQuaternion()); //.rotation.copy(snapOn.object3D.);
// Align position
toSnap.el.object3D.position.copy(snapOn.object3D.getWorldPosition());
// Set to same scale
toSnap.el.object3D.scale.copy(snapOn.object3D.getWorldScale());
// Move slightly to avoid texture tearing
toSnap.el.object3D.translateZ(0.002);
// Make snap target invisible
this.currentSnapTarget.object3DMap.mesh.material.opacity = 0;
},
clearSnapTarget() {
if (this.currentSnapTarget != null) {
this.currentSnapTarget.object3DMap.mesh.material.opacity = 1;
this.currentSnapTarget = null;
}
},
updateSnapTarget(closestObject) {
// Check if closest object already is colored
if (this.currentSnapTarget != closestObject) {
// If not, empty list of colored objects, since there should be only one colored object
if (this.currentSnapTarget != null) {
this.currentSnapTarget.object3DMap.mesh.material.opacity = 1;
}
// Mark closest object by changing its opacity
closestObject.object3DMap.mesh.material.opacity = 0.5;
this.currentSnapTarget = closestObject;
}
},
tick() {
if (!this.bodyHelper) {
this.bodyHelper = this.el.components["body-helper"];
}
const interaction = AFRAME.scenes[0].systems.interaction;
const isHeld = interaction && interaction.isHeld(this.el);
const physicsSystem = AFRAME.scenes[0].systems["hubs-systems"].physicsSystem;
const collisions = physicsSystem.getCollisions(this.bodyHelper.uuid);
if (collisions.length > 0) {
for (let bodyHelperID of collisions) {
const collision_Element = physicsSystem.bodyUuidToData.get(bodyHelperID).object3D.el;
if (collision_Element.object3D.name.substring(0, 10).toLowerCase() == "snapobject") {
this.updateSnapTarget(collision_Element);
}
}
}
if (
collisions.length === 0 ||
this.currentSnapTarget == null ||
!collisions.includes(this.currentSnapTarget.components["body-helper"].uuid)
) {
this.clearSnapTarget();
}
if (isHeld && !this.wasHeld) {
this.snapped = false;
this.clearSnapTarget();
if (this.data.resetScaleWhenGrabbed) this.el.object3D.scale.set(1, 1, 1);
}
if (this.wasHeld && !isHeld) {
this.snapIfPossible();
this.setLocked(true);
}
this.wasHeld = isHeld;
},
remove() {
if (this.snapped) {
this.clearSnapTarget();
this.snapped = false;
}
}
});
@AndreasH96
Copy link
Author

in media-loader.js, the line this.el.setAttribute("sticky-object", { resetScaleWhenGrabbed: true }); is added for media-video objects

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment