From 3d29c8c87c29a9e535c9d74b44f278d968975492 Mon Sep 17 00:00:00 2001
From: Kevin Lee <kevin@infinite-lee.com>
Date: Tue, 10 Jul 2018 18:28:36 -0700
Subject: [PATCH] update networking to not rely on networked-aframe's default
 attribute syncing

---
 src/components/tools/networked-drawing.js | 144 +++++++++++++++++-----
 src/components/tools/pen.js               |  26 ++--
 src/hub.html                              |   6 +-
 3 files changed, 128 insertions(+), 48 deletions(-)

diff --git a/src/components/tools/networked-drawing.js b/src/components/tools/networked-drawing.js
index e754dd74b..8004ac0b1 100644
--- a/src/components/tools/networked-drawing.js
+++ b/src/components/tools/networked-drawing.js
@@ -6,15 +6,43 @@
 
 import SharedBufferGeometryManager from "../../vendor/sharedbuffergeometrymanager";
 
+function round(x) {
+  return Math.round(x * 100000) / 100000;
+}
+
+function copyData(fromArray, toArray, fromIndex, toIndex) {
+  let i = fromIndex - 1;
+  let j = -1;
+  while (i + 1 < toIndex) {
+    if (fromArray[i + 1] === null) {
+      toArray[++j] = fromArray[++i];
+    } else {
+      //position
+      toArray[++j] = fromArray[++i];
+      toArray[++j] = fromArray[++i];
+      toArray[++j] = fromArray[++i];
+      //direction
+      toArray[++j] = fromArray[++i];
+      toArray[++j] = fromArray[++i];
+      toArray[++j] = fromArray[++i];
+      //normal
+      toArray[++j] = fromArray[++i];
+      toArray[++j] = fromArray[++i];
+      toArray[++j] = fromArray[++i];
+    }
+  }
+}
+
 AFRAME.registerComponent("networked-drawing", {
   schema: {
-    drawBuffer: { default: [] },
     segments: { default: 8 },
     radius: { default: 0.02 },
     color: { default: { r: 255, g: 0, b: 0 } }
   },
 
   init() {
+    this.drawBuffer = [];
+
     //TODO: figure out how to make this look nice
     const options = {
       roughness: 0.25,
@@ -22,6 +50,7 @@ AFRAME.registerComponent("networked-drawing", {
       vertexColors: THREE.VertexColors,
       side: THREE.DoubleSide,
       emissive: 0xff0000
+      // wireframe: true
     };
 
     const material = new THREE.MeshStandardMaterial(options);
@@ -43,55 +72,96 @@ AFRAME.registerComponent("networked-drawing", {
     this.scene.add(this.drawing);
 
     this.lineStarted = false;
+    this.remoteLineStarted = false;
 
     this.lastPoint = new THREE.Vector3();
     this.initialized = false;
 
     this.bufferIndex = 0;
 
-    NAF.utils.getNetworkedEntity(this.el).then(networkedEl => {
-      this.networkedEl = networkedEl;
+    this.sendDrawBuffer = this.sendDrawBuffer.bind(this);
+    this.receiveDrawBuffer = this.receiveDrawBuffer.bind(this);
+
+    document.body.addEventListener("clientConnected", this.sendDrawBuffer);
+
+    NAF.connection.onConnect(() => {
+      NAF.utils.getNetworkedEntity(this.el).then(networkedEl => {
+        this.networkedEl = networkedEl;
+
+        this.drawingId = "drawing-" + NAF.utils.getNetworkId(this.networkedEl);
+
+        if (!NAF.utils.isMine(this.networkedEl)) {
+          NAF.connection.subscribeToDataChannel(this.drawingId, this.receiveDrawBuffer);
+        }
+      });
     });
 
     this.debugGeometry = new THREE.SphereGeometry(0.02, 16, 16);
     this.debugMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
   },
 
+  remove() {
+    document.body.removeEventListener("clientConnected", this.sendDrawBuffer);
+    NAF.connection.unsubscribeToDataChannel(this.drawingId, this.receiveDrawBuffer);
+
+    this.scene.remove(this.drawing);
+  },
+
   tick: (() => {
     const position = new THREE.Vector3();
     const direction = new THREE.Vector3();
     const normal = new THREE.Vector3();
+    const copyArray = [];
     return function() {
-      if (this.networkedEl) {
-        const isMine = NAF.utils.isMine(this.networkedEl);
-        if (!isMine) {
-          if (this.peekBuffer() != null) {
-            position.set(this.getNextFromBuffer(), this.getNextFromBuffer(), this.getNextFromBuffer());
-            direction.set(this.getNextFromBuffer(), this.getNextFromBuffer(), this.getNextFromBuffer());
-            normal.set(this.getNextFromBuffer(), this.getNextFromBuffer(), this.getNextFromBuffer());
-
-            if (!this.lineStarted) {
+      if (this.bufferIndex < this.drawBuffer.length && NAF.connection.isConnected() && this.networkedEl) {
+        if (!NAF.utils.isMine(this.networkedEl)) {
+          if (this.drawBuffer[this.bufferIndex] != null && this.bufferIndex + 9 <= this.drawBuffer.length) {
+            --this.bufferIndex;
+            position.set(
+              this.drawBuffer[++this.bufferIndex],
+              this.drawBuffer[++this.bufferIndex],
+              this.drawBuffer[++this.bufferIndex]
+            );
+            direction.set(
+              this.drawBuffer[++this.bufferIndex],
+              this.drawBuffer[++this.bufferIndex],
+              this.drawBuffer[++this.bufferIndex]
+            );
+            normal.set(
+              this.drawBuffer[++this.bufferIndex],
+              this.drawBuffer[++this.bufferIndex],
+              this.drawBuffer[++this.bufferIndex]
+            );
+            if (!this.remoteLineStarted) {
               this.startDraw(position, direction, normal);
+              this.remoteLineStarted = true;
             } else {
               this.draw(position, direction, normal);
             }
-          } else if (this.data.drawBuffer.length > this.bufferIndex) {
+          } else if (this.drawBuffer[this.bufferIndex] === null) {
             this.endDraw(position, direction, normal);
-            this.bufferIndex++;
+            this.remoteLineStarted = false;
           }
-        } else if (this.data.drawBuffer.length > 0) {
-          this.bufferIndex = this.data.drawBuffer.length - 1;
+          ++this.bufferIndex;
+        } else if (this.drawBuffer.length > 0) {
+          copyArray.length = 0;
+          copyData(this.drawBuffer, copyArray, this.bufferIndex, this.drawBuffer.length);
+          NAF.connection.broadcastDataGuaranteed(this.drawingId, copyArray);
+          this.bufferIndex = this.drawBuffer.length;
         }
       }
     };
   })(),
 
-  peekBuffer() {
-    return this.data.drawBuffer[this.bufferIndex];
+  sendDrawBuffer(evt) {
+    if (NAF.utils.isMine(this.networkedEl)) {
+      //TODO: chunk this operation if drawBuffer is large
+      NAF.connection.sendDataGuaranteed(evt.detail.clientId, this.drawingId, this.drawBuffer);
+    }
   },
 
-  getNextFromBuffer() {
-    return this.data.drawBuffer[this.bufferIndex++];
+  receiveDrawBuffer(_, dataType, data) {
+    this.drawBuffer.push.apply(this.drawBuffer, data);
   },
 
   getLastPoint() {
@@ -99,6 +169,10 @@ AFRAME.registerComponent("networked-drawing", {
   },
 
   draw(position, direction, normal) {
+    if (!NAF.connection.isConnected()) {
+      return;
+    }
+
     if (!this.lineStarted) {
       this.addSegments(this.lastSegments, position, direction, normal, this.data.radius);
       if (this.initialized) {
@@ -115,6 +189,10 @@ AFRAME.registerComponent("networked-drawing", {
   },
 
   startDraw(position, direction, normal) {
+    if (!NAF.connection.isConnected()) {
+      return;
+    }
+
     this.lastPoint.copy(position);
     this.addToDrawBuffer(position, direction, normal);
   },
@@ -123,6 +201,10 @@ AFRAME.registerComponent("networked-drawing", {
     const projectedDirection = new THREE.Vector3();
     const projectedPoint = new THREE.Vector3();
     return function(position, direction, normal) {
+      if (!NAF.connection.isConnected()) {
+        return;
+      }
+
       if (!this.lineStarted) {
         this.drawPoint(position);
       } else {
@@ -133,7 +215,7 @@ AFRAME.registerComponent("networked-drawing", {
       }
 
       if (this.networkedEl && NAF.utils.isMine(this.networkedEl)) {
-        this.data.drawBuffer.push(null);
+        this.drawBuffer.push(null);
       }
       this.lineStarted = false;
     };
@@ -141,15 +223,15 @@ AFRAME.registerComponent("networked-drawing", {
 
   addToDrawBuffer(position, direction, normal) {
     if (this.networkedEl && NAF.utils.isMine(this.networkedEl)) {
-      this.data.drawBuffer.push(position.x);
-      this.data.drawBuffer.push(position.y);
-      this.data.drawBuffer.push(position.z);
-      this.data.drawBuffer.push(direction.x);
-      this.data.drawBuffer.push(direction.y);
-      this.data.drawBuffer.push(direction.z);
-      this.data.drawBuffer.push(normal.x);
-      this.data.drawBuffer.push(normal.y);
-      this.data.drawBuffer.push(normal.z);
+      this.drawBuffer.push(round(position.x));
+      this.drawBuffer.push(round(position.y));
+      this.drawBuffer.push(round(position.z));
+      this.drawBuffer.push(round(direction.x));
+      this.drawBuffer.push(round(direction.y));
+      this.drawBuffer.push(round(direction.z));
+      this.drawBuffer.push(round(normal.x));
+      this.drawBuffer.push(round(normal.y));
+      this.drawBuffer.push(round(normal.z));
     }
   },
 
@@ -208,7 +290,7 @@ AFRAME.registerComponent("networked-drawing", {
         this.addVertex(point);
       } else {
         this.addVertex(segments[segmentIndex % this.data.segments]);
-        segmentIndex++;
+        ++segmentIndex;
       }
     }
     this.sharedBuffer.restartPrimitive();
diff --git a/src/components/tools/pen.js b/src/components/tools/pen.js
index 742f0b3e4..24f37e861 100644
--- a/src/components/tools/pen.js
+++ b/src/components/tools/pen.js
@@ -17,8 +17,8 @@ AFRAME.registerComponent("pen", {
   },
 
   init() {
-    // this.onMouseDown = this.onMouseDown.bind(this);
-    // this.onMouseUp = this.onMouseUp.bind(this);
+    this.onMouseDown = this.onMouseDown.bind(this);
+    this.onMouseUp = this.onMouseUp.bind(this);
 
     this.startDraw = this.startDraw.bind(this);
     this.endDraw = this.endDraw.bind(this);
@@ -109,17 +109,17 @@ AFRAME.registerComponent("pen", {
     }
   },
 
-  // onMouseDown(e) {
-  //   if (this.currentDrawing && e.button === 0) {
-  //     this.startDraw();
-  //   }
-  // },
-
-  // onMouseUp(e) {
-  //   if (this.currentDrawing && e.button === 0) {
-  //     this.endDraw();
-  //   }
-  // },
+  onMouseDown(e) {
+    if (this.currentDrawing && e.button === 0) {
+      this.startDraw();
+    }
+  },
+
+  onMouseUp(e) {
+    if (this.currentDrawing && e.button === 0) {
+      this.endDraw();
+    }
+  },
 
   startDraw() {
     this.isDrawing = true;
diff --git a/src/hub.html b/src/hub.html
index 14297a1b4..86a8be524 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -235,11 +235,9 @@
             segments-height="9"
             segments-width="9"
             event-repeater="events: raycaster-intersection, raycaster-intersection-cleared; eventSource: #cursor-controller"
+            pen="camera: #player-camera; drawing: #my-first-drawing"
         ></a-sphere>
 
-        <!--             pen="camera: #player-camera; drawing: #my-first-drawing"
- -->
-
         <!-- Player Rig -->
         <a-entity
             id="player-rig"
@@ -312,7 +310,7 @@
                 mixin="controller-super-hands"
                 controls-shape-offset
             >
-                <a-sphere radius="0.02" color="red" pen="camera: #player-camera; drawing: #my-first-drawing"></a-sphere>
+                <!-- <a-sphere radius="0.02" color="red" pen="camera: #player-camera; drawing: #my-first-drawing;"></a-sphere> -->
                 <a-entity id="player-left-controller-reverse-z" rotation="0 180 0"></a-entity>
             </a-entity>
 
-- 
GitLab