فهرست منبع

Merge remote-tracking branch 'upstream/lcs-2020.1-5'

Nikolay Suslov 4 سال پیش
والد
کامیت
7d6cf07984
39فایلهای تغییر یافته به همراه3013 افزوده شده و 395 حذف شده
  1. 39 9
      public/app.js
  2. 10 0
      public/defaults/proxy/vwf.example.com/aframe/aentity.js
  3. 1 0
      public/defaults/proxy/vwf.example.com/aframe/aentity.vwf.yaml
  4. 120 18
      public/defaults/proxy/vwf.example.com/aframe/ascene.js
  5. 16 0
      public/defaults/proxy/vwf.example.com/aframe/ascene.vwf.yaml
  6. 22 9
      public/defaults/proxy/vwf.example.com/aframe/avatar.js
  7. 6 0
      public/defaults/proxy/vwf.example.com/aframe/avatar.vwf.yaml
  8. 2 2
      public/defaults/proxy/vwf.example.com/aframe/gearvrcontroller.js
  9. 24 0
      public/defaults/proxy/vwf.example.com/aframe/hand-controls.vwf.yaml
  10. 2 2
      public/defaults/proxy/vwf.example.com/aframe/wmrvrcontroller.js
  11. 175 0
      public/defaults/proxy/vwf.example.com/aframe/xrcontroller.js
  12. 30 0
      public/defaults/proxy/vwf.example.com/aframe/xrcontroller.vwf.yaml
  13. 6 0
      public/defaults/worlds/paint/appui.js
  14. 10 0
      public/defaults/worlds/paint/assets.json
  15. 24 0
      public/defaults/worlds/paint/controller.js
  16. 8 0
      public/defaults/worlds/paint/index.vwf.config.yaml
  17. 104 0
      public/defaults/worlds/paint/index.vwf.yaml
  18. 14 0
      public/defaults/worlds/paint/info.json
  19. BIN
      public/defaults/worlds/paint/webimg.jpg
  20. 62 1
      public/lib/locale/en/en.json
  21. 62 1
      public/lib/locale/ru/ru.json
  22. 238 7
      public/lib/widgets.js
  23. 12 1
      public/vwf/model/aframe.js
  24. 132 24
      public/vwf/model/aframe/addon/aframe-components.js
  25. 515 0
      public/vwf/model/aframe/addon/aframe-teleport-controls.js
  26. 0 0
      public/vwf/model/aframe/addon/aframe-teleport-controls.min.js
  27. 787 0
      public/vwf/model/aframe/addon/three/BufferGeometryUtils.js
  28. 215 114
      public/vwf/model/aframe/aframe-master.js
  29. 0 0
      public/vwf/model/aframe/aframe-master.js.map
  30. 0 0
      public/vwf/model/aframe/aframe-master.min.js
  31. 0 0
      public/vwf/model/aframe/aframe-master.min.js.map
  32. 66 29
      public/vwf/model/aframe/extras/aframe-extras.controls.js
  33. 0 0
      public/vwf/model/aframe/extras/aframe-extras.controls.min.js
  34. 66 29
      public/vwf/model/aframe/extras/aframe-extras.js
  35. 0 0
      public/vwf/model/aframe/extras/aframe-extras.min.js
  36. 194 112
      public/vwf/view/aframe.js
  37. 10 0
      public/vwf/view/editor-new.js
  38. 5 7
      public/web/header.js
  39. 36 30
      public/web/index-app.js

+ 39 - 9
public/app.js

@@ -38,8 +38,11 @@ class App {
 
     import('/lib/polyglot/language.js').then(res => {
       window._LangManager = new res.default;
-      _LangManager.setLanguage();
-    }).then(res => {
+      return new Promise(r=>r(_LangManager.setLanguage()))})
+      .then(res=>{
+        window._l = _LangManager.language;
+      })
+    .then(res => {
       return import('/web/index-app.js');
     }).then(res => {
       window.IndexApp = res.default;
@@ -52,6 +55,7 @@ class App {
     //client routes
     page('/', this.HandleIndex);
     page('/setup', this.HandleSetupIndex);
+    page('/debug', this.HandleDebugIndex);
     page('/settings', this.HandleSettingsIndex);
     page('/profile', this.HandleUserIndex);
     page('/worlds', this.HandleIndex);
@@ -86,7 +90,9 @@ class App {
         'dbhost': window.location.origin + '/gun', // 'https://' + window.location.hostname + ':8080/gun', //'http://localhost:8080/gun',
         'reflector': 'https://' + window.location.hostname + ':3002',
         'webrtc': false,
-        'language': 'en'
+        'language': 'en',
+        'd3DoF': false,
+        'd6DoF': false
       }
       localStorage.setItem('lcs_config', JSON.stringify(config));
     }
@@ -111,6 +117,16 @@ class App {
       localStorage.setItem('lcs_config', JSON.stringify(config));
     }
 
+    if (!config.d3DoF) {
+      config.d3DoF = false;
+      localStorage.setItem('lcs_config', JSON.stringify(config));
+    }
+
+    if (!config.d6DoF) {
+      config.d6DoF = false;
+      localStorage.setItem('lcs_config', JSON.stringify(config));
+    }
+
     this.config = config;
 
     let webrtcConnection = this.config.webrtc;
@@ -444,6 +460,18 @@ class App {
 
   }
 
+  HandleDebugIndex() {
+
+    window._app.hideProgressBar();
+    window._app.hideUIControl();
+
+    let el = document.createElement("div");
+    el.setAttribute("id", "appGUI");
+    document.body.appendChild(el);
+
+    _cellWidgets.debugGUI();
+
+  }
 
   HandleSettingsIndex() {
 
@@ -1403,16 +1431,18 @@ class App {
   async loadAppLibs() {
 
     await loadjs([
-      '/vwf/model/aframe/aframe-master.min.js',
-      '/vwf/model/aframe/extras/aframe-extras.loaders.js',
-      '/vwf/model/aframe/extras/aframe-extras.controls.min.js',
-      '/vwf/model/aframe/kframe/aframe-aabb-collider-component.min.js',
-      '/vwf/model/aframe/addon/aframe-interpolation.js',
-      '/vwf/model/aframe/addon/aframe-sun-sky.js',
+      '/vwf/model/aframe/aframe-master.js',
       '/vwf/model/aframe/addon/SkyShader.js',
       '/vwf/model/aframe/addon/BVHLoader.js',
       '/vwf/model/aframe/addon/TransformControls.js',
       '/vwf/model/aframe/addon/THREE.MeshLine.js',
+      '/vwf/model/aframe/addon/three/BufferGeometryUtils.js',
+      '/vwf/model/aframe/addon/aframe-sun-sky.min.js',
+      '/vwf/model/aframe/extras/aframe-extras.loaders.min.js',
+      '/vwf/model/aframe/extras/aframe-extras.controls.min.js',
+      '/vwf/model/aframe/addon/aframe-teleport-controls.js',
+      '/vwf/model/aframe/kframe/aframe-aabb-collider-component.min.js',
+      '/vwf/model/aframe/addon/aframe-interpolation.js',
       '/vwf/model/aframe/addon/aframe-components.js'
       //'/vwf/view/arjs/aframe-ar.js' //load in aframe-ar-driver
     ], {

+ 10 - 0
public/defaults/proxy/vwf.example.com/aframe/aentity.js

@@ -3,6 +3,16 @@ this.getChildByName = function (name) {
     return nodes[0]
 }
 
+this.nodeDef = function () {
+    let def = _app.helpers.getNodeDef(this.id);
+    return def
+ }
+
+this.clone = function () {
+   let nodeDef = _app.helpers.getNodeDef(this.id);
+   return nodeDef
+}
+
 this.getScene =  function () {
     let scene = this.find("/")[0];
     return scene

+ 1 - 0
public/defaults/proxy/vwf.example.com/aframe/aentity.vwf.yaml

@@ -105,5 +105,6 @@ methods:
   step:
   do:
   randomize:
+  nodeDef:
 scripts:
   - source: "http://vwf.example.com/aframe/aentity.js"

+ 120 - 18
public/defaults/proxy/vwf.example.com/aframe/ascene.js

@@ -1,5 +1,6 @@
 this.initialize = function () {
     this.future(3).clientWatch();
+    //this.createDefaultXRCostume();
 };
 
 this.clientWatch = function () {
@@ -26,22 +27,33 @@ this.clientWatch = function () {
                         //console.log(node.id + 'is here!');
                     } else {
                         //console.log(node.id + " needed to delete!");
-                        self.children.delete(self.children[node.id]);
-                        //'gearvr-'
-                        let controllerVR = self.children['gearvr-' + node.id.slice(7)];
-                        if (controllerVR) {
-                            self.children.delete(controllerVR);
-                        }
-
-                        let wmrvR = self.children['wmrvr-right-' + node.id.slice(7)];
-                        if (wmrvR) {
-                            self.children.delete(wmrvR);
-                        }
-
-                        let wmrvL = self.children['wmrvr-left-' + node.id.slice(7)];
-                        if (wmrvL) {
-                            self.children.delete(wmrvL);
-                        }
+                        let idToDelete = node.id.slice(7);
+                        let nodes = self.children.filter(el=>
+                            (el.id.includes(idToDelete) && 
+                            (   el.id.includes('avatar') ||
+                                el.id.includes('xrcontroller') ||
+                                el.id.includes('gearvr')))
+                            );
+
+                        nodes.forEach(el => {
+                            self.children.delete(self.children[el.id])
+                        })
+                        // self.children.delete(self.children[node.id]);
+                        // //'gearvr-'
+                        // let controllerVR = self.children['gearvr-' + node.id.slice(7)];
+                        // if (controllerVR) {
+                        //     self.children.delete(controllerVR);
+                        // }
+
+                        // let wmrvR = self.children['wmrvr-right-' + node.id.slice(7)];
+                        // if (wmrvR) {
+                        //     self.children.delete(wmrvR);
+                        // }
+
+                        // let wmrvL = self.children['wmrvr-left-' + node.id.slice(7)];
+                        // if (wmrvL) {
+                        //     self.children.delete(wmrvL);
+                        // }
 
                     }
                 }
@@ -174,14 +186,16 @@ this.coneProto = function () {
     return node
 }
 
-this.textProto = function () {
+this.textProto = function (textValue) {
+
+    let value = textValue ? textValue: "Text";
 
     let node = {
         "extends": "http://vwf.example.com/aframe/atext.vwf",
         "properties": {
             "displayName": "text",
             "color": "white",
-            "value": "Text",
+            "value": value,
             "side": "double",
             "class": "clickable",
             //"font": "/vwf/model/aframe/fonts/custom-msdf.json",
@@ -544,6 +558,26 @@ this.createAssetResource = function(resType, resSrc){
 
 }
 
+this.createDrawNode = function(node, name, color, width, pos) {
+    let newNode = {
+        extends: "http://vwf.example.com/aframe/aentity.vwf",
+        properties: {
+            position: pos
+        },
+        children: {
+            linepath: {
+                extends: "http://vwf.example.com/aframe/linepath.vwf",
+                properties: {
+                    color: color,
+                    path: [],
+                    width: width
+                }
+            }
+        }
+    }
+
+    node.children.create(name, newNode);
+} 
 
 this.createPrimitive = function (type, params, name, node, avatar) {
 
@@ -1136,4 +1170,72 @@ this.enterVR = function(){
 
 this.exitVR = function(){
     console.log("EXIT VR");
+}
+
+this.getChildByName = function (name) {
+    let nodes = this.children.filter(el => el.displayName == name);
+    return nodes[0]
+}
+
+this.getAllChildsByName = function (name) {
+    let nodes = this.children.filter(el => el.displayName == name);
+    return nodes
+}
+
+this.getDefaultXRCostume = function(){
+    
+    let defaultXRCostume = {
+        "extends": "http://vwf.example.com/aframe/abox.vwf",
+        "properties": {
+            displayName: "defaultXRCostume",
+            "position": "0 0 0",
+            "height": 0.01,
+            "width": 0.01,
+            "depth": 1
+        },
+        "methods":{
+            triggerdown:{
+                body:'\/\/do on trigger down \n this.pointer.material.color = "red"',
+                type: "application/javascript"
+            },
+            triggerup:{
+                body:'\/\/do on trigger up \n this.pointer.material.color = "green"',
+                type: "application/javascript"
+            },
+            onMove:{
+                body:'\/\/do on move \n ',
+                type: "application/javascript"
+            }
+        },
+        children: {
+            "material": {
+                "extends": "http://vwf.example.com/aframe/aMaterialComponent.vwf",
+                "type": "component",
+                "properties":{
+                    "color": "white"
+                }
+            },
+            "pointer": {
+                "extends": "http://vwf.example.com/aframe/abox.vwf",
+                "properties": {
+                    "position": "0 0 -0.7",
+                    "height": 0.1,
+                    "width": 0.1,
+                    "depth": 0.1
+                },
+                children: {
+                    "material": {
+                        "extends": "http://vwf.example.com/aframe/aMaterialComponent.vwf",
+                        "type": "component",
+                        "properties":{
+                            "color": "green"
+                        }
+                    }
+                }
+            }
+        }
+    
+    }
+
+    return defaultXRCostume
 }

+ 16 - 0
public/defaults/proxy/vwf.example.com/aframe/ascene.vwf.yaml

@@ -25,6 +25,8 @@ methods:
   cylinderProto:
   coneProto:
   textProto:
+    parameters:
+      - textValue
   mirrorProto:
   lightProto:
     parameters:
@@ -86,7 +88,21 @@ methods:
   deleteNode:
     parameters:
       - nodeName
+  getChildByName:
+    parameters:
+      - name
+  getAllChildsByName:
+    parameters:
+      - name
+  getDefaultXRCostume:
   enterVR:
   exitVR:
+  createDrawNode:
+    parameters:
+      - node
+      - name
+      - color
+      - width
+      - pos
 scripts:
 - source: "http://vwf.example.com/aframe/ascene.js"

+ 22 - 9
public/defaults/proxy/vwf.example.com/aframe/avatar.js

@@ -61,13 +61,19 @@ this.findWorldAvatarCostume = function () {
     return null
 } 
 
+this.updateYPositionForXR = function(height){
+
+    if(this.avatarNode) {
+            let position = goog.vec.Vec3.clone(this.avatarNode.position);
+            this.avatarNode.position = [position[0], height, position[2]]
+    }
+
+}
+
 this.createAvatarBody = function (nodeDef, modelSrc) {
 
     var userHeight = -1.6;
 
-    // if (AFRAME.utils.device.isGearVR()) {
-    //     userHeight = 0
-    // }
 
     let myColor = "white"; //this.getRandomColor();
     let myBodyDef = this.simpleBodyDef;
@@ -319,17 +325,22 @@ this.createAvatarBody = function (nodeDef, modelSrc) {
 
 }
 
+this.updateAvatarRotation = function (rotation) { 
+    
+    let myRot = goog.vec.Vec3.clone(this.rotation);
+    let myHeadRot = goog.vec.Vec3.clone(this.avatarNode.myHead.rotation);
+    this.rotation = [myRot[0], rotation.y, myRot[2]];
+    this.avatarNode.myHead.rotation = [rotation.x, myHeadRot[1], rotation.z];
+}
+
 this.followAvatarControl = function (position, rotation) {
-    // this.position = AFRAME.utils.coordinates.stringify(position);
-    // this.rotation = AFRAME.utils.coordinates.stringify(rotation);
-//debugger;
 
-   // this.position = AFRAME.utils.coordinates.stringify(position);
-    this.position = goog.vec.Vec3.createFromValues(position.x, position.y, position.z);
+
+    //this.position = goog.vec.Vec3.createFromValues(position.x, position.y, position.z);
 
     let myRot = goog.vec.Vec3.clone(this.rotation);
     let myHeadRot = goog.vec.Vec3.clone(this.avatarNode.myHead.rotation);
-    let myBodyRot = goog.vec.Vec3.clone(this.avatarNode.myBody.rotation);
+    //let myBodyRot = goog.vec.Vec3.clone(this.avatarNode.myBody.rotation);
 
     //let myRot = AFRAME.utils.coordinates.parse(this.rotation);
     //let myHeadRot = AFRAME.utils.coordinates.parse(this.avatarNode.myHead.rotation);
@@ -389,6 +400,8 @@ this.changeCostume = function(val, restore){
 
 this.resetAvatar = function(){
 
+    //TODO: add XR check
+
     if (this.avatarNode) {
         //myNameValue = this.avatarNode.children.myName.properties.value;
         this.children.delete(this.avatarNode);

+ 6 - 0
public/defaults/proxy/vwf.example.com/aframe/avatar.vwf.yaml

@@ -27,10 +27,16 @@ methods:
         parameters:
             - nodeDef
             - modelSrc
+    updateYPositionForXR:
+        parameters:
+            - height    
     followAvatarControl:
         parameters:
             - position
             - rotation
+    updateAvatarRotation:
+        parameters:
+            - rotation
     setSmallVideoHead:
     setBigVideoHead:
     setVideoTexture:

+ 2 - 2
public/defaults/proxy/vwf.example.com/aframe/gearvrcontroller.js

@@ -19,7 +19,7 @@ this.simpleDef = {
         "pointer": {
             "extends": "http://vwf.example.com/aframe/abox.vwf",
             "properties": {
-                "position": "0 0 -0.8",
+                "position": "0 0 -0.7",
                 "height": 0.1,
                 "width": 0.1,
                 "depth": 0.1
@@ -96,7 +96,7 @@ this.createController = function (modelSrc) {
     var newNode = {
         "extends": "http://vwf.example.com/aframe/aentity.vwf",
         "properties": {
-            "position": [0, 0, 0]
+            "position": [0, 0, -0.4]
         },
         children: {
             "controller": controllerDef

+ 24 - 0
public/defaults/proxy/vwf.example.com/aframe/hand-controls.vwf.yaml

@@ -0,0 +1,24 @@
+# https://aframe.io/docs/master/components/hand-controls.html
+# Copyright 2017 Krestianstvo.org project
+---
+extends: http://vwf.example.com/aframe/aentity.vwf
+type: "handcontrols"
+properties:
+methods:
+    initialize:
+    updateController:
+    createSimpleController:
+    createControllerFromGLTF:
+        parameters:
+            - modelSrc
+    createController:
+        parameters:
+            - modelSrc
+    updateVRControl:
+        parameters:
+            - position
+            - rotation
+    triggerdown:
+    triggerup:
+scripts:
+- source: "http://vwf.example.com/aframe/handcontrols.js"

+ 2 - 2
public/defaults/proxy/vwf.example.com/aframe/wmrvrcontroller.js

@@ -19,7 +19,7 @@ this.simpleDef = {
         "pointer": {
             "extends": "http://vwf.example.com/aframe/abox.vwf",
             "properties": {
-                "position": "0 0 -0.8",
+                "position": "0 0 -0.7",
                 "height": 0.1,
                 "width": 0.1,
                 "depth": 0.1
@@ -71,7 +71,7 @@ this.createController = function (modelSrc) {
     var newNode = {
         "extends": "http://vwf.example.com/aframe/aentity.vwf",
         "properties": {
-            "position": [0, 0, 0]
+            "position": [0, 0, -0.4]
         },
         children: {
             "controller": controllerDef

+ 175 - 0
public/defaults/proxy/vwf.example.com/aframe/xrcontroller.js

@@ -0,0 +1,175 @@
+this.modelDef = {
+    "extends": "http://vwf.example.com/aframe/agltfmodel.vwf",
+    "properties": {
+        "src": "#xrcontroller",
+        "position": "0 0 0",
+        "rotation": "0 180 0"
+    },
+    "children": {
+        "animation-mixer": {
+            "extends": "http://vwf.example.com/aframe/anim-mixer-component.vwf",
+            "properties": {
+                "clip": "*",
+                "duration": 1
+            }
+        }
+
+    }
+}
+
+this.createController = function (modelSrc) {
+
+    let self = this;
+
+    var newNode = {
+        "extends": "http://vwf.example.com/aframe/aentity.vwf",
+        "properties": {
+            "position": [0, 0, -0.1]
+        },
+        children: {}
+    }
+
+    let interpolation =  {
+        "extends": "http://vwf.example.com/aframe/interpolation-component.vwf",
+        "type": "component",
+        "properties": {
+            "enabled": true
+        }
+    }
+
+
+    this.children.create( "interpolation", interpolation );
+    this.children.create("xrnode", newNode, function(child){
+        if(child) {
+            //find default costume
+            self.setControllerNode(modelSrc);
+        }
+
+    });
+
+}
+
+this.moveVRController = function(){
+
+    let controller = this.xrnode.controller;
+    if(controller){
+        controller.onMove();
+    }
+}
+
+this.updateVRControl = function(position, rotation){
+
+    this.rotation = rotation;
+    this.position = position;
+
+}
+
+
+// this.createSimpleController = function(){
+//        if (this.handVRNode.controller) {
+//         this.handVRNode.children.delete(this.handVRNode.controller);
+
+//         let controllerDef = this.simpleDef;
+
+//         this.handVRNode.children.create("controller", controllerDef);
+
+//        }
+// }
+
+this.createAvatarFromGLTF = function(modelSrc){
+
+    if (this.handVRNode.controller) {
+        this.handVRNode.children.delete(this.handVRNode.controller);
+        
+        let controllerDef = this.modelDef;
+        controllerDef.properties.src = modelSrc;
+
+        this.handVRNode.children.create("controller", controllerDef);
+
+       }
+}
+
+this.initialize = function() {
+   // this.future(0).update();
+}
+
+this.triggerdown = function() {
+    let controller = this.xrnode.controller;
+    if(controller){
+        controller.triggerdown();
+    }
+    //this.xrnode.controller.pointer.material.color = 'red'
+ }
+
+ this.triggerup = function() {
+    let controller = this.xrnode.controller;
+    if(controller){
+        controller.triggerup();
+    }
+    //this.xrnode.controller.pointer.material.color = 'green'
+ }
+
+this.saveToScene = function(){
+
+    let scene = this.getScene();
+    let controller = this.xrnode.controller;
+    if(controller){
+        let defNode = this.checkDefaultXRCostume();
+
+        if(defNode){
+            scene.children.delete(defNode);
+        } 
+
+       let node = controller.nodeDef(); 
+       node.properties.visible = false;
+       node.properties.displayName = 'defaultXRCostume';
+        scene.children.create('defaultXRCostume', node, function( child ) {
+            console.log('Save default controller costume to scene: ', child);
+           });
+
+    }
+
+}
+
+ this.checkDefaultXRCostume = function(){
+    let scene = this.getScene();
+    let defaultNode = scene.getChildByName('defaultXRCostume');
+    return defaultNode ? defaultNode : undefined
+ }
+
+
+this.setControllerNode = function(modelSrc){
+
+    let scene = this.getScene();
+    let defaultNode = this.checkDefaultXRCostume();
+    let oldCostume = this.xrnode.controller;
+    if(oldCostume){
+        this.xrnode.children.delete(oldCostume);
+    }
+
+    if(defaultNode) {
+        let def = _app.helpers.getNodeDef(defaultNode.id);
+        def.properties.position = '0 0 0';
+        def.properties.rotation = '0 0 0';
+        def.properties.visible = true;
+        def.properties.displayName = 'controller';
+        this.xrnode.children.create('controller', def, function( child ) {
+            console.log('Restore controller costume: ', child)
+           });
+    } else {
+
+        let controllerDef = scene.getDefaultXRCostume();
+        controllerDef.properties.displayName = 'controller';
+
+        if (modelSrc) {
+            let controllerDef = this.modelDef;
+            controllerDef.properties.src = modelSrc;
+        }
+
+        this.xrnode.children.create('controller', controllerDef, function( child ) {
+            console.log('New controller costume: ', child)
+           });
+    
+    }
+
+}

+ 30 - 0
public/defaults/proxy/vwf.example.com/aframe/xrcontroller.vwf.yaml

@@ -0,0 +1,30 @@
+# xrcontroller controller
+# Copyright 2017 Krestianstvo.org project
+---
+extends: http://vwf.example.com/aframe/aentity.vwf
+type: "xrcontroller"
+properties:
+methods:
+    initialize:
+    updateController:
+    createSimpleController:
+    createControllerFromGLTF:
+        parameters:
+            - modelSrc
+    createController:
+        parameters:
+            - modelSrc
+    updateVRControl:
+        parameters:
+            - position
+            - rotation
+    triggerdown:
+    triggerup:
+    checkDefaultXRCostume:
+    setControllerNode:
+        parameters:
+            - modelSrc
+    saveToScene:
+    moveVRController:
+scripts:
+- source: "http://vwf.example.com/aframe/xrcontroller.js"

+ 6 - 0
public/defaults/worlds/paint/appui.js

@@ -0,0 +1,6 @@
+//-----App ui-----
+
+// function createApp() {
+    
+//     }
+    

+ 10 - 0
public/defaults/worlds/paint/assets.json

@@ -0,0 +1,10 @@
+{
+    "sky":{
+        "tag": "img",
+        "src": "/defaults/assets/skyes/sky3.jpg"
+    },
+     "bg2":{
+        "tag": "img",
+        "src": "/defaults/assets/checker.jpg"
+    }
+}

+ 24 - 0
public/defaults/worlds/paint/controller.js

@@ -0,0 +1,24 @@
+this.triggerdown = function(){
+    let scene = this.getScene();
+    this.pointer.material.color = "white";
+    this.penDown = true;
+    this.penName = 'drawNode-' + scene.GUID();
+    scene.createDrawNode(scene.drawBox, this.penName, "#f9f9f9", 0.007, "0 0 0");
+}
+
+this.triggerup = function(){
+    this.pointer.material.color = "green";
+    this.penDown = false;
+}
+
+this.onMove = function(){
+    if(this.penDown){
+        let scene = this.getScene();
+        let pen = scene.drawBox.children[this.penName];
+        let pos = this.pointer.worldPosition();
+        let path = pen.linepath.path.slice();
+        path.push(pos);
+        pen.linepath.path = path;
+    }
+    
+}

+ 8 - 0
public/defaults/worlds/paint/index.vwf.config.yaml

@@ -0,0 +1,8 @@
+---
+info:
+  title: "Paint App"
+model:
+  vwf/model/aframe:
+view:
+  vwf/view/aframe:
+  vwf/view/editor-new:

+ 104 - 0
public/defaults/worlds/paint/index.vwf.yaml

@@ -0,0 +1,104 @@
+# A-Frame & VWF simple scene
+# Copyright 2017 Krestianstvo.org project
+---
+extends: http://vwf.example.com/aframe/ascene.vwf
+properties:
+  assets: "assets.json"
+children:
+  fog:
+    extends: http://vwf.example.com/aframe/aSceneFogComponent.vwf
+    type: "component"
+    properties:
+      fogType: "linear"
+      fogColor: "#ECECEC"
+      far: 20
+      near: 0
+  groundPlane:
+    extends: http://vwf.example.com/aframe/aplane.vwf
+    properties:
+      height: 50
+      width: 50
+      rotation: "-90 0 0"
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          wireframe: false
+          src: "#bg2"
+          repeat: "10 10"
+  myLight:
+    extends: http://vwf.example.com/aframe/alight.vwf
+    properties:
+      type: "point"
+      color: "white"
+      position: "0 3 0"
+      rotation: "0 0 0"
+  sky:
+    extends: http://vwf.example.com/aframe/asky.vwf
+    properties:
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "#ECECEC"
+          src: "#sky"
+          fog: false
+          side: "back"
+  spaceText:
+    extends: http://vwf.example.com/aframe/atext.vwf
+    properties:
+      value: "Paint App"
+      color: "white"
+      position: "-2 2.5 -2"
+  box:
+    extends: http://vwf.example.com/aframe/abox.vwf
+    properties:
+      position: "0 0 -3"
+      rotation: "0 0 0"
+      depth: 3
+      height: 0.2
+      width: 3
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        properties:
+          color: "#3c7249"
+  drawBox:
+    extends: http://vwf.example.com/aframe/aentity.vwf
+    properties:
+      position: "0 0 0"
+  defaultXRCostume:
+    extends: http://vwf.example.com/aframe/abox.vwf
+    properties:
+      displayName: "defaultXRCostume"
+      position: "0 0 0"
+      height: 0.01
+      width: 0.01
+      depth: 0.3
+      penDown: false
+      penName: "drawNode"
+    children:
+      material:
+        extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+        type: "component"
+        properties:
+          color: "#6aa171"
+      pointer:
+        extends: http://vwf.example.com/aframe/abox.vwf
+        properties:
+          position: "0 0 -0.25"
+          height: 0.05
+          width: 0.05
+          depth: 0.05
+        children:
+          material:
+            extends: http://vwf.example.com/aframe/aMaterialComponent.vwf
+            type: "component"
+            properties:
+              color: "green"
+    methods:
+      triggerdown:
+      triggerup:
+      onMove:
+    scripts:
+      - source: "controller.js"

+ 14 - 0
public/defaults/worlds/paint/info.json

@@ -0,0 +1,14 @@
+{
+    "info": {
+        "en": {
+            "title": "Paint app in Web XR",
+            "imgUrl": "/defaults/worlds/webrtc/webimg.jpg",
+            "text": "Painting app using Web XR controllers"
+        },
+        "ru": {
+            "title": "Рисование в Web XR",
+            "imgUrl": "/defaults/worlds/webrtc/webimg.jpg",
+            "text": "Пример приложения для рисования с помощью контроллеров Web XR"
+        }
+    }
+}

BIN
public/defaults/worlds/paint/webimg.jpg


+ 62 - 1
public/lib/locale/en/en.json

@@ -1,7 +1,68 @@
 {
+    "header_home": "Home",
+    "conn_settings":"Connection settings",
+    "help":"Help",
+    "en":"English",
+    "ru":"Русский",
     "home": "Home",
     "App": "App",
     "clone proto": "Clone",
     "start": "Start",
-    "users": "Users"
+    "users": "Users",
+    "welcome": "Welcome",
+    "login": "Login",
+    "password": "Password",
+   "sign up": "Sign up",
+   "sign in": "Sign in",
+   "sign out": "Sign out",
+   "profile": "My profile",
+   "show worlds": "Search for Worlds, made by other Users!",
+   "my world protos": "My protos",
+    "my world states": "My worlds",
+   "world protos": "protos",
+    "world states": "worlds",
+    "protos for": "World protos by - ",
+    "states for": "Worlds by  - ",
+    "enter user name": "Enter user name",
+    "details": "details",
+    "online now": "online now",
+    "scene": "Scene",
+    "create": "Create",
+    "code editor": "Code editor",
+    "my avatar": "My Avatar",
+    "settings": "Settings",
+    "clone/save": "Clone/Save",
+    "chat": "chat",
+    "users online": "users online",
+   "methods browser": "methods browser",
+    "children": "children",
+    "properties": "properties",
+    "proto properties": "proto properties",
+    "actions": "actions",
+    "primitives": "Primitives",
+     "lights": "Lights",
+     "objects": "Objects",
+     "assets": "Assets",
+     "resources": "Resources",
+     "image": "IMAGE",
+     "sound": "SOUND",
+     "video": "VIDEO",
+     "enter URL to asset source": "Enter URL to asset source",
+     "enter google poly model ID ": "Enter Google Poly model ID",
+     "load from poly": "Load from Poly",
+     "reset camera view": "reset camera view",
+     "hide cursor": "hide cursor",
+    "show cursor": "show cursor",
+     "hide avatar": "hide avatar",
+     "show avatar": "show avatar",
+     "reset avatar": "reset avatar",
+     "cube simple": "cube simple ",
+     "female human": "female human",
+     "male human": "male human",
+     "wide": "WIDE",
+     "small": "SMALL",
+     "OSC settings": "OSC settings",
+     "node methods": "NODE METHODS",
+     "proto methods": "PROTO METHODS",
+     "methods name": "Methods name"
 }

+ 62 - 1
public/lib/locale/ru/ru.json

@@ -1,7 +1,68 @@
 {
+    "header_home": "Домой",
+    "conn_settings":"Свойства подключения",
+    "help":"Помощь",
+    "en":"English",
+    "ru":"Русский",
     "home": "Дом",
     "App": "Программа",
     "clone proto": "Клонировать",
     "start": "Запустить",
-    "users": "Пользователи"
+    "users": "Пользователи",
+    "welcome": "Добро пожаловать",
+    "login": "Имя",
+    "password": "Пароль",
+    "sign up": "Зарегистрироваться",
+    "sign in": "Войти",
+    "sign out": "Выйти",
+    "profile": "Мой профиль",
+    "show worlds": "Найти Миры, созданные другими пользователями!",
+    "my world protos": "Мои прототипы",
+    "my world states": "Мои миры",
+    "world protos": "Прототипы",
+    "world states": "Миры",
+    "protos for": "Прототипы миров пользователя: ",
+    "states for": "Миры пользователя: ",
+    "enter user name": "Введите имя пользователя",
+    "details": "Подробнее",
+    "online now": "онлайн",
+    "scene": "Сцена",
+    "create": "Создать",
+    "code editor": "Редактор кода",
+    "my avatar": "Мой Аватар",
+    "settings": "Настройки",
+    "clone/save": "Клонировать/Сохранить",
+    "chat": "Чат",
+    "users online": "пользователи в сети",
+   "methods browser": "методы браузера",
+    "children": "дети",
+    "properties": "Свойства",
+    "proto properties": "Свойства прототипа",
+    "actions": "Действия",
+     "primitives": "Простые объекы",
+     "lights": "Освещение",
+     "objects": "Объекты",
+     "assets": "Ресурсы",
+     "resources": "Материалы",
+     "image": "Изображения",
+     "sound": "Звук",
+     "video": "видео",
+     "enter URL to asset source": "введите URL источника ресурса",
+     "enter google poly model ID ": "введите Google Poly модель ID",
+     "load from poly": "Загрузить из Poly",
+     "reset camera view": "Сбросит камеры вид",
+     "hide cursor": "Спрятать курсор",
+    "show cursor": "Показать курсор",
+     "hide avatar": "Спрятать аватара",
+     "show avatar": "Показать аватара",
+     "reset avatar": "Сбросить аватара",
+     "cube simple": "Простой ",
+     "female human": "Женский образ",
+     "male human": "Мужской образ",
+     "wide": "Большой",
+     "small": "Маленький",
+     "OSC settings": "OSC настройки",
+     "node methods": "методы узла",
+     "proto methods": "методы прототипа",
+     "methods name": "имя метода"
 }

+ 238 - 7
public/lib/widgets.js

@@ -714,8 +714,224 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
             
         }
 
+        debugGUI() {
+
+            let self = this;
+
+            let debug6DoF = {
+                $cell: true,
+                $components: [
+                  {
+                    $type: "p",
+                    class: "mdc-typography--headline5",
+                    $text: "Debug 6DoF mode (for using with WebXR emulator)"
+                  },
+                  {
+                    $type: 'p'
+                  },
+                  _app.widgets.switch({
+                    'id': 'forceDebug6DoF',
+                    'init': function () {
+                      this._switch = new mdc.switchControl.MDCSwitch(this);
+                      let config = localStorage.getItem('lcs_config');
+                      this._switch.checked = JSON.parse(config).d6DoF;
+                      
+                     // this._replaceSwitch = this._switch;
+                      
+                    },
+                    'onchange': function (e) {
+    
+                        if (this._switch) {
+                            let chkAttr = this._switch.checked;//this.getAttribute('checked');
+                            if (chkAttr) {
+                                let config = JSON.parse(localStorage.getItem('lcs_config'));
+                                config.d6DoF = true;
+                                localStorage.setItem('lcs_config', JSON.stringify(config));
+                                //this._switch.checked = false;
+                            } else {
+                                let config = JSON.parse(localStorage.getItem('lcs_config'));
+                                config.d6DoF = false;
+                                localStorage.setItem('lcs_config', JSON.stringify(config));
+                            }
+                        }
+                    }
+                  }
+                  ),
+                  {
+                    $type: 'label',
+                    for: 'input-forceDebug6DoF',
+                    $text: 'On / Off'
+                  }
+    
+                ]
+              }
+
+              let debug3DoF = {
+                $cell: true,
+                $components: [
+                  {
+                    $type: "p",
+                    class: "mdc-typography--headline5",
+                    $text: "Debug 3DoF mode (for using with WebXR emulator)"
+                  },
+                  {
+                    $type: 'p'
+                  },
+                  _app.widgets.switch({
+                    'id': 'forceDebug3DoF',
+                    'init': function () {
+                      this._switch = new mdc.switchControl.MDCSwitch(this);
+                      let config = localStorage.getItem('lcs_config');
+                      this._switch.checked = JSON.parse(config).d3DoF;
+                      
+                     // this._replaceSwitch = this._switch;
+                      
+                    },
+                    'onchange': function (e) {
+    
+                        if (this._switch) {
+                            let chkAttr = this._switch.checked;//this.getAttribute('checked');
+                            if (chkAttr) {
+                                let config = JSON.parse(localStorage.getItem('lcs_config'));
+                                config.d3DoF = true;
+                                localStorage.setItem('lcs_config', JSON.stringify(config));
+                                //this._switch.checked = false;
+                            } else {
+                                let config = JSON.parse(localStorage.getItem('lcs_config'));
+                                config.d3DoF = false;
+                                localStorage.setItem('lcs_config', JSON.stringify(config));
+                            }
+                        }
+                    }
+                  }
+                  ),
+                  {
+                    $type: 'label',
+                    for: 'input-forceDebug3DoF',
+                    $text: 'On / Off'
+                  }
+    
+                ]
+              }
+
+
+              let allGUI =
+              {
+                  $type: "div",
+                  id: "allGUI",
+                  //style:"background-color: #efefef",
+                  class: "mdc-layout-grid mdc-layout-grid--align-left",
+                  _d3DoF: null,
+                  _d6DoF: null,
+                  _initData: function () {
+          
+                      let config = JSON.parse(localStorage.getItem('lcs_config'));
+          
+                      if (config.d3DoF) {
+                          this._d3DoF = config.d3DoF
+                      }
+                      if (config.d6DoF) {
+                          this._d6DoF =config.d6DoF
+                      }
+                    
+                      this._refresh();
+                 },
+                  $init: function () {
+                      this._initData();
+                  },
+                  _refresh: function () {
+          
+                      this.$components = [
+                          {
+                              $type: "div",
+                              class: "mdc-layout-grid__inner",
+                              $components: [
+                                  {
+                                      $type: "div",
+                                      class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                      $components: [
+                                      {
+                                          $type: "h4",
+                                          class: "mdc-typography--headline4",
+                                          $text: "Debug settings"
+                                      }
+                                  ]
+                                  },
+                                 { 
+                                  $type: "div",
+                                  class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                  $components: [debug6DoF ]
+                                 },
+                                 { 
+                                  $type: "div",
+                                  class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                  $components: [_app.widgets.divider]
+                                 },
+                                 { 
+                                  $type: "div",
+                                  class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                  $components: [debug3DoF]
+                                 },
+                                  {
+                                      $type: "div",
+                                      class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                      $components: [
+                                        //   window._app.widgets.buttonRaised(
+                                        //       {
+                                        //           "label": 'Update',
+                                        //           "onclick": function (e) {
+                                        //               e.preventDefault();
+          
+                                        //               let config = JSON.parse(localStorage.getItem('lcs_config'));
+          
+                                        //               config.reflector = this._refHostField.value;
+                                        //               config.dbhost = this._dbHostField.value;
+                                        //               config.luminaryPath = this._lpathField.value;
+                                        //               config.luminaryGlobalHBPath = this._hbpathField.value;
+          
+                                        //               localStorage.setItem('lcs_config', JSON.stringify(config));
+                                        //               window.location.reload(true);
+                                        //           }
+                                        //       }),
+                                              {
+                                                $type: 'span',
+                                                $text: " "
+                                              },
+                                              {
+                                                $type: "button",
+                                                class: "mdc-button mdc-button--raised",
+                                                $text: "Close",
+                                                onclick: function (e) {
+                                                      window.history.back();
+                                                    //window.location.pathname = '/'
+                                                }
+                                              }
+                                      ]
+                                  }
+          
+                              ]
+                          }
+                      ]
+                  }
+          
+              }
+          
+              document.querySelector("#appGUI").$cell({
+                  id: "appGUI",
+                  $cell: true,
+                  $type: "div",
+                  $components: [allGUI]
+              }
+              );
+
+
+
+            }
+
         reflectorGUI() {
 
+            let self = this;
+
             let webrtcConnection = {
                 $cell: true,
                 $components: [
@@ -881,6 +1097,7 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                 _lpathField: null,
                 _hbpath: null,
                 _hbpathField: null,
+                //_debug: null,
                 _initData: function () {
                     this._reflectorHost = '';
                     this._dbHost = '';
@@ -899,6 +1116,9 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                     if (config.luminaryGlobalHBPath) {
                         this._hbpath = config.luminaryGlobalHBPath
                     }
+                    // if (config.debug) {
+                    //     this._debug = config.debug
+                    // }
 
                 },
                 $init: function () {
@@ -1052,6 +1272,16 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                                 class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
                                 $components: [luminaryGlobalHB ]
                                },
+                               { 
+                                $type: "div",
+                                class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                                $components: [_app.widgets.divider]
+                               },
+                            //    { 
+                            //     $type: "div",
+                            //     class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                            //     $components: [debugGUI]
+                            //    },
                                 {
                                     $type: "div",
                                     class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
@@ -1082,7 +1312,8 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                                               class: "mdc-button mdc-button--raised",
                                               $text: "Close",
                                               onclick: function (e) {
-                                                  window.location.pathname = '/'
+                                                    window.history.back();
+                                                  //window.location.pathname = '/'
                                               }
                                             }
                                     ]
@@ -1145,11 +1376,11 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                                         {
                                             $type: "span",
                                             class: "mdc-typography--headline5",
-                                            $text: "Login: "
+                                            $text: _l.t("login") + ": "
                                         },
                                         window._app.widgets.inputTextFieldOutlined({
                                             "id": 'aliasInput',
-                                            "label": "Login",
+                                            "label": _l.t("login"),
                                             "value": this._alias,
                                             "type": "text",
                                             "init": function () {
@@ -1165,11 +1396,11 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                                         {
                                             $type: "span",
                                             class: "mdc-typography--headline5",
-                                            $text: "Password: "
+                                            $text: _l.t("password") + ": "
                                         },
                                         window._app.widgets.inputTextFieldOutlined({
                                             "id": 'passwordInput',
-                                            "label": "Password",
+                                            "label": _l.t("password"),
                                             "value": this._pass,
                                             "type": "password",
                                             "init": function () {
@@ -1184,7 +1415,7 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                                     $components: [
                                         window._app.widgets.buttonRaised(
                                             {
-                                                "label": 'Sign UP',
+                                                "label": _l.t("sign up"),
                                                 "onclick": function (e) {
                                                     e.preventDefault();
     
@@ -1225,7 +1456,7 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
                                         _app.widgets.space,
                                         window._app.widgets.buttonRaised(
                                             {
-                                                "label": 'Sign IN',
+                                                "label": _l.t("sign in"),
                                                 "onclick": function (e) {
                                                     e.preventDefault();
                                                     let alias = this._aliasField.value;

+ 12 - 1
public/vwf/model/aframe.js

@@ -588,11 +588,19 @@ define(["module", "vwf/model", "vwf/utility"], function (module, model, utility)
                 if (value === undefined && aframeObject.nodeName == "A-TEXT") {
                     value = propertyValue;
 
+                    //.filter(el=>el !== 'font')
                     self.aframeDef['A-TEXT'].forEach(element => {
-                        element == propertyName ? aframeObject.setAttribute(element, propertyValue) :
+
+                       
+                            element == propertyName ? aframeObject.setAttribute(element, propertyValue) :
                             value = undefined;
+                        
                     })
 
+                    // if(propertyName == 'font'){
+                    //     console.log('Loading font...', element);
+                    // }
+
                 }
 
                 if (value === undefined && aframeObject.nodeName == "A-SCENE") {
@@ -1374,6 +1382,9 @@ define(["module", "vwf/model", "vwf/utility"], function (module, model, utility)
             //aframeObj.setAttribute('embedded', {});
             //aframeObj.setAttribute('loading-screen', "backgroundColor: black");
             self.state.scenes[node.ID] = aframeObj;
+            //TODO: move from veiw here
+            //document.body.appendChild(aframeObj);
+
         } else if (self.state.isAFrameClass(protos, "http://vwf.example.com/aframe/a-asset-item.vwf")) {
 
             let assets = document.querySelector('a-assets');

+ 132 - 24
public/vwf/model/aframe/addon/aframe-components.js

@@ -7,41 +7,55 @@ if (typeof AFRAME === 'undefined') {
     throw new Error('Component attempted to register before AFRAME was available.');
 }
 
+AFRAME.registerComponent('avatar', {
+
+
+    init: function () {
+    },
+    tick: function () {  
+    }
+})
+       
+
+
 AFRAME.registerComponent('scene-utils', {
 
 
     init: function () {
         this.mirrors = {};
 
+        //this.setCameraControl();
         const sceneEnterVR = (e) => {
 
-            //vwf_view.kernel.callMethod(vwf.application(), "enterVR");
-            let avatarEl = document.querySelector('#avatarControlParent');
-            if (AFRAME.utils.device.isMobileVR()) {
+            let driver = vwf.views["vwf/view/aframe"];
 
-            } else if (AFRAME.utils.device.isMobile()) {
-                avatarEl.setAttribute('position', '0 0 0')
-            } else {
-                avatarEl.setAttribute('position', '0 0 0'); //'0 1.6 0'
-            }
+            // let avatarEl = document.querySelector('#avatarControlParent');
+             let avatarID = 'avatar-' + vwf_view.kernel.moniker();
 
-            // if (!AFRAME.utils.device.isGearVR() && !AFRAME.utils.device.isMobile()) {
-            //     avatarEl.setAttribute('position', '0 1.6 0');
-            // }
+            driver.hmd = true;
+
+            if (driver.threeDoFMobile || _app.config.d3DoF ) {
+                driver.threeDoF = true;
+                 vwf_view.kernel.callMethod(avatarID, "updateYPositionForXR", [0.0]);
+            } else if (driver.sixDoFMobile || driver.sixDoFDesktop || _app.config.d6DoF ) {
+                driver.sixDoF = true;
+            }
 
         }
 
         const sceneExitVR = (e) => {
 
-            //vwf_view.kernel.callMethod(vwf.application(), "exitVR");
-            let avatarEl = document.querySelector('#avatarControlParent');
+            let driver = vwf.views["vwf/view/aframe"];
+            let avatarID = 'avatar-' + vwf_view.kernel.moniker();
 
-            if (AFRAME.utils.device.isMobileVR()) {
-                //avatarEl.setAttribute('position', '0 0 0');
-            } else if (AFRAME.utils.device.isMobile()) {
-                avatarEl.setAttribute('position', '0 1.6 0');
-            } else {
-                avatarEl.setAttribute('position', '0 0 0');
+            driver.hmd = false;
+            
+            if (driver.threeDoFMobile || _app.config.d3DoF ) {
+                driver.threeDoF = false;
+                vwf_view.kernel.callMethod(avatarID, "updateYPositionForXR", [-1.6]);
+
+            } else if (driver.sixDoFMobile || driver.sixDoFDesktop || _app.config.d6DoF ) {
+                driver.sixDoF = false;
             }
 
         }
@@ -51,6 +65,35 @@ AFRAME.registerComponent('scene-utils', {
 
     },
 
+    setCameraControl(){
+
+        let avatarEl = document.querySelector('#avatarControl');
+
+        document.addEventListener('keydown', (event) => {
+            const keyName = event.key;
+          
+            if (keyName === 'Alt') {
+              // do not alert when only Control key is pressed.
+              console.log(keyName, ' pressed');
+              avatarEl.setAttribute('look-controls', 'enabled', true)
+              return;
+            }
+        })
+        
+        document.addEventListener('keyup', (event) => {
+            const keyName = event.key;
+          
+            if (keyName === 'Alt') {
+              // do not alert when only Control key is pressed.
+              console.log(keyName, ' released');
+              avatarEl.setAttribute('look-controls', 'enabled', false)
+              return;
+            }
+        })
+
+
+    },
+
     update: function () {
 
     },
@@ -477,6 +520,27 @@ AFRAME.registerComponent('gearvrcontrol', {
             vwf_view.kernel.callMethod(controllerID, "triggerup", []);
         });
 
+         //X-buttorn Pressed 
+         this.el.addEventListener('buttondown', function (e) { //xbuttondown
+            //Start pointing position to teleport  
+           //let buttonID = e.detail.id;
+           //let avatarID = 'avatar-' + vwf_view.kernel.moniker();
+           //vwf_view.kernel.callMethod(vwf.application(), "createPrimitive", ['text', buttonID, 'debug', null, avatarID]);
+           if(e.detail.id == 2){
+            this.emit('teleportstart');
+           }
+            
+        });
+
+        //X-buttorn Released 
+        this.el.addEventListener('buttonup', function (e) { //xbuttonup
+            //Jump to pointed position
+            if(e.detail.id == 2){
+                this.emit('teleportend');
+               }
+            
+        });
+
     },
 
     update: function () {
@@ -486,6 +550,50 @@ AFRAME.registerComponent('gearvrcontrol', {
     // }
 })
 
+AFRAME.registerComponent('xrcontroller', {
+
+    schema: {
+        hand: { default: 'right' }
+    },
+
+    update: function (old) {
+        this.hand = this.data.hand;
+    },
+
+    init: function () {
+        var self = this;
+        this.hand = this.data.hand;
+        this.controllerID = 'xrcontroller-' + this.hand + '-' + vwf_view.kernel.moniker();
+
+        this.el.addEventListener('triggerdown', function (event) { //pointdown 'triggerdown'
+            vwf_view.kernel.callMethod(self.controllerID, "triggerdown", []);
+        });
+        this.el.addEventListener('triggerup', function (event) { //pointup 'triggerup'
+            vwf_view.kernel.callMethod(self.controllerID, "triggerup", []);
+        });
+
+         //X-buttorn Pressed 
+         this.el.addEventListener('xbuttondown', function (e) { //xbuttondown
+            //Start pointing position to teleport  
+            this.emit('teleportstart');
+        });
+
+        //X-buttorn Released 
+        this.el.addEventListener('xbuttonup', function (e) { //xbuttonup
+            //Jump to pointed position
+            this.emit('teleportend');
+        });
+
+        this.el.addEventListener('teleported', function (e) { //xbuttonup
+            //Teleported
+            console.log('TELEPORTED: ', e);
+
+        });
+    },
+
+    // tick: function (t) {
+    // }
+})
 
 AFRAME.registerComponent('wmrvrcontrol', {
 
@@ -500,13 +608,13 @@ AFRAME.registerComponent('wmrvrcontrol', {
     init: function () {
         var self = this;
         this.hand = this.data.hand;
-        var controllerID = 'wrmr-' + this.hand + '-' + vwf_view.kernel.moniker();
+        this.controllerID = 'wmrvr-' + this.hand + '-' + vwf_view.kernel.moniker();
         //this.gearel = document.querySelector('#gearvrcontrol');
-        this.el.addEventListener('triggerdown', function (event) {
-            vwf_view.kernel.callMethod(controllerID, "triggerdown", []);
+        this.el.addEventListener('triggerdown', function (event) { //pointdown 'triggerdown'
+            vwf_view.kernel.callMethod(self.controllerID, "triggerdown", []);
         });
-        this.el.addEventListener('triggerup', function (event) {
-            vwf_view.kernel.callMethod(controllerID, "triggerup", []);
+        this.el.addEventListener('triggerup', function (event) { //pointup 'triggerup'
+            vwf_view.kernel.callMethod(self.controllerID, "triggerup", []);
         });
     },
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 515 - 0
public/vwf/model/aframe/addon/aframe-teleport-controls.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
public/vwf/model/aframe/addon/aframe-teleport-controls.min.js


+ 787 - 0
public/vwf/model/aframe/addon/three/BufferGeometryUtils.js

@@ -0,0 +1,787 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.BufferGeometryUtils = {
+
+	computeTangents: function ( geometry ) {
+
+		var index = geometry.index;
+		var attributes = geometry.attributes;
+
+		// based on http://www.terathon.com/code/tangent.html
+		// (per vertex tangents)
+
+		if ( index === null ||
+			 attributes.position === undefined ||
+			 attributes.normal === undefined ||
+			 attributes.uv === undefined ) {
+
+			console.error( 'THREE.BufferGeometryUtils: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
+			return;
+
+		}
+
+		var indices = index.array;
+		var positions = attributes.position.array;
+		var normals = attributes.normal.array;
+		var uvs = attributes.uv.array;
+
+		var nVertices = positions.length / 3;
+
+		if ( attributes.tangent === undefined ) {
+
+			geometry.setAttribute( 'tangent', new THREE.BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
+
+		}
+
+		var tangents = attributes.tangent.array;
+
+		var tan1 = [], tan2 = [];
+
+		for ( var i = 0; i < nVertices; i ++ ) {
+
+			tan1[ i ] = new THREE.Vector3();
+			tan2[ i ] = new THREE.Vector3();
+
+		}
+
+		var vA = new THREE.Vector3(),
+			vB = new THREE.Vector3(),
+			vC = new THREE.Vector3(),
+
+			uvA = new THREE.Vector2(),
+			uvB = new THREE.Vector2(),
+			uvC = new THREE.Vector2(),
+
+			sdir = new THREE.Vector3(),
+			tdir = new THREE.Vector3();
+
+		function handleTriangle( a, b, c ) {
+
+			vA.fromArray( positions, a * 3 );
+			vB.fromArray( positions, b * 3 );
+			vC.fromArray( positions, c * 3 );
+
+			uvA.fromArray( uvs, a * 2 );
+			uvB.fromArray( uvs, b * 2 );
+			uvC.fromArray( uvs, c * 2 );
+
+			vB.sub( vA );
+			vC.sub( vA );
+
+			uvB.sub( uvA );
+			uvC.sub( uvA );
+
+			var r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
+
+			// silently ignore degenerate uv triangles having coincident or colinear vertices
+
+			if ( ! isFinite( r ) ) return;
+
+			sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
+			tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
+
+			tan1[ a ].add( sdir );
+			tan1[ b ].add( sdir );
+			tan1[ c ].add( sdir );
+
+			tan2[ a ].add( tdir );
+			tan2[ b ].add( tdir );
+			tan2[ c ].add( tdir );
+
+		}
+
+		var groups = geometry.groups;
+
+		if ( groups.length === 0 ) {
+
+			groups = [ {
+				start: 0,
+				count: indices.length
+			} ];
+
+		}
+
+		for ( var i = 0, il = groups.length; i < il; ++ i ) {
+
+			var group = groups[ i ];
+
+			var start = group.start;
+			var count = group.count;
+
+			for ( var j = start, jl = start + count; j < jl; j += 3 ) {
+
+				handleTriangle(
+					indices[ j + 0 ],
+					indices[ j + 1 ],
+					indices[ j + 2 ]
+				);
+
+			}
+
+		}
+
+		var tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3();
+		var n = new THREE.Vector3(), n2 = new THREE.Vector3();
+		var w, t, test;
+
+		function handleVertex( v ) {
+
+			n.fromArray( normals, v * 3 );
+			n2.copy( n );
+
+			t = tan1[ v ];
+
+			// Gram-Schmidt orthogonalize
+
+			tmp.copy( t );
+			tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
+
+			// Calculate handedness
+
+			tmp2.crossVectors( n2, t );
+			test = tmp2.dot( tan2[ v ] );
+			w = ( test < 0.0 ) ? - 1.0 : 1.0;
+
+			tangents[ v * 4 ] = tmp.x;
+			tangents[ v * 4 + 1 ] = tmp.y;
+			tangents[ v * 4 + 2 ] = tmp.z;
+			tangents[ v * 4 + 3 ] = w;
+
+		}
+
+		for ( var i = 0, il = groups.length; i < il; ++ i ) {
+
+			var group = groups[ i ];
+
+			var start = group.start;
+			var count = group.count;
+
+			for ( var j = start, jl = start + count; j < jl; j += 3 ) {
+
+				handleVertex( indices[ j + 0 ] );
+				handleVertex( indices[ j + 1 ] );
+				handleVertex( indices[ j + 2 ] );
+
+			}
+
+		}
+
+	},
+
+	/**
+	 * @param  {Array<THREE.BufferGeometry>} geometries
+	 * @param  {Boolean} useGroups
+	 * @return {THREE.BufferGeometry}
+	 */
+	mergeBufferGeometries: function ( geometries, useGroups ) {
+
+		var isIndexed = geometries[ 0 ].index !== null;
+
+		var attributesUsed = new Set( Object.keys( geometries[ 0 ].attributes ) );
+		var morphAttributesUsed = new Set( Object.keys( geometries[ 0 ].morphAttributes ) );
+
+		var attributes = {};
+		var morphAttributes = {};
+
+		var morphTargetsRelative = geometries[ 0 ].morphTargetsRelative;
+
+		var mergedGeometry = new THREE.BufferGeometry();
+
+		var offset = 0;
+
+		for ( var i = 0; i < geometries.length; ++ i ) {
+
+			var geometry = geometries[ i ];
+			var attributesCount = 0;
+
+			// ensure that all geometries are indexed, or none
+
+			if ( isIndexed !== ( geometry.index !== null ) ) {
+
+				console.error( 'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' + i + '. All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them.' );
+				return null;
+
+			}
+
+			// gather attributes, exit early if they're different
+
+			for ( var name in geometry.attributes ) {
+
+				if ( ! attributesUsed.has( name ) ) {
+
+					console.error( 'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' + i + '. All geometries must have compatible attributes; make sure "' + name + '" attribute exists among all geometries, or in none of them.' );
+					return null;
+
+				}
+
+				if ( attributes[ name ] === undefined ) attributes[ name ] = [];
+
+				attributes[ name ].push( geometry.attributes[ name ] );
+
+				attributesCount ++;
+
+			}
+
+			// ensure geometries have the same number of attributes
+
+			if ( attributesCount !== attributesUsed.size ) {
+
+				console.error( 'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' + i + '. Make sure all geometries have the same number of attributes.' );
+				return null;
+
+			}
+
+			// gather morph attributes, exit early if they're different
+
+			if ( morphTargetsRelative !== geometry.morphTargetsRelative ) {
+
+				console.error( 'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' + i + '. .morphTargetsRelative must be consistent throughout all geometries.' );
+				return null;
+
+			}
+
+			for ( var name in geometry.morphAttributes ) {
+
+				if ( ! morphAttributesUsed.has( name ) ) {
+
+					console.error( 'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' + i + '.  .morphAttributes must be consistent throughout all geometries.' );
+					return null;
+
+				}
+
+				if ( morphAttributes[ name ] === undefined ) morphAttributes[ name ] = [];
+
+				morphAttributes[ name ].push( geometry.morphAttributes[ name ] );
+
+			}
+
+			// gather .userData
+
+			mergedGeometry.userData.mergedUserData = mergedGeometry.userData.mergedUserData || [];
+			mergedGeometry.userData.mergedUserData.push( geometry.userData );
+
+			if ( useGroups ) {
+
+				var count;
+
+				if ( isIndexed ) {
+
+					count = geometry.index.count;
+
+				} else if ( geometry.attributes.position !== undefined ) {
+
+					count = geometry.attributes.position.count;
+
+				} else {
+
+					console.error( 'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index ' + i + '. The geometry must have either an index or a position attribute' );
+					return null;
+
+				}
+
+				mergedGeometry.addGroup( offset, count, i );
+
+				offset += count;
+
+			}
+
+		}
+
+		// merge indices
+
+		if ( isIndexed ) {
+
+			var indexOffset = 0;
+			var mergedIndex = [];
+
+			for ( var i = 0; i < geometries.length; ++ i ) {
+
+				var index = geometries[ i ].index;
+
+				for ( var j = 0; j < index.count; ++ j ) {
+
+					mergedIndex.push( index.getX( j ) + indexOffset );
+
+				}
+
+				indexOffset += geometries[ i ].attributes.position.count;
+
+			}
+
+			mergedGeometry.setIndex( mergedIndex );
+
+		}
+
+		// merge attributes
+
+		for ( var name in attributes ) {
+
+			var mergedAttribute = this.mergeBufferAttributes( attributes[ name ] );
+
+			if ( ! mergedAttribute ) {
+
+				console.error( 'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the ' + name + ' attribute.' );
+				return null;
+
+			}
+
+			mergedGeometry.setAttribute( name, mergedAttribute );
+
+		}
+
+		// merge morph attributes
+
+		for ( var name in morphAttributes ) {
+
+			var numMorphTargets = morphAttributes[ name ][ 0 ].length;
+
+			if ( numMorphTargets === 0 ) break;
+
+			mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};
+			mergedGeometry.morphAttributes[ name ] = [];
+
+			for ( var i = 0; i < numMorphTargets; ++ i ) {
+
+				var morphAttributesToMerge = [];
+
+				for ( var j = 0; j < morphAttributes[ name ].length; ++ j ) {
+
+					morphAttributesToMerge.push( morphAttributes[ name ][ j ][ i ] );
+
+				}
+
+				var mergedMorphAttribute = this.mergeBufferAttributes( morphAttributesToMerge );
+
+				if ( ! mergedMorphAttribute ) {
+
+					console.error( 'THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the ' + name + ' morphAttribute.' );
+					return null;
+
+				}
+
+				mergedGeometry.morphAttributes[ name ].push( mergedMorphAttribute );
+
+			}
+
+		}
+
+		return mergedGeometry;
+
+	},
+
+	/**
+	 * @param {Array<THREE.BufferAttribute>} attributes
+	 * @return {THREE.BufferAttribute}
+	 */
+	mergeBufferAttributes: function ( attributes ) {
+
+		var TypedArray;
+		var itemSize;
+		var normalized;
+		var arrayLength = 0;
+
+		for ( var i = 0; i < attributes.length; ++ i ) {
+
+			var attribute = attributes[ i ];
+
+			if ( attribute.isInterleavedBufferAttribute ) {
+
+				console.error( 'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. InterleavedBufferAttributes are not supported.' );
+				return null;
+
+			}
+
+			if ( TypedArray === undefined ) TypedArray = attribute.array.constructor;
+			if ( TypedArray !== attribute.array.constructor ) {
+
+				console.error( 'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes.' );
+				return null;
+
+			}
+
+			if ( itemSize === undefined ) itemSize = attribute.itemSize;
+			if ( itemSize !== attribute.itemSize ) {
+
+				console.error( 'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes.' );
+				return null;
+
+			}
+
+			if ( normalized === undefined ) normalized = attribute.normalized;
+			if ( normalized !== attribute.normalized ) {
+
+				console.error( 'THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes.' );
+				return null;
+
+			}
+
+			arrayLength += attribute.array.length;
+
+		}
+
+		var array = new TypedArray( arrayLength );
+		var offset = 0;
+
+		for ( var i = 0; i < attributes.length; ++ i ) {
+
+			array.set( attributes[ i ].array, offset );
+
+			offset += attributes[ i ].array.length;
+
+		}
+
+		return new THREE.BufferAttribute( array, itemSize, normalized );
+
+	},
+
+	/**
+	 * @param {Array<THREE.BufferAttribute>} attributes
+	 * @return {Array<THREE.InterleavedBufferAttribute>}
+	 */
+	interleaveAttributes: function ( attributes ) {
+
+		// Interleaves the provided attributes into an InterleavedBuffer and returns
+		// a set of InterleavedBufferAttributes for each attribute
+		var TypedArray;
+		var arrayLength = 0;
+		var stride = 0;
+
+		// calculate the the length and type of the interleavedBuffer
+		for ( var i = 0, l = attributes.length; i < l; ++ i ) {
+
+			var attribute = attributes[ i ];
+
+			if ( TypedArray === undefined ) TypedArray = attribute.array.constructor;
+			if ( TypedArray !== attribute.array.constructor ) {
+
+				console.error( 'AttributeBuffers of different types cannot be interleaved' );
+				return null;
+
+			}
+
+			arrayLength += attribute.array.length;
+			stride += attribute.itemSize;
+
+		}
+
+		// Create the set of buffer attributes
+		var interleavedBuffer = new THREE.InterleavedBuffer( new TypedArray( arrayLength ), stride );
+		var offset = 0;
+		var res = [];
+		var getters = [ 'getX', 'getY', 'getZ', 'getW' ];
+		var setters = [ 'setX', 'setY', 'setZ', 'setW' ];
+
+		for ( var j = 0, l = attributes.length; j < l; j ++ ) {
+
+			var attribute = attributes[ j ];
+			var itemSize = attribute.itemSize;
+			var count = attribute.count;
+			var iba = new THREE.InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, attribute.normalized );
+			res.push( iba );
+
+			offset += itemSize;
+
+			// Move the data for each attribute into the new interleavedBuffer
+			// at the appropriate offset
+			for ( var c = 0; c < count; c ++ ) {
+
+				for ( var k = 0; k < itemSize; k ++ ) {
+
+					iba[ setters[ k ] ]( c, attribute[ getters[ k ] ]( c ) );
+
+				}
+
+			}
+
+		}
+
+		return res;
+
+	},
+
+	/**
+	 * @param {Array<THREE.BufferGeometry>} geometry
+	 * @return {number}
+	 */
+	estimateBytesUsed: function ( geometry ) {
+
+		// Return the estimated memory used by this geometry in bytes
+		// Calculate using itemSize, count, and BYTES_PER_ELEMENT to account
+		// for InterleavedBufferAttributes.
+		var mem = 0;
+		for ( var name in geometry.attributes ) {
+
+			var attr = geometry.getAttribute( name );
+			mem += attr.count * attr.itemSize * attr.array.BYTES_PER_ELEMENT;
+
+		}
+
+		var indices = geometry.getIndex();
+		mem += indices ? indices.count * indices.itemSize * indices.array.BYTES_PER_ELEMENT : 0;
+		return mem;
+
+	},
+
+	/**
+	 * @param {THREE.BufferGeometry} geometry
+	 * @param {number} tolerance
+	 * @return {THREE.BufferGeometry>}
+	 */
+	mergeVertices: function ( geometry, tolerance = 1e-4 ) {
+
+		tolerance = Math.max( tolerance, Number.EPSILON );
+
+		// Generate an index buffer if the geometry doesn't have one, or optimize it
+		// if it's already available.
+		var hashToIndex = {};
+		var indices = geometry.getIndex();
+		var positions = geometry.getAttribute( 'position' );
+		var vertexCount = indices ? indices.count : positions.count;
+
+		// next value for triangle indices
+		var nextIndex = 0;
+
+		// attributes and new attribute arrays
+		var attributeNames = Object.keys( geometry.attributes );
+		var attrArrays = {};
+		var morphAttrsArrays = {};
+		var newIndices = [];
+		var getters = [ 'getX', 'getY', 'getZ', 'getW' ];
+
+		// initialize the arrays
+		for ( var i = 0, l = attributeNames.length; i < l; i ++ ) {
+
+			var name = attributeNames[ i ];
+
+			attrArrays[ name ] = [];
+
+			var morphAttr = geometry.morphAttributes[ name ];
+			if ( morphAttr ) {
+
+				morphAttrsArrays[ name ] = new Array( morphAttr.length ).fill().map( () => [] );
+
+			}
+
+		}
+
+		// convert the error tolerance to an amount of decimal places to truncate to
+		var decimalShift = Math.log10( 1 / tolerance );
+		var shiftMultiplier = Math.pow( 10, decimalShift );
+		for ( var i = 0; i < vertexCount; i ++ ) {
+
+			var index = indices ? indices.getX( i ) : i;
+
+			// Generate a hash for the vertex attributes at the current index 'i'
+			var hash = '';
+			for ( var j = 0, l = attributeNames.length; j < l; j ++ ) {
+
+				var name = attributeNames[ j ];
+				var attribute = geometry.getAttribute( name );
+				var itemSize = attribute.itemSize;
+
+				for ( var k = 0; k < itemSize; k ++ ) {
+
+					// double tilde truncates the decimal value
+					hash += `${ ~ ~ ( attribute[ getters[ k ] ]( index ) * shiftMultiplier ) },`;
+
+				}
+
+			}
+
+			// Add another reference to the vertex if it's already
+			// used by another index
+			if ( hash in hashToIndex ) {
+
+				newIndices.push( hashToIndex[ hash ] );
+
+			} else {
+
+				// copy data to the new index in the attribute arrays
+				for ( var j = 0, l = attributeNames.length; j < l; j ++ ) {
+
+					var name = attributeNames[ j ];
+					var attribute = geometry.getAttribute( name );
+					var morphAttr = geometry.morphAttributes[ name ];
+					var itemSize = attribute.itemSize;
+					var newarray = attrArrays[ name ];
+					var newMorphArrays = morphAttrsArrays[ name ];
+
+					for ( var k = 0; k < itemSize; k ++ ) {
+
+						var getterFunc = getters[ k ];
+						newarray.push( attribute[ getterFunc ]( index ) );
+
+						if ( morphAttr ) {
+
+							for ( var m = 0, ml = morphAttr.length; m < ml; m ++ ) {
+
+								newMorphArrays[ m ].push( morphAttr[ m ][ getterFunc ]( index ) );
+
+							}
+
+						}
+
+					}
+
+				}
+
+				hashToIndex[ hash ] = nextIndex;
+				newIndices.push( nextIndex );
+				nextIndex ++;
+
+			}
+
+		}
+
+		// Generate typed arrays from new attribute arrays and update
+		// the attributeBuffers
+		const result = geometry.clone();
+		for ( var i = 0, l = attributeNames.length; i < l; i ++ ) {
+
+			var name = attributeNames[ i ];
+			var oldAttribute = geometry.getAttribute( name );
+
+			var buffer = new oldAttribute.array.constructor( attrArrays[ name ] );
+			var attribute = new THREE.BufferAttribute( buffer, oldAttribute.itemSize, oldAttribute.normalized );
+
+			result.setAttribute( name, attribute );
+
+			// Update the attribute arrays
+			if ( name in morphAttrsArrays ) {
+
+				for ( var j = 0; j < morphAttrsArrays[ name ].length; j ++ ) {
+
+					var oldMorphAttribute = geometry.morphAttributes[ name ][ j ];
+
+					var buffer = new oldMorphAttribute.array.constructor( morphAttrsArrays[ name ][ j ] );
+					var morphAttribute = new THREE.BufferAttribute( buffer, oldMorphAttribute.itemSize, oldMorphAttribute.normalized );
+					result.morphAttributes[ name ][ j ] = morphAttribute;
+
+				}
+
+			}
+
+		}
+
+		// indices
+
+		result.setIndex( newIndices );
+
+		return result;
+
+	},
+
+	/**
+	 * @param {THREE.BufferGeometry} geometry
+	 * @param {number} drawMode
+	 * @return {THREE.BufferGeometry>}
+	 */
+	toTrianglesDrawMode: function ( geometry, drawMode ) {
+
+		if ( drawMode === THREE.TrianglesDrawMode ) {
+
+			console.warn( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.' );
+			return geometry;
+
+		}
+
+		if ( drawMode === THREE.TriangleFanDrawMode || drawMode === THREE.TriangleStripDrawMode ) {
+
+			var index = geometry.getIndex();
+
+			// generate index if not present
+
+			if ( index === null ) {
+
+				var indices = [];
+
+				var position = geometry.getAttribute( 'position' );
+
+				if ( position !== undefined ) {
+
+					for ( var i = 0; i < position.count; i ++ ) {
+
+						indices.push( i );
+
+					}
+
+					geometry.setIndex( indices );
+					index = geometry.getIndex();
+
+				} else {
+
+					console.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );
+					return geometry;
+
+				}
+
+			}
+
+			//
+
+			var numberOfTriangles = index.count - 2;
+			var newIndices = [];
+
+			if ( drawMode === THREE.TriangleFanDrawMode ) {
+
+				// gl.TRIANGLE_FAN
+
+				for ( var i = 1; i <= numberOfTriangles; i ++ ) {
+
+					newIndices.push( index.getX( 0 ) );
+					newIndices.push( index.getX( i ) );
+					newIndices.push( index.getX( i + 1 ) );
+
+				}
+
+			} else {
+
+				// gl.TRIANGLE_STRIP
+
+				for ( var i = 0; i < numberOfTriangles; i ++ ) {
+
+					if ( i % 2 === 0 ) {
+
+						newIndices.push( index.getX( i ) );
+						newIndices.push( index.getX( i + 1 ) );
+						newIndices.push( index.getX( i + 2 ) );
+
+
+					} else {
+
+						newIndices.push( index.getX( i + 2 ) );
+						newIndices.push( index.getX( i + 1 ) );
+						newIndices.push( index.getX( i ) );
+
+					}
+
+				}
+
+			}
+
+			if ( ( newIndices.length / 3 ) !== numberOfTriangles ) {
+
+				console.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );
+
+			}
+
+			// build final geometry
+
+			var newGeometry = geometry.clone();
+			newGeometry.setIndex( newIndices );
+			newGeometry.clearGroups();
+
+			return newGeometry;
+
+		} else {
+
+			console.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:', drawMode );
+			return geometry;
+
+		}
+
+	}
+
+};

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 215 - 114
public/vwf/model/aframe/aframe-master.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
public/vwf/model/aframe/aframe-master.js.map


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
public/vwf/model/aframe/aframe-master.min.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
public/vwf/model/aframe/aframe-master.min.js.map


+ 66 - 29
public/vwf/model/aframe/extras/aframe-extras.controls.js

@@ -898,6 +898,11 @@ var GamepadButton = require('../../lib/GamepadButton'),
 
 var JOYSTICK_EPS = 0.2;
 
+var Joystick = {
+  MOVEMENT: 1,
+  ROTATION: 2
+};
+
 module.exports = AFRAME.registerComponent('gamepad-controls', {
 
   /*******************************************************************
@@ -935,7 +940,10 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
    * Called once when component is attached. Generally for initial setup.
    */
   init: function init() {
-    var scene = this.el.sceneEl;
+    var sceneEl = this.el.sceneEl;
+
+    this.system = sceneEl.systems['tracked-controls-webxr'] || { controllers: [] };
+
     this.prevTime = window.performance.now();
 
     // Button state
@@ -950,7 +958,11 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
     this.yaw.rotation.y = THREE.Math.degToRad(rotation.y);
     this.yaw.add(this.pitch);
 
-    scene.addBehavior(this);
+    this._lookVector = new THREE.Vector2();
+    this._moveVector = new THREE.Vector2();
+    this._dpadVector = new THREE.Vector2();
+
+    sceneEl.addBehavior(this);
   },
 
   /**
@@ -982,20 +994,28 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
   isVelocityActive: function isVelocityActive() {
     if (!this.data.enabled || !this.isConnected()) return false;
 
-    var dpad = this.getDpad(),
-        joystick0 = this.getJoystick(0),
-        inputX = dpad.x || joystick0.x,
-        inputY = dpad.y || joystick0.y;
+    var dpad = this._dpadVector;
+    var joystick = this._moveVector;
+
+    this.getDpad(dpad);
+    this.getJoystick(Joystick.MOVEMENT, joystick);
+
+    var inputX = dpad.x || joystick.x;
+    var inputY = dpad.y || joystick.y;
 
     return Math.abs(inputX) > JOYSTICK_EPS || Math.abs(inputY) > JOYSTICK_EPS;
   },
 
   getVelocityDelta: function getVelocityDelta() {
-    var dpad = this.getDpad(),
-        joystick0 = this.getJoystick(0),
-        inputX = dpad.x || joystick0.x,
-        inputY = dpad.y || joystick0.y,
-        dVelocity = new THREE.Vector3();
+    var dpad = this._dpadVector;
+    var joystick = this._moveVector;
+
+    this.getDpad(dpad);
+    this.getJoystick(Joystick.MOVEMENT, joystick);
+
+    var inputX = dpad.x || joystick.x;
+    var inputY = dpad.y || joystick.y;
+    var dVelocity = new THREE.Vector3();
 
     if (Math.abs(inputX) > JOYSTICK_EPS) {
       dVelocity.x += inputX;
@@ -1014,9 +1034,11 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
   isRotationActive: function isRotationActive() {
     if (!this.data.enabled || !this.isConnected()) return false;
 
-    var joystick1 = this.getJoystick(1);
+    var joystick = this._lookVector;
 
-    return Math.abs(joystick1.x) > JOYSTICK_EPS || Math.abs(joystick1.y) > JOYSTICK_EPS;
+    this.getJoystick(Joystick.ROTATION, joystick);
+
+    return Math.abs(joystick.x) > JOYSTICK_EPS || Math.abs(joystick.y) > JOYSTICK_EPS;
   },
 
   updateRotation: function updateRotation(dt) {
@@ -1034,7 +1056,9 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
       yaw.rotation.copy(lookControls.yawObject.rotation);
     }
 
-    var lookVector = this.getJoystick(1);
+    var lookVector = this._lookVector;
+
+    this.getJoystick(Joystick.ROTATION, lookVector);
 
     if (Math.abs(lookVector.x) <= JOYSTICK_EPS) lookVector.x = 0;
     if (Math.abs(lookVector.y) <= JOYSTICK_EPS) lookVector.y = 0;
@@ -1095,10 +1119,12 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
    * @return {Gamepad}
    */
   getGamepad: function getGamepad() {
-    var localGamepad = navigator.getGamepads && navigator.getGamepads()[this.data.controller],
+    var stdGamepad = navigator.getGamepads && navigator.getGamepads()[this.data.controller],
+        xrController = this.system.controllers[this.data.controller],
+        xrGamepad = xrController && xrController.gamepad,
         proxyControls = this.el.sceneEl.components['proxy-controls'],
         proxyGamepad = proxyControls && proxyControls.isConnected() && proxyControls.getGamepad(this.data.controller);
-    return proxyGamepad || localGamepad;
+    return proxyGamepad || xrGamepad || stdGamepad;
   },
 
   /**
@@ -1121,32 +1147,43 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
   },
 
   /**
-   * Returns the state of the given joystick (0 or 1) as a THREE.Vector2.
-   * @param  {number} id The joystick (0, 1) for which to find state.
+   * Returns the state of the specified joystick as a THREE.Vector2.
+   * @param  {Joystick} role
+   * @param  {THREE.Vector2} target
    * @return {THREE.Vector2}
    */
-  getJoystick: function getJoystick(index) {
+  getJoystick: function getJoystick(index, target) {
     var gamepad = this.getGamepad();
-    switch (index) {
-      case 0:
-        return new THREE.Vector2(gamepad.axes[0], gamepad.axes[1]);
-      case 1:
-        return new THREE.Vector2(gamepad.axes[2], gamepad.axes[3]);
-      default:
-        throw new Error('Unexpected joystick index "%d".', index);
+    if (gamepad.mapping === 'xr-standard') {
+      // See: https://github.com/donmccurdy/aframe-extras/issues/307
+      switch (index) {
+        case Joystick.MOVEMENT:
+          return target.set(gamepad.axes[2], gamepad.axes[3]);
+        case Joystick.ROTATION:
+          return target.set(gamepad.axes[0], gamepad.axes[1]);
+      }
+    } else {
+      switch (index) {
+        case Joystick.MOVEMENT:
+          return target.set(gamepad.axes[0], gamepad.axes[1]);
+        case Joystick.ROTATION:
+          return target.set(gamepad.axes[2], gamepad.axes[3]);
+      }
     }
+    throw new Error('Unexpected joystick index "%d".', index);
   },
 
   /**
    * Returns the state of the dpad as a THREE.Vector2.
+   * @param {THREE.Vector2} target
    * @return {THREE.Vector2}
    */
-  getDpad: function getDpad() {
+  getDpad: function getDpad(target) {
     var gamepad = this.getGamepad();
     if (!gamepad.buttons[GamepadButton.DPAD_RIGHT]) {
-      return new THREE.Vector2();
+      return target.set(0, 0);
     }
-    return new THREE.Vector2((gamepad.buttons[GamepadButton.DPAD_RIGHT].pressed ? 1 : 0) + (gamepad.buttons[GamepadButton.DPAD_LEFT].pressed ? -1 : 0), (gamepad.buttons[GamepadButton.DPAD_UP].pressed ? -1 : 0) + (gamepad.buttons[GamepadButton.DPAD_DOWN].pressed ? 1 : 0));
+    return target.set((gamepad.buttons[GamepadButton.DPAD_RIGHT].pressed ? 1 : 0) + (gamepad.buttons[GamepadButton.DPAD_LEFT].pressed ? -1 : 0), (gamepad.buttons[GamepadButton.DPAD_UP].pressed ? -1 : 0) + (gamepad.buttons[GamepadButton.DPAD_DOWN].pressed ? 1 : 0));
   },
 
   /**

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
public/vwf/model/aframe/extras/aframe-extras.controls.min.js


+ 66 - 29
public/vwf/model/aframe/extras/aframe-extras.js

@@ -8838,6 +8838,11 @@ var GamepadButton = require('../../lib/GamepadButton'),
 
 var JOYSTICK_EPS = 0.2;
 
+var Joystick = {
+  MOVEMENT: 1,
+  ROTATION: 2
+};
+
 module.exports = AFRAME.registerComponent('gamepad-controls', {
 
   /*******************************************************************
@@ -8875,7 +8880,10 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
    * Called once when component is attached. Generally for initial setup.
    */
   init: function init() {
-    var scene = this.el.sceneEl;
+    var sceneEl = this.el.sceneEl;
+
+    this.system = sceneEl.systems['tracked-controls-webxr'] || { controllers: [] };
+
     this.prevTime = window.performance.now();
 
     // Button state
@@ -8890,7 +8898,11 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
     this.yaw.rotation.y = THREE.Math.degToRad(rotation.y);
     this.yaw.add(this.pitch);
 
-    scene.addBehavior(this);
+    this._lookVector = new THREE.Vector2();
+    this._moveVector = new THREE.Vector2();
+    this._dpadVector = new THREE.Vector2();
+
+    sceneEl.addBehavior(this);
   },
 
   /**
@@ -8922,20 +8934,28 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
   isVelocityActive: function isVelocityActive() {
     if (!this.data.enabled || !this.isConnected()) return false;
 
-    var dpad = this.getDpad(),
-        joystick0 = this.getJoystick(0),
-        inputX = dpad.x || joystick0.x,
-        inputY = dpad.y || joystick0.y;
+    var dpad = this._dpadVector;
+    var joystick = this._moveVector;
+
+    this.getDpad(dpad);
+    this.getJoystick(Joystick.MOVEMENT, joystick);
+
+    var inputX = dpad.x || joystick.x;
+    var inputY = dpad.y || joystick.y;
 
     return Math.abs(inputX) > JOYSTICK_EPS || Math.abs(inputY) > JOYSTICK_EPS;
   },
 
   getVelocityDelta: function getVelocityDelta() {
-    var dpad = this.getDpad(),
-        joystick0 = this.getJoystick(0),
-        inputX = dpad.x || joystick0.x,
-        inputY = dpad.y || joystick0.y,
-        dVelocity = new THREE.Vector3();
+    var dpad = this._dpadVector;
+    var joystick = this._moveVector;
+
+    this.getDpad(dpad);
+    this.getJoystick(Joystick.MOVEMENT, joystick);
+
+    var inputX = dpad.x || joystick.x;
+    var inputY = dpad.y || joystick.y;
+    var dVelocity = new THREE.Vector3();
 
     if (Math.abs(inputX) > JOYSTICK_EPS) {
       dVelocity.x += inputX;
@@ -8954,9 +8974,11 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
   isRotationActive: function isRotationActive() {
     if (!this.data.enabled || !this.isConnected()) return false;
 
-    var joystick1 = this.getJoystick(1);
+    var joystick = this._lookVector;
 
-    return Math.abs(joystick1.x) > JOYSTICK_EPS || Math.abs(joystick1.y) > JOYSTICK_EPS;
+    this.getJoystick(Joystick.ROTATION, joystick);
+
+    return Math.abs(joystick.x) > JOYSTICK_EPS || Math.abs(joystick.y) > JOYSTICK_EPS;
   },
 
   updateRotation: function updateRotation(dt) {
@@ -8974,7 +8996,9 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
       yaw.rotation.copy(lookControls.yawObject.rotation);
     }
 
-    var lookVector = this.getJoystick(1);
+    var lookVector = this._lookVector;
+
+    this.getJoystick(Joystick.ROTATION, lookVector);
 
     if (Math.abs(lookVector.x) <= JOYSTICK_EPS) lookVector.x = 0;
     if (Math.abs(lookVector.y) <= JOYSTICK_EPS) lookVector.y = 0;
@@ -9035,10 +9059,12 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
    * @return {Gamepad}
    */
   getGamepad: function getGamepad() {
-    var localGamepad = navigator.getGamepads && navigator.getGamepads()[this.data.controller],
+    var stdGamepad = navigator.getGamepads && navigator.getGamepads()[this.data.controller],
+        xrController = this.system.controllers[this.data.controller],
+        xrGamepad = xrController && xrController.gamepad,
         proxyControls = this.el.sceneEl.components['proxy-controls'],
         proxyGamepad = proxyControls && proxyControls.isConnected() && proxyControls.getGamepad(this.data.controller);
-    return proxyGamepad || localGamepad;
+    return proxyGamepad || xrGamepad || stdGamepad;
   },
 
   /**
@@ -9061,32 +9087,43 @@ module.exports = AFRAME.registerComponent('gamepad-controls', {
   },
 
   /**
-   * Returns the state of the given joystick (0 or 1) as a THREE.Vector2.
-   * @param  {number} id The joystick (0, 1) for which to find state.
+   * Returns the state of the specified joystick as a THREE.Vector2.
+   * @param  {Joystick} role
+   * @param  {THREE.Vector2} target
    * @return {THREE.Vector2}
    */
-  getJoystick: function getJoystick(index) {
+  getJoystick: function getJoystick(index, target) {
     var gamepad = this.getGamepad();
-    switch (index) {
-      case 0:
-        return new THREE.Vector2(gamepad.axes[0], gamepad.axes[1]);
-      case 1:
-        return new THREE.Vector2(gamepad.axes[2], gamepad.axes[3]);
-      default:
-        throw new Error('Unexpected joystick index "%d".', index);
+    if (gamepad.mapping === 'xr-standard') {
+      // See: https://github.com/donmccurdy/aframe-extras/issues/307
+      switch (index) {
+        case Joystick.MOVEMENT:
+          return target.set(gamepad.axes[2], gamepad.axes[3]);
+        case Joystick.ROTATION:
+          return target.set(gamepad.axes[0], gamepad.axes[1]);
+      }
+    } else {
+      switch (index) {
+        case Joystick.MOVEMENT:
+          return target.set(gamepad.axes[0], gamepad.axes[1]);
+        case Joystick.ROTATION:
+          return target.set(gamepad.axes[2], gamepad.axes[3]);
+      }
     }
+    throw new Error('Unexpected joystick index "%d".', index);
   },
 
   /**
    * Returns the state of the dpad as a THREE.Vector2.
+   * @param {THREE.Vector2} target
    * @return {THREE.Vector2}
    */
-  getDpad: function getDpad() {
+  getDpad: function getDpad(target) {
     var gamepad = this.getGamepad();
     if (!gamepad.buttons[GamepadButton.DPAD_RIGHT]) {
-      return new THREE.Vector2();
+      return target.set(0, 0);
     }
-    return new THREE.Vector2((gamepad.buttons[GamepadButton.DPAD_RIGHT].pressed ? 1 : 0) + (gamepad.buttons[GamepadButton.DPAD_LEFT].pressed ? -1 : 0), (gamepad.buttons[GamepadButton.DPAD_UP].pressed ? -1 : 0) + (gamepad.buttons[GamepadButton.DPAD_DOWN].pressed ? 1 : 0));
+    return target.set((gamepad.buttons[GamepadButton.DPAD_RIGHT].pressed ? 1 : 0) + (gamepad.buttons[GamepadButton.DPAD_LEFT].pressed ? -1 : 0), (gamepad.buttons[GamepadButton.DPAD_UP].pressed ? -1 : 0) + (gamepad.buttons[GamepadButton.DPAD_DOWN].pressed ? 1 : 0));
   },
 
   /**

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
public/vwf/model/aframe/extras/aframe-extras.min.js


+ 194 - 112
public/vwf/view/aframe.js

@@ -50,9 +50,23 @@ define(["module", "vwf/view"], function (module, view) {
                 this.rootSelector = options;
             }
 
-            this.gearvr = options.gearvr !== undefined ? options.gearvr : false;
-            this.wmrright = options.wmrright !== undefined ? options.wmrright : false;
-            this.wmrleft = options.wmrleft !== undefined ? options.wmrleft : false;
+            // this.gearvr = options.gearvr !== undefined ? options.gearvr : false;
+            // this.wmrright = options.wmrright !== undefined ? options.wmrright : false;
+            // this.wmrleft = options.wmrleft !== undefined ? options.wmrleft : false;
+
+            this.xrType = undefined;
+
+            //TODO: FIX detection in better way! (now works for Oculus Browser only)
+
+            this.hmd = false; 
+            this.threeDoF = false;
+            this.sixDoF = false;
+
+            this.threeDoFMobile = AFRAME.utils.device.isMobileVR() && AFRAME.utils.device.checkHeadsetConnected() && !navigator.userAgent.includes('Quest');
+            this.sixDoFMobile = AFRAME.utils.device.checkHeadsetConnected() && navigator.userAgent.includes('Quest');
+            this.sixDoFDesktop = !AFRAME.utils.device.isMobile && !AFRAME.utils.device.isMobileVR() && AFRAME.utils.device.checkHeadsetConnected();
+
+
         },
 
         createdNode: function (nodeID, childID, childExtendsID, childImplementsIDs,
@@ -68,58 +82,52 @@ define(["module", "vwf/view"], function (module, view) {
 
             if (this.state.scenes[childID]) {
                 let scene = this.state.scenes[childID];
-
+                //TODO: FIX
+                
 
                 let prepairAvatar = new Promise((resolve, reject) => {
-
-                    function cb() {
-                        resolve("ok");
-                    }
-                    createAvatarControl(scene, cb);
+                    document.body.appendChild(scene);
+                    let createAvatarPromise = new Promise(r=> r(createAvatarControl(scene)));
+                    return resolve(createAvatarPromise) 
                 });
 
-
                 prepairAvatar.then(res => {
-                    // console.log(res);
-                    createAvatar.call(self, childID);                  
-                    postLoadAction.call(self, childID);
-
-                    if (this.gearvr == true) {
                         console.log("CREATE GEARVR HERE!!");
-                        if (AFRAME.utils.device.isMobileVR()) {
+                        if (self.threeDoFMobile || _app.config.d3DoF ) {
+                            this.xrType = 'mobileVR';
                             let nodeName = 'gearvr-' + self.kernel.moniker();
                             createGearVRControls();
                             createGearVRController.call(self, childID, nodeName);
                         }
-                    }
-
-
-                    if (this.wmrright == true) {
-                        console.log("CREATE WMR RIGHT HERE!!");
-                        if (!AFRAME.utils.device.isMobileVR()) {
-                            if (AFRAME.utils.device.checkHeadsetConnected()) {
-                                let nodeName = 'wmrvr-right-' + self.kernel.moniker();
-                                createWMRVRControls('right');
-                                createWMRVR.call(this, childID, nodeName);
+                    
+                        console.log("CREATE XRController RIGHT HERE!!");
+                       // if (!AFRAME.utils.device.isMobileVR()) {
+                            if (self.sixDoFMobile || self.sixDoFDesktop || _app.config.d6DoF  ) {
+
+                                let nodeRight = 'xrcontroller-right-' + self.kernel.moniker();
+                                createXRControls('right');
+                                createXR.call(this, childID, nodeRight);
+
+                                console.log("CREATE XRController LEFT HERE!!");
+                       // if (!AFRAME.utils.device.isMobileVR()) {
+  
+                                let nodeLeft = 'xrcontroller-left-' + self.kernel.moniker();
+                                createXRControls('left');
+                                createXR.call(this, childID, nodeLeft);
                             }
-                        }
-                    }
+                       // }
+                    
 
-                    if (this.wmrleft == true) {
-                        console.log("CREATE WMR LEFT HERE!!");
-                        if (!AFRAME.utils.device.isMobileVR()) {
-                            if (AFRAME.utils.device.checkHeadsetConnected()) {
-                                let nodeName = 'wmrvr-left-' + self.kernel.moniker();
-                                createWMRVRControls('left');
-                                createWMRVR.call(this, childID, nodeName);
-                            }
-                        }
-                    }
+                     // console.log(res);
+                     createAvatar.call(self, childID);                  
+                     postLoadAction.call(self, childID);
 
+                }).then(res=>{
+                    //document.body.appendChild(scene);
                 })
                 // this.state.appInitialized  = true;
 
-                document.body.appendChild(scene); //append is not working in Edge browser
+                //document.body.appendChild(scene); //append is not working in Edge browser
 
             }
 
@@ -178,6 +186,12 @@ define(["module", "vwf/view"], function (module, view) {
             }
 
 
+            // if (node.extendsID == "http://vwf.example.com/aframe/atext.vwf") {
+            //     console.log("Text component initialized");
+            //     node.aframeObj.play();
+
+            // }
+
             // if (node.prototypes.includes("http://vwf.example.com/aframe/aentity.vwf")) {
 
             //     var clientThatSatProperty = self.kernel.client();
@@ -260,26 +274,6 @@ define(["module", "vwf/view"], function (module, view) {
                 receiveModelTransformChanges(nodeId, 'scale', propertyValue);
             }
 
-            // if (node.aframeObj.nodeName == "AUDIO" && propertyName == 'itemSrc') {
-
-            //     //console.log("sat new item");
-            //     let elID = '#' + node.aframeObj.getAttribute('id');
-            //     Object.entries(this.state.nodes).forEach(el => {
-            //         let src = el[1].aframeObj.getAttribute('src');
-            //         if (src){
-            //            // console.log("my: " + src);
-            //             if (src == elID)
-            //             self.kernel.callMethod(el[0], "updateSrc", [elID])
-            //         }
-            //     })
-
-            // }
-
-            // if ( propertyName == "position" ) {
-            //     receiveModelTransformChanges( nodeId, propertyValue );
-            // }
-
-
             if (node.aframeObj.nodeName == "AUDIO" && propertyName == 'itemSrc') {
 
                 //console.log("sat new item");
@@ -475,16 +469,22 @@ define(["module", "vwf/view"], function (module, view) {
             updateAvatarPosition();
 
             //update vr controllers
-            if (this.gearvr == true) {
-                updateHandControllerVR('gearvr-', '#gearvrcontrol');
-            }
-            if (this.wmrright == true) {
-                updateHandControllerVR('wmrvr-right-', '#wmrvrcontrolright');
-            }
-            if (this.wmrleft == true) {
-                updateHandControllerVR('wmrvr-left-', '#wmrvrcontrolleft');
+
+            if(self.hmd){
+                if(self.threeDoF )
+                        updateHandControllerVR('gearvr-', '#gearvrcontrol');
+
+                if(this.sixDoF ) {
+                        updateHandControllerVR('xrcontroller-right-', '#xrcontrollerright');
+                        updateHandControllerVR('xrcontroller-left-', '#xrcontrollerleft');
+                }
             }
 
+            
+    
+                
+            
+
             //lerpTick ();
         },
 
@@ -643,7 +643,7 @@ define(["module", "vwf/view"], function (module, view) {
 
     function updateAvatarPosition() {
 
-        let delta = 0.0001;
+        let delta = 0.001;
 
         let avatarName = 'avatar-' + self.kernel.moniker();
         var node = self.state.nodes[avatarName];
@@ -654,25 +654,51 @@ define(["module", "vwf/view"], function (module, view) {
         if (el) {
             //let position = el.object3D.getWorldPosition(); //el.getAttribute('position');
 
+            //var position;
+            // if((self.hmd && self.sixDoF) || _app.config.d6DoF){
+            //     position = el.getAttribute('position');
+            // } else {
+            //     position = new THREE.Vector3();
+            //     el.object3D.getWorldPosition(position);
+            // }
+            //let position = el.getAttribute('position');
+
+            //let position = el.getAttribute('position');
+            //let position = el.object3D.position.clone();
             let position = new THREE.Vector3();
-            el.object3D.getWorldPosition(position);
+            el.object3D.localToWorld(position);
 
             let rotation = el.getAttribute('rotation'); //getWorldRotation(el, 'YXZ');
 
             let lastRotation = self.nodes[avatarName].selfTickRotation;
-            let lastPosition = self.nodes[avatarName].selfTickPosition;
+            let lastPosition = self.nodes[avatarName].selfTickPosition ? self.nodes[avatarName].selfTickPosition: new THREE.Vector3(0, 0, 0);
 
             // let currentPosition = node.aframeObj.getAttribute('position');
             // let currentRotation = node.aframeObj.getAttribute('rotation');
 
-            if (position && rotation && lastPosition && lastRotation) {
-                if (compareCoordinates(position, lastPosition, delta) || Math.abs(rotation.y - lastRotation.y) > delta) {
-                    console.log("not equal!!")
-                    self.kernel.callMethod(avatarName, "followAvatarControl", [position, rotation]);
+            
+            // compareCoordinates(position, lastPosition, delta) 
+
+            if(position && lastPosition ) {
+                let distance = lastPosition.distanceTo(position);
+
+                if (distance > delta)
+                {
+                    console.log("position not equal");
+                    self.kernel.setProperty(avatarName, "position", position);
+                }
+            }
+
+            if (rotation && lastRotation) {
+                let distance = Math.abs(rotation.y - lastRotation.y);
+                if ( distance > delta) {
+                    console.log("rotation not equal")
+                    self.kernel.callMethod(avatarName, "updateAvatarRotation", [rotation]);
                 }
             }
             self.nodes[avatarName].selfTickRotation = Object.assign({}, rotation);
-            self.nodes[avatarName].selfTickPosition = Object.assign({}, position);
+            //self.nodes[avatarName].selfTickPosition = Object.assign({}, position);
+            self.nodes[avatarName].selfTickPosition = position.clone();
         }
 
     }
@@ -681,7 +707,7 @@ define(["module", "vwf/view"], function (module, view) {
     function updateHandControllerVR(aName, aSelector) {
         //let avatarName = 'avatar-' + self.kernel.moniker();
 
-        let delta = 0.0001
+        let delta = 0.001
 
         let avatarName = aName + self.kernel.moniker();
         var node = self.state.nodes[avatarName];
@@ -692,30 +718,57 @@ define(["module", "vwf/view"], function (module, view) {
         if (el) {
             //let position = el.object3D.getWorldPosition() //el.getAttribute('position');
 
-            let position = new THREE.Vector3();
-            el.object3D.getWorldPosition(position);
+            // let position = new THREE.Vector3();
+            // el.object3D.getWorldPosition(position);
+            // let rotation = getWorldRotation(el, 'XYZ');
 
-            let rotation = getWorldRotation(el, 'XYZ');
+            // let position = el.getAttribute('position');
+            // let rotation = el.getAttribute('rotation');
 
-            //let rotation = el.getAttribute('rotation');
+           // let position = el.object3D.position;
+           let position = new THREE.Vector3();
+           el.object3D.localToWorld(position);
+            let rotation = el.getAttribute('rotation'); //getWorldRotation(el, 'YXZ');
 
             let lastRotation = self.nodes[avatarName].selfTickRotation;
-            let lastPosition = self.nodes[avatarName].selfTickPosition;
+            let lastPosition = self.nodes[avatarName].selfTickPosition ? self.nodes[avatarName].selfTickPosition: new THREE.Vector3(0, 0, 0);
 
             // let currentPosition = node.aframeObj.getAttribute('position');
             //let currentRotation = node.aframeObj.getAttribute('rotation');
 
-            if (position && rotation && lastRotation && lastPosition) {
-                if (compareCoordinates(position, lastPosition, delta) || compareCoordinates(rotation, lastRotation, delta)) {
-                    console.log("not equal!!");
-                    vwf_view.kernel.callMethod(avatarName, "updateVRControl", [position, rotation]);
+            if (position && lastPosition) {
+                let distance = lastPosition.distanceTo(position);
+
+                if (distance > delta)
+                {
+                    console.log("position not equal");
+                    self.kernel.setProperty(avatarName, "position", position);
+                    self.kernel.callMethod(avatarName, "moveVRController",[]);
                 }
             }
 
+            if (rotation && lastRotation) {
+                let distance = compareCoordinates(rotation, lastRotation, delta)
+
+                if (distance)
+                {
+                    console.log("rotation not equal");
+                    self.kernel.setProperty(avatarName, "rotation", rotation);
+                    self.kernel.callMethod(avatarName, "moveVRController",[]);
+                }
+            }
+
+            // if (position && rotation && lastRotation && lastPosition) {
+            //     if (compareCoordinates(position, lastPosition, delta) || compareCoordinates(rotation, lastRotation, delta)) {
+            //         console.log("not equal!!");
+            //         vwf_view.kernel.callMethod(avatarName, "updateVRControl", [position, rotation]);
+            //     }
+            // }
+
 
             //vwf_view.kernel.callMethod(avatarName, "updateVRControl", [position, rotation]);
 
-            self.nodes[avatarName].selfTickPosition = Object.assign({}, position);
+            self.nodes[avatarName].selfTickPosition = position.clone();
             self.nodes[avatarName].selfTickRotation = Object.assign({}, rotation);
 
         }
@@ -749,7 +802,7 @@ define(["module", "vwf/view"], function (module, view) {
         //console.log(axes);
         let el = document.querySelector('#avatarControl');
         let position = new THREE.Vector3();
-        el.object3D.getWorldPosition(position);
+        el.object3D.localToWorld(position);//getWorldPosition(position);
         let vel = new THREE.Vector3(axes[0], 0, -axes[1]);
         el.object3D.position.add(getMovementVector(el,vel));
     }
@@ -772,7 +825,7 @@ define(["module", "vwf/view"], function (module, view) {
         //el.object3D.rotation.set(val+rotation.x, rotation.y, rotation.z)
     }
 
-    function createAvatarControl(aScene, cb) {
+    async function createAvatarControl(aScene) {
 
         let avatarName = 'avatar-' + self.kernel.moniker();
 
@@ -780,8 +833,10 @@ define(["module", "vwf/view"], function (module, view) {
         avatarEl.setAttribute('id', 'avatarControlParent');
 
 
-        if (AFRAME.utils.device.isMobileVR()) {
+        if (self.d3DoF || _app.config.d3DoF) {
+            //avatarEl.setAttribute('gearvr-controls', {}); 
             avatarEl.setAttribute('movement-controls', {});//{'controls': 'gamepad'});
+           // avatarEl.setAttribute("gamepad-controls", {});
             //avatarEl.setAttribute('position', '0 0 0');
         }
 
@@ -791,11 +846,15 @@ define(["module", "vwf/view"], function (module, view) {
 
         controlEl.setAttribute('id', 'avatarControl');
         controlEl.setAttribute('wasd-controls', {acceleration:20});
-        controlEl.setAttribute('look-controls', { pointerLockEnabled: false });
+        controlEl.setAttribute('look-controls', { pointerLockEnabled: false});
+        controlEl.setAttribute('look-controls', 'enabled', true );
+
         //controlEl.setAttribute('gamepad-controls', {'controller': 0});
 
         if (AFRAME.utils.device.isMobile()) {
             //self.state.showMobileJoystick()
+
+            controlEl.setAttribute('look-controls', 'enabled', true );
             controlEl.setAttribute("virtual-gamepad-controls", {});
             controlEl.addEventListener("move", setJoystickMoveInput);
         }
@@ -817,13 +876,14 @@ define(["module", "vwf/view"], function (module, view) {
         cursorEl.setAttribute('raycaster', 'objects', '.clickable');
         cursorEl.setAttribute('raycaster', 'showLine', false);
 
-        if (AFRAME.utils.device.isMobileVR()) { }
-
         // cursorEl.setAttribute('raycaster', {objects: '.intersectable', showLine: true, far: 100});
         // cursorEl.setAttribute('raycaster', 'showLine', true);
         controlEl.appendChild(cursorEl);
 
         avatarEl.appendChild(controlEl);
+
+        //avatarEl.setAttribute('avatar', {});
+
         aScene.appendChild(avatarEl);
 
         controlEl.setAttribute('camera', 'active', true);
@@ -840,8 +900,8 @@ define(["module", "vwf/view"], function (module, view) {
         // aScene.appendChild(arControl);
 
 
-
-        cb();
+        return "OK!"
+       // cb();
 
         // let gearVRControlsEl = document.createElement('a-entity');
         // gearVRControlsEl.setAttribute('id', 'gearvr-'+avatarName);
@@ -865,12 +925,12 @@ define(["module", "vwf/view"], function (module, view) {
 
     }
 
-    function createWMRVR(nodeID, nodeName) {
+    function createXR(nodeID, nodeName) {
 
         var newNode = {
             "id": nodeName,
             "uri": nodeName,
-            "extends": "http://vwf.example.com/aframe/wmrvrcontroller.vwf",
+            "extends": "http://vwf.example.com/aframe/xrcontroller.vwf",
             "properties": {
             }
         }
@@ -1025,35 +1085,57 @@ define(["module", "vwf/view"], function (module, view) {
 
     function createGearVRControls() {
 
-        let sceneEl = document.querySelector('a-scene');
-
         let avatarControl = document.querySelector('#avatarControlParent');
 
-        let gearvr = document.createElement('a-entity');
-        gearvr.setAttribute('id', 'gearvrcontrol');
-        gearvr.setAttribute('gearvr-controls', {
+        let el = document.createElement('a-entity');
+        el.setAttribute('id', 'gearvrcontrol');
+
+        el.setAttribute('gearvr-controls', {
             'hand': 'right',
             'model': true
         });
+    
         // gearvr.setAttribute('gearvr-controls', 'hand', 'right');
 
-        gearvr.setAttribute('gearvrcontrol', {});
-        avatarControl.appendChild(gearvr);
+        el.setAttribute('teleport-controls', { 
+            cameraRig: '#avatarControlParent',
+            teleportOrigin: '#avatarControl',
+            startEvents: 'teleportstart',
+            endEvents: 'teleportend'
+        });
+
+        el.setAttribute('gearvrcontrol', {});
+        avatarControl.appendChild(el);
 
     }
 
-    function createWMRVRControls(hand) {
-
-        let sceneEl = document.querySelector('a-scene');
+    function createXRControls(hand) {
 
         let avatarControl = document.querySelector('#avatarControlParent');
 
-        let wmrvr = document.createElement('a-entity');
-        wmrvr.setAttribute('id', 'wmrvrcontrol' + hand);
-        wmrvr.setAttribute('windows-motion-controls', '');
-        wmrvr.setAttribute('windows-motion-controls', 'hand', hand);
-        wmrvr.setAttribute('wmrvrcontrol', { 'hand': hand });
-        avatarControl.appendChild(wmrvr);
+        let el = document.createElement('a-entity');
+        el.setAttribute('id', 'xrcontroller' + hand);
+
+        el.setAttribute('hand-controls', {
+            'hand': hand,
+            'handModelStyle': 'lowPoly',
+            'color': '#ffcccc'
+        });
+
+        // wmrvr.setAttribute('windows-motion-controls', '');
+        // wmrvr.setAttribute('windows-motion-controls', 'hand', hand);
+
+        el.setAttribute('xrcontroller', { 'hand': hand });
+
+        //add teleport controls
+        el.setAttribute('teleport-controls', { 
+            cameraRig: '#avatarControlParent',
+            teleportOrigin: '#avatarControl',
+            startEvents: 'teleportstart',
+            endEvents: 'teleportend'
+        });
+
+        avatarControl.appendChild(el);
     }
 
 

+ 10 - 0
public/vwf/view/editor-new.js

@@ -621,6 +621,7 @@ define([
                                             "label": "Reset Avatar",
                                             "onclick": function (e) {
                                                 let avatarID = 'avatar-' + self.kernel.moniker();
+                                                //TODO: add XR check
                                                 vwf_view.kernel.callMethod(avatarID, "resetAvatar", []);
                                             }
                                         }
@@ -2101,6 +2102,15 @@ define([
                                         }
                                     }))
                                 }
+                        } else if(node.name.includes('xrcontroller')){
+                            actionsGUI.push(self.widgets.buttonStroked(
+                                {
+                                    "label": "Set as World default XR controller",
+                                    "onclick": function (e) {
+                                         vwf_view.kernel.callMethod(node.ID, "saveToScene", []);
+                                        
+                                    }
+                                }))
                         }
                        
 

+ 5 - 7
public/web/header.js

@@ -8,8 +8,6 @@ Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contribu
 class Header {
     constructor() {
         console.log("header constructor");
-        this.language = _LangManager.language;
-
     }
 
     init() {
@@ -49,7 +47,7 @@ class Header {
                                             $type: "a",
                                             style: "cursor:pointer; margin-right: 10px",
                                             class: "mdc-typography link-in-text mdc-theme--text-hint-on-background",
-                                            $text: "Home",
+                                            $text: _l.t("header_home"),//"Home",
                                             //href: "/" + desc[2] + '/worlds/' + desc[0] + '/edit', ///:user/worlds/:name/edit
                                             onclick: function (e) {
                                                 window.location.pathname = '/'
@@ -61,7 +59,7 @@ class Header {
                                             $type: "a",
                                             style: "cursor:pointer; margin-right: 10px",
                                             class: "mdc-typography link-in-text mdc-theme--text-hint-on-background",
-                                            $text: "Connection settings",
+                                            $text: _l.t("conn_settings"),
                                             //href: "/" + desc[2] + '/worlds/' + desc[0] + '/edit', ///:user/worlds/:name/edit
                                             onclick: function (e) {
                                                 window.location.pathname = '/settings'
@@ -74,7 +72,7 @@ class Header {
                                             $type: "a",
                                             style: "cursor:pointer; margin-right: 40px",
                                             class: "mdc-typography link-in-text mdc-theme--text-hint-on-background",
-                                            $text: "Help",
+                                            $text: _l.t("help"),
                                             //href: "/" + desc[2] + '/worlds/' + desc[0] + '/edit', ///:user/worlds/:name/edit
                                             href: 'https://www.krestianstvo.org/docs/sdk3'
 
@@ -84,7 +82,7 @@ class Header {
                                             id: 'ruLang',
                                             style: "cursor:pointer; margin-right: 10px",
                                             class: "mdc-typography link-in-text mdc-theme--text-hint-on-background",
-                                            $text: "RU",
+                                            $text: _l.t("ru"),
                                             //href: "/" + desc[2] + '/worlds/' + desc[0] + '/edit', ///:user/worlds/:name/edit
                                             onclick: function (e) {
                                                 _LangManager.locale = 'ru';
@@ -97,7 +95,7 @@ class Header {
                                             id: 'enLang',
                                             style: "cursor:pointer; margin-right: 10px",
                                             class: "mdc-typography link-in-text mdc-theme--text-hint-on-background",
-                                            $text: "EN",
+                                            $text: _l.t("en"),
                                             //href: "/" + desc[2] + '/worlds/' + desc[0] + '/edit', ///:user/worlds/:name/edit
                                             onclick: function (e) {
                                                 _LangManager.locale = 'en';

+ 36 - 30
public/web/index-app.js

@@ -138,7 +138,7 @@ class IndexApp {
             id: "userGUI",
             // style:"background-color: #ffeb3b",
             class: "mdc-layout-grid mdc-layout-grid--align-left",
-            _status: "Welcome!",
+            _status: _l.t("welcome") + '!',//"Welcome!",
             $init: function () {
                 //this._status = "Welcome!"
                 //this._status = 'Welcome!';
@@ -154,7 +154,7 @@ class IndexApp {
                     gui = [
                         window._app.widgets.buttonRaised(
                             {
-                                "label": 'Sign OUT',
+                                "label": _l.t("sign out"), //'Sign OUT',
                                 "onclick": function (e) {
                                     _LCSDB.user().leave();
                                     setTimeout(() => {
@@ -168,7 +168,7 @@ class IndexApp {
                         },
                         window._app.widgets.buttonStroked(
                             {
-                                "label": 'PROFILE',
+                                "label": _l.t("profile"),//'PROFILE',
                                 "onclick": function (e) {
                                     e.preventDefault();
                                     //page("/profile")
@@ -180,7 +180,7 @@ class IndexApp {
                         },
                         window._app.widgets.buttonStroked(
                             {
-                                "label": 'My World protos',
+                                "label": _l.t("my world protos"),
                                 "onclick": function (e) {
                                     e.preventDefault();
                                     let alias = _LCSDB.user().is.alias;
@@ -191,7 +191,7 @@ class IndexApp {
                             }),
                         window._app.widgets.buttonStroked(
                             {
-                                "label": 'My World states',
+                                "label": _l.t("my world states"),
                                 "onclick": function (e) {
                                     e.preventDefault();
                                     let alias = _LCSDB.user().is.alias;
@@ -210,6 +210,12 @@ class IndexApp {
                         class: "mdc-typography--headline3",
                         $text: this._status
                     }
+                    // ,{
+                    //     $type: "div",
+                    //     class: "mdc-typography--headline4",
+                    //     $text: navigator.userAgent
+                    // }
+                    
                 ].concat(gui)
             }
         }
@@ -268,7 +274,7 @@ class IndexApp {
                                     {
                                         $type: "h1",
                                         class: "mdc-typography--headline4",
-                                        $text: 'Worlds for user: ' + userAlias
+                                        $text: _l.t("protos for") + userAlias
                                     }
                                 ]
                             },
@@ -328,7 +334,7 @@ class IndexApp {
                                     {
                                         $type: "h1",
                                         class: "mdc-typography--headline4",
-                                        $text: 'States for ' + userAlias
+                                        $text: _l.t("states for") + userAlias
                                     }
                                 ]
                             },
@@ -352,7 +358,7 @@ class IndexApp {
 
         let alias = _LCSDB.user().is.alias;
         let userEl = document.querySelector('#userGUI');
-        userEl._status = 'Welcome ' + alias + '!';
+        userEl._status = _l.t("welcome") +', ' + alias + '!';
         //userEl.style.backgroundColor = '#e6e6e6';   
         userEl._refresh(); //$update();
 
@@ -445,7 +451,7 @@ class IndexApp {
 
                                 _app.widgets.inputTextFieldOutlined({
                                     "id": 'worldsUserName',
-                                    "label": 'Enter user name',
+                                    "label": _l.t("enter user name"),
                                     "value": defaultName,
                                     "type": "text",
                                     "init": function () {
@@ -475,7 +481,7 @@ class IndexApp {
                                 // }
                                 _app.widgets.buttonRaised(
                                     {
-                                        "label": 'World Protos',
+                                        "label":  _l.t("world protos"),
                                         "onclick": function (e) {
                                             e.preventDefault();
                                             //page("/app/worlds/protos")
@@ -489,7 +495,7 @@ class IndexApp {
                                 _app.widgets.space,
                                 _app.widgets.buttonRaised(
                                     {
-                                        "label": 'World States',
+                                        "label": _l.t("world states"),
                                         "onclick": function (e) {
                                             e.preventDefault();
                                             //page("/app/worlds/states")
@@ -531,7 +537,7 @@ class IndexApp {
                     {
                         $type: "h1",
                         class: "mdc-typography--headline4",
-                        $text: "Looking for Worlds made by other Users!"
+                        $text: _l.t("show worlds")//"Looking for Worlds made by other Users!"
                     }
                 ].concat(guiForAll, _app.widgets.p)
             }
@@ -949,7 +955,7 @@ class IndexApp {
                     userGUI.push({
                         $type: "a",
                         class: "mdc-button mdc-button--compact mdc-card__action mdc-button--outlined",
-                        $text: "Details",
+                        $text: _l.t("details"),
                         onclick: function (e) {
                             e.preventDefault();
                             window.location.pathname = "/" + desc.userAlias + '/' + desc.worldName + '/about'
@@ -1115,7 +1121,7 @@ class IndexApp {
                             $components: [
                                 {
                                     $type: 'div',
-                                    $text: 'online now: '
+                                    $text: _l.t("online now") + ': '
                                 }
                             ].concat(online)
                         }
@@ -1282,22 +1288,22 @@ class IndexApp {
                         $type: "div",
                         class: "mdc-layout-grid",
                         $components: [
-                            {
-                                $type: "div",
-                                class: "mdc-layout-grid__inner",
-                                $components: [
-                                    {
-                                        $type: "div",
-                                        class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
-                                        $components: [
-                                            {
-                                                $type: "H3",
-                                                $text: headerText
-                                            }
-                                        ]
-                                    }
-                                ]
-                            },
+                            // {
+                            //     $type: "div",
+                            //     class: "mdc-layout-grid__inner",
+                            //     $components: [
+                            //         {
+                            //             $type: "div",
+                            //             class: "mdc-layout-grid__cell mdc-layout-grid__cell--span-12",
+                            //             $components: [
+                            //                 {
+                            //                     $type: "H3",
+                            //                     $text: headerText
+                            //                 }
+                            //             ]
+                            //         }
+                            //     ]
+                            // },
                             {
                                 $type: "div",
                                 class: "mdc-layout-grid__inner",

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است