From 10b1b295ba1e9b27c6daa6f1778ebd6ad50bdb04 Mon Sep 17 00:00:00 2001
From: netpro2k <netpro2k@gmail.com>
Date: Thu, 7 Jun 2018 18:35:32 -0700
Subject: [PATCH] Sticky zones and refactor image-plus

---
 src/components/image-plus.js        | 26 ++---------
 src/components/networked-counter.js |  3 +-
 src/components/sticky-object.js     | 67 +++++++++++++++++++++++++++++
 src/hub.html                        | 42 ++++++++++++++++--
 src/hub.js                          |  1 +
 5 files changed, 113 insertions(+), 26 deletions(-)
 create mode 100644 src/components/sticky-object.js

diff --git a/src/components/image-plus.js b/src/components/image-plus.js
index f23be48bb..942f02281 100644
--- a/src/components/image-plus.js
+++ b/src/components/image-plus.js
@@ -4,8 +4,6 @@ AFRAME.registerComponent("image-plus", {
   schema: {
     src: { type: "string" },
 
-    freezeSpeedLimit: { default: 1 },
-
     initialOffset: { default: { x: 0, y: 0, z: -1.5 } },
     reorientOnGrab: { default: false }
   },
@@ -45,19 +43,9 @@ AFRAME.registerComponent("image-plus", {
     }
   },
 
-  _sleepIfStill(e) {
-    if (
-      e.target === this.el &&
-      this.el.body.velocity.lengthSquared() < this.data.freezeSpeedLimit * this.data.freezeSpeedLimit
-    ) {
-      this.el.body.sleep();
-    }
-  },
-
   _onGrab: (function() {
     const q = new THREE.Quaternion();
     return function() {
-      this.el.body.wakeUp();
       if (this.data.reorientOnGrab) {
         this.billboardTarget.getWorldQuaternion(q);
         this.el.body.quaternion.copy(q);
@@ -67,20 +55,14 @@ AFRAME.registerComponent("image-plus", {
 
   init() {
     this._onMaterialLoaded = this._onMaterialLoaded.bind(this);
-    this._sleepIfStill = this._sleepIfStill.bind(this);
     this._onGrab = this._onGrab.bind(this);
 
-    this.billboardTarget = document.querySelector("#player-camera").object3D;
-
-    const el = this.el;
-    el.addEventListener("materialtextureloaded", this._onMaterialLoaded);
-    el.addEventListener("materialvideoloadeddata", this._onMaterialLoaded);
-
-    el.addEventListener("grab-start", this._onGrab);
-    el.addEventListener("grab-end", this._sleepIfStill);
-    el.addEventListener("body-loaded", this._sleepIfStill);
+    this.el.addEventListener("materialtextureloaded", this._onMaterialLoaded);
+    this.el.addEventListener("materialvideoloadeddata", this._onMaterialLoaded);
+    this.el.addEventListener("grab-start", this._onGrab);
 
     const worldPos = new THREE.Vector3().copy(this.data.initialOffset);
+    this.billboardTarget = document.querySelector("#player-camera").object3D;
     this.billboardTarget.localToWorld(worldPos);
     this.el.object3D.position.copy(worldPos);
     this.billboardTarget.getWorldQuaternion(this.el.object3D.quaternion);
diff --git a/src/components/networked-counter.js b/src/components/networked-counter.js
index be9725cf6..9b9b5f8be 100644
--- a/src/components/networked-counter.js
+++ b/src/components/networked-counter.js
@@ -6,7 +6,7 @@
 AFRAME.registerComponent("networked-counter", {
   schema: {
     max: { default: 3 },
-    ttl: { default: 120 },
+    ttl: { default: 0 },
     grab_event: { type: "string", default: "grab-start" },
     release_event: { type: "string", default: "grab-end" }
   },
@@ -115,6 +115,7 @@ AFRAME.registerComponent("networked-counter", {
   },
 
   _addTimeout: function(id) {
+    if (!this.data.ttl) return;
     const timeout = this.data.ttl * 1000;
     this.timeouts[id] = setTimeout(() => {
       const el = this.queue[id].el;
diff --git a/src/components/sticky-object.js b/src/components/sticky-object.js
new file mode 100644
index 000000000..d24bf0277
--- /dev/null
+++ b/src/components/sticky-object.js
@@ -0,0 +1,67 @@
+AFRAME.registerComponent("sticky-object", {
+  dependencies: ["body"],
+
+  schema: {
+    autoLockOnLoad: { default: false },
+    autoLockOnRelease: { default: false },
+    autoLockSpeedLimit: { default: 1 }
+  },
+
+  init() {
+    this._onGrab = this._onGrab.bind(this);
+    this._onRelease = this._onRelease.bind(this);
+    this._onBodyLoaded = this._onBodyLoaded.bind(this);
+    this.el.addEventListener("grab-start", this._onGrab);
+    this.el.addEventListener("grab-end", this._onRelease);
+    this.el.addEventListener("body-loaded", this._onBodyLoaded);
+  },
+
+  setLocked(locked) {
+    this.locked = locked;
+    this.el.body.type = locked ? window.CANNON.Body.STATIC : window.CANNON.Body.DYNAMIC;
+    this.el.setAttribute("body", {
+      mass: locked ? 0 : this.bodyMass
+    });
+  },
+
+  _onBodyLoaded() {
+    this.bodyMass = this.el.body.mass;
+    if (this.data.autoLockOnLoad) {
+      this.setLocked(true);
+    }
+  },
+
+  _onRelease() {
+    if (
+      this.data.autoLockOnRelease &&
+      this.el.body.velocity.lengthSquared() < this.data.autoLockSpeedLimit * this.data.autoLockSpeedLimit
+    ) {
+      this.setLocked(true);
+    }
+  },
+
+  _onGrab() {
+    this.setLocked(false);
+  }
+});
+
+AFRAME.registerComponent("sticky-object-zone", {
+  dependencies: ["physics"],
+  init() {
+    const q = new THREE.Quaternion();
+    const p = new THREE.Vector3();
+    this.el.object3D.getWorldQuaternion(q);
+    this.el.object3D.getWorldPosition(p);
+    this.el.addEventListener("collisions", e => {
+      console.log("collisions", e.detail.els, e.detail.clearedEls);
+      e.detail.els.forEach(el => {
+        const stickyObject = el.components["sticky-object"];
+        if (!stickyObject) return;
+
+        stickyObject.setLocked(true);
+        el.object3D.position.copy(p);
+        el.object3D.quaternion.copy(q);
+      });
+    });
+  }
+});
diff --git a/src/hub.html b/src/hub.html
index 1206d99c1..c7d4a7562 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -36,7 +36,7 @@
     <a-scene
         renderer="antialias: true"
         networked-scene="adapter: janus; audio: true; debug: true; connectOnLoad: false;"
-        physics="gravity: -6;"
+        physics="gravity: -6; debug: true;"
         mute-mic="eventSrc: a-scene; toggleEvents: action_mute"
         freeze-controller="toggleEvent: action_freeze"
         personal-space-bubble="debug: false;"
@@ -190,6 +190,7 @@
                     stretchable="useWorldPosition: true;"
                     hoverable
                     duck
+                    sticky-object
                 ></a-entity>
             </template>
 
@@ -198,12 +199,13 @@
                     class="interactable"
                     super-networked-interactable="counter: #media-counter; mass: 1;"
                     body="type: dynamic; shape: none; mass: 1;"
-                    grabbable="uusePhysics: never;"
+                    grabbable
                     stretchable="useWorldPosition: true;"
                     hoverable
                     geometry="primitive: plane"
                     material="side: double;"
                     image-plus
+                    sticky-object="autoLockOnLoad: true; autoLockOnRelease: true;"
                 >
                 </a-entity>
             </template>
@@ -222,7 +224,7 @@
 
         <!-- Interactables -->
         <a-entity id="counter" networked-counter="max: 3; ttl: 120"></a-entity>
-        <a-entity id="media-counter" networked-counter="max: 3; ttl: 120"></a-entity>
+        <a-entity id="media-counter" networked-counter="max: 3;"></a-entity>
 
         <a-entity
             id="cursor-controller"
@@ -387,6 +389,40 @@
             nav-mesh-helper
             static-body="shape: none;"
         ></a-entity>
+
+        <a-entity
+            geometry="primitive: box;"
+            static-body="shape: box;"
+            collision-filter="collisionForces: false;"
+            physics-collider
+            sticky-object-zone
+            position="1.25 2 -5.9"
+            visible="false"
+            scale="1 1 0.5"
+        >
+        </a-entity>
+        <a-entity
+            geometry="primitive: box;"
+            static-body="shape: box;"
+            collision-filter="collisionForces: false;"
+            physics-collider
+            sticky-object-zone
+            position="0 2 -5.9"
+            visible="false"
+            scale="1 1 0.5"
+        >
+        </a-entity>
+        <a-entity
+            geometry="primitive: box;"
+            static-body="shape: box;"
+            collision-filter="collisionForces: false;"
+            physics-collider
+            sticky-object-zone
+            position="-1.25 2 -5.9"
+            visible="false"
+            scale="1 1 0.5"
+        >
+        </a-entity>
     </a-scene>
 
     <div id="ui-root"></div>
diff --git a/src/hub.js b/src/hub.js
index 53b98c7c4..ed9f861b9 100644
--- a/src/hub.js
+++ b/src/hub.js
@@ -68,6 +68,7 @@ import "./components/pinch-to-move";
 import "./components/look-on-mobile";
 import "./components/pitch-yaw-rotator";
 import "./components/input-configurator";
+import "./components/sticky-object";
 
 import ReactDOM from "react-dom";
 import React from "react";
-- 
GitLab