UNPKG

fyogametable

Version:

Fyo Game Table API

1,412 lines (1,190 loc) 110 kB
var FYO = FYO || {}; (function () { 'use strict'; function Button2D(connector, options) { options = options || {}; this.connector = connector; this.element = null; this.camera = null; this.scene = null; this.renderer = null; this.mouseX = 0; this.mouseY = 0; this.windowHalfX = window.innerWidth / 2; this.windowHalfY = window.innerHeight / 2; this.thumbObj = null; this.events = new FYO.EventManager(); if (options.ondown) { this.events.on('down', options.ondown); } if (options.onup) { this.events.on('up', options.onup); } navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate || function () { }; this.Init(options || { color: 0x222222 }); } Button2D.prototype = { element: null, camera: null, scene: null, renderer: null, mouseX: 0, mouseY: 0, windowHalfX: window.innerWidth / 2, windowHalfY: window.innerHeight / 2, thumbObj: null, events: null, on: function (e, f) { return this.events.on(e, f); }, remove: function (e, f) { return this.events.remove(e, f); }, clear: function (e) { return this.events.clear(e); }, Set: function (x, y, w, h) { this.positioner.Set(x, y, w, h); this.onWindowResize(); }, SetAlign: function (h, v) { this.positioner.align.horizontal = h; this.positioner.align.vertical = v; }, Reposition: function (x, y, w, h) { this.onWindowResize(x, y, w, h); }, Init: function (options) { var self = this; this.element = document.createElement('div'); this.positioner = new FYO.Positioner(this.element); this.element.setAttribute('style', 'position: absolute; top: 0; left: 0; right: 100%; bottom: 0;'); var containerParent = document.body; if (options.container) { containerParent = document.getElementById(options.container); } containerParent.appendChild(this.element); this.image = document.createElement('div'); var style = 'background: url(\'' + (options.image || '/fyogametable/imgs/Red_A.png') + '\') no-repeat center center;'; style += 'background-size: contain; width: 100%; height: 100%;' this.image.setAttribute('style', style); this.element.appendChild(this.image); this.element.addEventListener('mousemove', function (e) { self.onMouseMove(e); }, false); this.element.addEventListener('mousedown', function (e) { self.onMouseDown(e); }, false); this.element.addEventListener('mouseup', function (e) { self.onMouseUp(e); }, false); this.element.addEventListener('mouseleave', function (e) { self.onMouseLeave(e); }, false); this.element.addEventListener('touchmove', function (e) { self.onTouchMove(e); }, false); this.element.addEventListener('touchstart', function (e) { self.onTouchStart(e); }, false); this.element.addEventListener('touchend', function (e) { self.onTouchDone(e); }, false); // window.addEventListener('resize', function (e) { self.onWindowResize(e); }, false); }, onWindowResize: function () { this.elementHalfX = this.element.clientWidth / 2; this.elementHalfY = this.element.clientHeight / 2; }, onMouseMove: function (event) { event.preventDefault(); this.mouseX = event.offsetX; this.mouseY = event.offsetY; }, onMouseDown: function (event) { event.preventDefault(); this.mouseDown = true; this.events.trigger('down', true); }, onMouseUp: function (event) { event.preventDefault(); this.mouseDown = false; this.events.trigger('up', true); }, onMouseLeave: function (event) { event.preventDefault(); this.mouseX = this.elementHalfX; this.mouseY = this.elementHalfY; }, onTouchStart: function () { navigator.vibrate(10); this.mouseDown = true; this.events.trigger('down', true); }, onTouchMove: function (event) { event.preventDefault(); var rect = this.element.getBoundingClientRect(); for (var i = 0; i < event.touches.length; i++) { // determine if touch is within rect var touch = event.touches[i]; if (touch.pageX >= rect.left && touch.pageX <= rect.right && touch.pageY >= rect.top && touch.pageY <= rect.bottom) { this.mouseX = touch.pageX - rect.left; this.mouseY = touch.pageY - rect.top; } } }, onTouchDone: function (event) { event.preventDefault(); this.mouseX = this.elementHalfX; this.mouseY = this.elementHalfY; //navigator.vibrate(10); this.mouseDown = false; this.events.trigger('up', true); } }; FYO.Button2D = Button2D; })(); var FYO = FYO || {}; (function () { 'use strict'; function Button3D(connector, options) { options = options || {}; this.connector = connector; this.element = null; this.camera = null; this.scene = null; this.renderer = null; this.mouseX = 0; this.mouseY = 0; this.windowHalfX = window.innerWidth / 2; this.windowHalfY = window.innerHeight / 2; this.thumbObj = null; this.events = new FYO.EventManager(); if (options.ondown) { this.events.on('down', options.ondown); } if (options.onup) { this.events.on('up', options.onup); } navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate || function () { }; this.Init(options || { color: 0x222222 }); //this.Animate(); } Button3D.prototype = { element: null, camera: null, scene: null, renderer: null, mouseX: 0, mouseY: 0, windowHalfX: window.innerWidth / 2, windowHalfY: window.innerHeight / 2, thumbObj: null, events: null, on: function (e, f) { return this.events.on(e, f); }, remove: function (e, f) { return this.events.remove(e, f); }, clear: function (e) { return this.events.clear(e); }, Set: function (x, y, w, h) { this.positioner.Set(x, y, w, h); this.onWindowResize(); }, SetAlign: function (h, v) { this.positioner.align.horizontal = h; this.positioner.align.vertical = v; }, Reposition: function (x, y, w, h) { this.onWindowResize(x, y, w, h); }, Init: function (options) { var self = this; this.element = document.createElement('div'); this.positioner = new FYO.Positioner(this.element); this.element.setAttribute('style', 'position: absolute; top: 0; left: 0; right: 100%; bottom: 0;'); var containerParent = document.body; if (options.container) { containerParent = document.getElementById(options.container); } containerParent.appendChild(this.element); // scene this.scene = new THREE.Scene(); var ambient = new THREE.AmbientLight(0x101030); this.scene.add(ambient); var directionalLight = new THREE.DirectionalLight(0xffeedd); directionalLight.position.set(1, 10, 1); this.scene.add(directionalLight); this.camera = new THREE.PerspectiveCamera(45, this.element.clientWidth / this.element.clientHeight, 1, 2000); this.camera.position.y = 3.3; this.camera.position.z = 1; this.camera.lookAt(this.scene.position); // texture var manager = new THREE.LoadingManager(); manager.onProgress = function (/*item, loaded, total*/) { }; var onProgress = function (/*xhr*/) { //if (xhr.lengthComputable) { // var percentComplete = xhr.loaded / xhr.total * 100; // console.log(Math.round(percentComplete, 2) + '% downloaded'); //} }; var onError = function (/*xhr*/) { }; var modelLoader = new THREE.OBJLoader(manager); if (options.color) { modelLoader.load(options.model || '/fyogametable/assets/objs/Button.obj', function (object) { object.traverse(function (child) { console.log(child); if (child instanceof THREE.Mesh) { child.material.color = new THREE.Color(options.color || 0x221111); } }); object.position.y = 0; self.thumbObj = object; self.scene.add(object); self.Render(); }, onProgress, onError); } else if(options.image) { var texture = new THREE.Texture(); var loader = new THREE.ImageLoader(manager); loader.load(options.image || '/fyogametable/imgs/Red_A.png', function (image) { texture.image = image; texture.needsUpdate = true; self.Render(); }); modelLoader.load(options.model || '/fyogametable/assets/objs/ButtonTex.obj', function (object) { object.traverse(function (child) { if (child instanceof THREE.Mesh) { child.material.map = texture; } }); object.position.y = 0; self.thumbObj = object; self.scene.add(object); self.Render(); }, onProgress, onError); } // this.renderer = new THREE.WebGLRenderer({ alpha: true }); this.renderer.setPixelRatio(window.devicePixelRatio); this.renderer.setSize(this.element.clientWidth, this.element.clientHeight); this.renderer.setClearColor(0x000000, 0); this.element.appendChild(this.renderer.domElement); this.element.addEventListener('mousemove', function (e) { self.onMouseMove(e); }, false); this.element.addEventListener('mousedown', function (e) { self.onMouseDown(e); }, false); this.element.addEventListener('mouseup', function (e) { self.onMouseUp(e); }, false); this.element.addEventListener('mouseleave', function (e) { self.onMouseLeave(e); }, false); this.element.addEventListener('touchmove', function (e) { self.onTouchMove(e); }, false); this.element.addEventListener('touchstart', function (e) { self.onTouchStart(e); }, false); this.element.addEventListener('touchend', function (e) { self.onTouchDone(e); }, false); // window.addEventListener('resize', function (e) { self.onWindowResize(e); }, false); this.Render(); }, onWindowResize: function () { this.elementHalfX = this.element.clientWidth / 2; this.elementHalfY = this.element.clientHeight / 2; this.camera.aspect = this.elementHalfX / this.elementHalfY; this.camera.updateProjectionMatrix(); this.renderer.setSize(this.element.clientWidth, this.element.clientHeight); this.Render(); }, onMouseMove: function (event) { event.preventDefault(); this.mouseX = event.offsetX; this.mouseY = event.offsetY; this.Render(); }, onMouseDown: function (event) { event.preventDefault(); this.mouseDown = true; this.events.trigger('down', true); this.Render(); }, onMouseUp: function (event) { event.preventDefault(); this.mouseDown = false; this.events.trigger('up', true); this.Render(); }, onMouseLeave: function (event) { event.preventDefault(); this.mouseX = this.elementHalfX; this.mouseY = this.elementHalfY; this.Render(); }, onTouchStart: function () { navigator.vibrate(10); this.mouseDown = true; this.events.trigger('down', true); this.Render(); }, onTouchMove: function (event) { event.preventDefault(); var rect = this.element.getBoundingClientRect(); for (var i = 0; i < event.touches.length; i++) { // determine if touch is within rect var touch = event.touches[i]; if (touch.pageX >= rect.left && touch.pageX <= rect.right && touch.pageY >= rect.top && touch.pageY <= rect.bottom) { this.mouseX = touch.pageX - rect.left; this.mouseY = touch.pageY - rect.top; } } this.Render(); }, onTouchDone: function (event) { event.preventDefault(); this.mouseX = this.elementHalfX; this.mouseY = this.elementHalfY; //navigator.vibrate(10); this.mouseDown = false; this.events.trigger('up', true); this.Render(); }, //Animate: function () { // var self = this; // requestAnimationFrame(function () { // self.Animate(); // }); // this.Render(); //}, Render: function () { if (this.thumbObj !== null) { this.thumbObj.scale.y = this.mouseDown ? 0.75 : 1.0; } this.renderer.render(this.scene, this.camera); } }; FYO.Button3D = Button3D; })(); var FYO = FYO || {}; (function () { 'use strict'; function DPad2D(connector, options) { options = options || {}; this.connector = connector; this.element = null; this.camera = null; this.scene = null; this.renderer = null; this.mouseX = 0; this.mouseY = 0; this.windowHalfX = window.innerWidth / 2; this.windowHalfY = window.innerHeight / 2; this.thumbObj = null; this.x = 0; this.y = 0; this.events = new FYO.EventManager(); if (options.onmoved) { this.events.on('moved', options.onmoved); } navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate || function () { }; this.Init(options); } DPad2D.prototype = { element: null, camera: null, scene: null, renderer: null, mouseX: 0, mouseY: 0, windowHalfX: window.innerWidth / 2, windowHalfY: window.innerHeight / 2, thumbObj: null, events: null, on: function (e, f) { return this.events.on(e, f); }, remove: function (e, f) { return this.events.remove(e, f); }, clear: function (e) { return this.events.clear(e); }, Reposition: function (x, y, w, h) { var style = 'position: absolute; top: ' + y + 'px;'; style += 'left: ' + x + 'px;'; style += 'right: ' + (x + w) + 'px;'; style += 'bottom: ' + (y + h) + 'px;'; style += 'width: ' + w + 'px;'; style += 'height: ' + h + 'px;'; style += 'padding: 30px;'; this.element.setAttribute('style', style); this.onWindowResize(); }, Init: function (options) { var self = this; this.element = document.createElement('div'); // TODO: (garrett) This needs to be abstracted out like the button if (options.side) { this.element.setAttribute('style', 'padding: 30px; position: absolute; top: 0; left: 50%; right: 0; bottom: 30%;'); } else { this.element.setAttribute('style', 'padding: 30px; position: absolute; top: 0; left: 0; right: 50%; bottom: 0;'); } var containerParent = document.body; if (options.container) { containerParent = document.getElementById(options.container); } containerParent.appendChild(this.element); this.elementHalfX = this.element.clientWidth / 2; this.elementHalfY = this.element.clientHeight / 2; this.image = document.createElement('div'); var style = 'background: url(\'' + (options.image || '/fyogametable/assets/imgs/DPad_2D.png') + '\') no-repeat center center;'; style += 'background-size: contain; width: 100%; height: 100%;' this.image.setAttribute('style', style); this.element.appendChild(this.image); this.element.addEventListener('mousemove', function (e) { self.onMouseMove(e); }, false); this.element.addEventListener('mouseleave', function (e) { self.onMouseLeave(e); }, false); this.element.addEventListener('touchmove', function (e) { self.onTouchMove(e); }, false); this.element.addEventListener('touchstart', function (e) { self.onTouchStart(e); }, false); this.element.addEventListener('touchend', function (e) { self.onTouchDone(e); }, false); // window.addEventListener('resize', function (e) { self.onWindowResize(e); }, false); }, onWindowResize: function () { this.elementHalfX = this.element.clientWidth / 2; this.elementHalfY = this.element.clientHeight / 2; }, onMouseMove: function (event) { event.preventDefault(); this.mouseX = event.offsetX; this.mouseY = event.offsetY; this._update(); }, onMouseLeave: function (event) { event.preventDefault(); this.mouseX = this.elementHalfX; this.mouseY = this.elementHalfY; this._update(); }, onTouchStart: function (event) { event.preventDefault(); navigator.vibrate(10); var rect = this.element.getBoundingClientRect(); for (var i = 0; i < event.touches.length; i++) { // determine if touch is within rect var touch = event.touches[i]; if (touch.pageX >= rect.left && touch.pageX <= rect.right && touch.pageY >= rect.top && touch.pageY <= rect.bottom) { this.mouseX = touch.pageX - rect.left; this.mouseY = touch.pageY - rect.top; this._update(); } } }, onTouchMove: function (event) { event.preventDefault(); var rect = this.element.getBoundingClientRect(); for (var i = 0; i < event.touches.length; i++) { // determine if touch is within rect var touch = event.touches[i]; if (touch.pageX >= rect.left && touch.pageX <= rect.right && touch.pageY >= rect.top && touch.pageY <= rect.bottom) { this.mouseX = touch.pageX - rect.left; this.mouseY = touch.pageY - rect.top; this._update(); } } }, onTouchDone: function (event) { event.preventDefault(); this.mouseX = this.elementHalfX; this.mouseY = this.elementHalfY; this._update(); navigator.vibrate(10); }, _update: function () { var prevX = this.x; var prevY = this.y; var _y = (this.mouseY - this.elementHalfY) / this.elementHalfY; var _x = (this.mouseX - this.elementHalfX) / this.elementHalfX; this.x = -Math.sin(_x); this.y = Math.sin(_y); var len = Math.sqrt((this.x * this.x + this.y * this.y)); if (len > 1) { this.x /= len; this.y /= len; } if (Math.abs(this.y) > Math.abs(this.x)) { this.y = this.y > 0 ? 1 : -1; this.x = 0; } else if (Math.abs(this.x) > Math.abs(this.y)) { this.x = this.x > 0 ? 1 : -1; this.y = 0; } else { this.x = 0; this.y = 0; } if (prevX != this.x || prevY != this.y) { navigator.vibrate(10); } this.events.trigger('moved', { x: -this.x, y: -this.y }); } }; FYO.DPad2D = DPad2D; })(); var FYO = FYO || {}; (function () { 'use strict'; function DPad3D(connector, options) { options = options || {}; this.connector = connector; this.element = null; this.camera = null; this.scene = null; this.renderer = null; this.mouseX = 0; this.mouseY = 0; this.windowHalfX = window.innerWidth / 2; this.windowHalfY = window.innerHeight / 2; this.thumbObj = null; this.x = 0; this.y = 0; this.events = new FYO.EventManager(); if (options.onmoved) { this.events.on('moved', options.onmoved); } navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate || function () { }; this.Init(options); } DPad3D.prototype = { element: null, camera: null, scene: null, renderer: null, mouseX: 0, mouseY: 0, windowHalfX: window.innerWidth / 2, windowHalfY: window.innerHeight / 2, thumbObj: null, events: null, on: function (e, f) { return this.events.on(e, f); }, remove: function (e, f) { return this.events.remove(e, f); }, clear: function (e) { return this.events.clear(e); }, Reposition: function (x, y, w, h) { var style = 'position: absolute; top: ' + y + 'px;'; style += 'left: ' + x + 'px;'; style += 'right: ' + (x + w) + 'px;'; style += 'bottom: ' + (y + h) + 'px;'; style += 'width: ' + w + 'px;'; style += 'height: ' + h + 'px;'; this.element.setAttribute('style', style); this.onWindowResize(); }, Init: function (options) { var self = this; this.element = document.createElement('div'); // TODO: (garrett) This needs to be abstracted out like the button if (options.side) { this.element.setAttribute('style', 'position: absolute; top: 0; left: 50%; right: 0; bottom: 30%;'); } else { this.element.setAttribute('style', 'position: absolute; top: 0; left: 0; right: 50%; bottom: 0;'); } var containerParent = document.body; if (options.container) { containerParent = document.getElementById(options.container); } containerParent.appendChild(this.element); // scene this.scene = new THREE.Scene(); var ambient = new THREE.AmbientLight(0x101030); this.scene.add(ambient); var directionalLight = new THREE.DirectionalLight(0xffeedd); directionalLight.position.set(1, 10, 1); this.scene.add(directionalLight); this.camera = new THREE.PerspectiveCamera(45, this.element.clientWidth / this.element.clientHeight, 1, 2000); this.camera.position.y = 7; this.camera.position.z = 1; this.camera.lookAt(this.scene.position); // texture var manager = new THREE.LoadingManager(); manager.onProgress = function (item, loaded, total) { console.log(item, loaded, total); }; var onProgress = function () { //if (xhr.lengthComputable) { // var percentComplete = xhr.loaded / xhr.total * 100; // console.log(Math.round(percentComplete, 2) + '% downloaded'); //} }; var onError = function (xhr) { console.log(xhr); }; // model var loader = new THREE.OBJLoader(manager); loader.load('/fyogametable/assets/objs/DPad.obj', function (object) { object.traverse(function (child) { //console.log(child); if (child instanceof THREE.Mesh) { if (child.material.materials) { child.material.materials[0].color = new THREE.Color(0xcccccc); child.material.materials[1].color = new THREE.Color(0x222222); } else { child.material.color = new THREE.Color(0x222222); } } }); object.position.y = 0; self.thumbObj = object; self.scene.add(object); self.Render(); }, onProgress, onError); // this.elementHalfX = this.element.clientWidth / 2; this.elementHalfY = this.element.clientHeight / 2; this.renderer = new THREE.WebGLRenderer({ alpha: true }); this.renderer.setPixelRatio(window.devicePixelRatio); this.renderer.setSize(this.element.clientWidth, this.element.clientHeight); this.renderer.setClearColor(0x000000, 0); this.element.appendChild(this.renderer.domElement); this.element.addEventListener('mousemove', function (e) { self.onMouseMove(e); }, false); this.element.addEventListener('mouseleave', function (e) { self.onMouseLeave(e); }, false); this.element.addEventListener('touchmove', function (e) { self.onTouchMove(e); }, false); this.element.addEventListener('touchstart', function (e) { self.onTouchStart(e); }, false); this.element.addEventListener('touchend', function (e) { self.onTouchDone(e); }, false); // window.addEventListener('resize', function (e) { self.onWindowResize(e); }, false); this.Render(); }, onWindowResize: function () { this.elementHalfX = this.element.clientWidth / 2; this.elementHalfY = this.element.clientHeight / 2; this.camera.aspect = this.elementHalfX / this.elementHalfY; this.camera.updateProjectionMatrix(); this.renderer.setSize(this.element.clientWidth, this.element.clientHeight); this.Render(); }, onMouseMove: function (event) { event.preventDefault(); this.mouseX = event.offsetX; this.mouseY = event.offsetY; this._update(); this.Render(); }, onMouseLeave: function (event) { event.preventDefault(); this.mouseX = this.elementHalfX; this.mouseY = this.elementHalfY; this._update(); this.Render(); }, onTouchStart: function (event) { event.preventDefault(); navigator.vibrate(10); var rect = this.element.getBoundingClientRect(); for (var i = 0; i < event.touches.length; i++) { // determine if touch is within rect var touch = event.touches[i]; if (touch.pageX >= rect.left && touch.pageX <= rect.right && touch.pageY >= rect.top && touch.pageY <= rect.bottom) { this.mouseX = touch.pageX - rect.left; this.mouseY = touch.pageY - rect.top; this._update(); } } this.Render(); }, onTouchMove: function (event) { event.preventDefault(); var rect = this.element.getBoundingClientRect(); for (var i = 0; i < event.touches.length; i++) { // determine if touch is within rect var touch = event.touches[i]; if (touch.pageX >= rect.left && touch.pageX <= rect.right && touch.pageY >= rect.top && touch.pageY <= rect.bottom) { this.mouseX = touch.pageX - rect.left; this.mouseY = touch.pageY - rect.top; this._update(); } } this.Render(); }, onTouchDone: function (event) { event.preventDefault(); this.mouseX = this.elementHalfX; this.mouseY = this.elementHalfY; this._update(); navigator.vibrate(10); this.Render(); }, _update: function () { var prevX = this.x; var prevY = this.y; var _y = (this.mouseY - this.elementHalfY) / this.elementHalfY; var _x = (this.mouseX - this.elementHalfX) / this.elementHalfX; this.x = -Math.sin(_x); this.y = Math.sin(_y); var len = Math.sqrt((this.x * this.x + this.y * this.y)); if (len > 1) { this.x /= len; this.y /= len; } if (Math.abs(this.y) > Math.abs(this.x)) { this.y = this.y > 0 ? 1 : -1; this.x = 0; } else if (Math.abs(this.x) > Math.abs(this.y)) { this.x = this.x > 0 ? 1 : -1; this.y = 0; } else { this.x = 0; this.y = 0; } if (prevX != this.x || prevY != this.y) { navigator.vibrate(10); } this.events.trigger('moved', { x: -this.x, y: -this.y }); }, Render: function () { if (this.thumbObj !== null) { this.thumbObj.rotation.x = this.y / 4.0; this.thumbObj.rotation.z = this.x / 4.0; } this.renderer.render(this.scene, this.camera); } }; FYO.DPad3D = DPad3D; })(); var FYO = FYO || {}; (function () { 'use strict'; function EventManager() { this.onEvents = {}; } EventManager.prototype = { onEvents: {}, on: function (e, f) { if (!this.onEvents[e]) { this.onEvents[e] = []; } this.onEvents[e].push(f); }, remove: function (e, f) { if (!this.onEvents[e]) { return; } for (var i = 0; i < this.onEvents[e].length; i++) { if (this.onEvents[e][i] === f) { this.onEvents[e].splice(i, 1); return true; } } return false; }, clear: function (e) { delete this.onEvents[e]; }, trigger: function (e, arg) { if (!this.onEvents[e]) { return; } for (var i = 0; i < this.onEvents[e].length; i++) { this.onEvents[e][i](arg); } } }; FYO.EventManager = EventManager; })(); var FYO = FYO || {}; (function () { 'use strict'; function FyoConnection(controller, options, cb) { var self = this; if (!controller) { alert('Controller must be specified'); return; } options = options || {}; this.controller = controller; this.socket = io(); this.socket.on('connect', function () { self.OnConnect(); }); this.input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; this.events = new FYO.EventManager(); this.IOHelper = new FYO.IOHelper({ orientation: function (gamma, beta, alpha) { self.events.trigger('orientation', { gamma: gamma, beta: beta, alpha: alpha }); }, motion: function (accelerationX, accelerationY, accelerationZ) { self.events.trigger('acceleration', { x: accelerationX, y: accelerationY, z: accelerationZ }); } }); var fullscreenImage = document.createElement('img'); fullscreenImage.setAttribute('class', 'fyo-fullscreen'); fullscreenImage.setAttribute('src', options.fullscreenImage || '/fyogametable/assets/imgs/fullscreen-128.png'); fullscreenImage.onmouseup = FYO.IOHelper.FullScreen; document.body.appendChild(fullscreenImage); var settings = document.createElement('img'); settings.setAttribute('class', 'fyo-settings'); settings.setAttribute('src', options.settingsImage || '/fyogametable/assets/imgs/settings-128.png'); var settingsWindowEl = document.createElement('div'); { settingsWindowEl.setAttribute('class', 'fyo-settings-window'); settingsWindowEl.setAttribute('style', 'display: none'); { var settingsWindowInnerEl = document.createElement('div'); settingsWindowInnerEl.setAttribute('class', 'fyo-settings-window-inner'); { var headerEl = document.createElement('h1'); headerEl.innerText = 'SETTINGS'; settingsWindowInnerEl.appendChild(headerEl); var optionsEl = document.createElement('div'); optionsEl.setAttribute('class', 'fyo-settings-window-options'); { var optEl = document.createElement('div'); optEl.setAttribute('class', 'fyo-settings-window-option'); optEl.innerText = 'Close Game'; optEl.onmouseup = function () { self.Send('AppEndMsg'); }; optionsEl.appendChild(optEl); } settingsWindowInnerEl.appendChild(optionsEl); var closeEl = document.createElement('img'); closeEl.setAttribute('class', 'fyo-settings-close'); closeEl.setAttribute('src', options.closeImage || '/fyogametable/assets/imgs/close.png'); closeEl.onmouseup = function () { settingsWindowEl.setAttribute('style', 'display: none'); }; settingsWindowInnerEl.appendChild(closeEl); } settingsWindowEl.appendChild(settingsWindowInnerEl); } document.body.appendChild(settingsWindowEl); } settings.onmouseup = function () { // display settings window settingsWindowEl.setAttribute('style', ''); }; document.body.appendChild(settings); this.IOHelper.GetDeviceInfo(function (info) { self.info = info; self.events.trigger('info'); }); } FyoConnection.prototype = { alphabet: 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', OnConnect: function () { var self = this; this.IOHelper.GetDeviceInfo(function (info) { console.log(info); self.info = info; self.socket.emit('SGHandshakeIdentMsg', { DeviceId: self.GetClientId(), Controller: self.controller, Info: info }); self.events.trigger('connected'); }); this.socket.on('SGRedirectMsg', function (path) { if (path == this.controller) { // we're already at this controller return; } window.location = '/' + path; }); this.socket.on('SGUpdateMsg', function (msg) { self.events.trigger('SGUpdateMsg', msg); self.events.trigger(msg.MessageType, msg.data); }); this.socket.on('app-ping', function (data) { self.socket.emit('app-pong', data); }); this.socket.on('app-latency', function (data) { self.events.trigger('app-latency', data); }); }, GetClientId: function () { var clientId = window.localStorage.getItem('clientId'); if (!clientId) { clientId = this.GenUniqueId(); window.localStorage.setItem('clientId', clientId); } return clientId; }, GenUniqueId: function() { var code = ''; for (var i = 0; i < 24; i++) { code += this.alphabet[Math.floor(Math.random() * (this.alphabet.length - 1))]; } return code; }, Send: function (messageType, data) { this.socket.emit('SGUpdateMsg', { MessageType: messageType, data: data }); }, SendInput: function () { this.Send('Input', { 'button 0': this.input[0] > 0, 'button 1': this.input[1] > 0, 'button 2': this.input[2] > 0, 'button 3': this.input[3] > 0, 'button 4': this.input[4] > 0, 'button 5': this.input[5] > 0, 'button 6': this.input[6] > 0, 'button 7': this.input[7] > 0, 'button 8': this.input[8] > 0, 'button 9': this.input[9] > 0, 'axis 0': this.input[10], 'axis 1': this.input[11], 'axis 2': this.input[12], 'axis 3': this.input[13], 'axis 4': this.input[14], 'axis 5': this.input[15], 'axis 6': this.input[16], 'axis 7': this.input[17] }); }, SetAxis: function (axis1, val1, axis2, val2) { this.input[axis1] = val1; if (axis2) { this.input[axis2] = val2; } this.SendInput(); }, SetButton: function (btn, state) { this.input[btn] = state; this.SendInput(); }, SetButtonOn: function (btn) { this.SetButton(btn, 1); }, SetButtonOff: function (btn) { this.SetButton(btn, 0); }, AddVisualLatency: function () { var ping = document.createElement('h3'); ping.setAttribute('id', 'ping-message'); document.body.appendChild(ping); this.on('app-latency', function (data) { ping.innerText = Math.floor(data.average); }); }, TakePicture: function (ev) { var self = this; var picture = new FYO.Picture(function (data) { self.Send(ev || 'Picture', data); }); }, // Event Manager - easy access on: function (e, f) { return this.events.on(e, f); }, remove: function (e, f) { return this.events.remove(e, f); } }; FYO.FyoConnection = FyoConnection; FYO.BUTTON = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; FYO.AXIS = [10, 11, 12, 13, 14, 15, 16, 17]; })(); var FYO = FYO || {}; (function () { 'use strict'; function IOHelper(options) { options = options || {}; if (window.DeviceOrientationEvent) { // Listen for the event and handle DeviceOrientationEvent object window.addEventListener('deviceorientation', function(ev) { if (options && options.orientation) { options.orientation(ev.gamma, ev.beta, ev.alpha); } }, false); } if (window.DeviceMotionEvent) { window.addEventListener('devicemotion', function(ev) { if (options && options.motion) { options.motion(ev.acceleration.x, ev.acceleration.y, ev.acceleration.z); } }, false); } } IOHelper.FullScreen = function () { // Supports most browsers and their versions. var requestMethod = document.body.requestFullScreen || document.body.webkitRequestFullScreen || document.body.mozRequestFullScreen || document.body.msRequestFullScreen; var requestExitMethod = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen; if (requestMethod) { // Native full screen. if (!document.fullscreenElement) { // no full screen element found, go full screen requestMethod.call(document.body); document.fullscreenElement = document.body; } else { requestExitMethod.call(document); document.fullscreenElement = null; } } else if (typeof window.ActiveXObject !== 'undefined') { // Older IE. var wscript = new ActiveXObject('WScript.Shell'); if (wscript !== null) { wscript.SendKeys('{F11}'); } } }; IOHelper.GetDevices = function (cb) { if (navigator.mediaDevices) { navigator.mediaDevices.enumerateDevices().then(function (devices) { var result = { audioInput: [], audioOutput: [], videoInput: [] }; for (var i = 0; i < devices.length; i++) { switch (devices[i].kind) { case 'audioinput': result.audioInput.push({ deviceId: devices[i].deviceId, groupId: devices[i].groupId, label: devices[i].label }); break; case 'videoinput': result.videoInput.push({ deviceId: devices[i].deviceId, groupId: devices[i].groupId, label: devices[i].label }); break; case 'audiooutput': result.audioOutput.push({ deviceId: devices[i].deviceId, groupId: devices[i].groupId, label: devices[i].label }); break; default: break; } } cb && cb(result); }); } else { cb && cb(null); } }; IOHelper.prototype = { _getBattery: function (cb) { if (navigator.getBattery) { navigator.getBattery().then(function (battery) { if (battery) { cb && cb({ charging: battery.charging, chargingTime: battery.chargingTime, dischargingTime: battery.dischargingTime, level: battery.level }); } else { cb && cb(null); } }); } else { cb && cb(null); } }, GetDeviceInfo: function (cb) { var self = this; var result = { browser: platform.name, version: platform.version, manufacturer: platform.manufacturer, product: platform.product, os: { family: platform.os.family, version: platform.os.version, architecture: platform.os.architecture }, description: platform.description, layout: platform.layout, ua: platform.ua, resolution: { width: window.screen.width, height: window.screen.height, pixelRatio: window.devicePixelRatio }, orientation: window.innerHeight > window.innerWidth ? 'portrait' : 'landscape' }; result.capabilities = { deviceorientation: Modernizr.deviceorientation, devicemotion: Modernizr.devicemotion, ambientlight: Modernizr.ambientlight, applicationcache: Modernizr.applicationcache, audiopreload: Modernizr.audiopreload, batteryapi: Modernizr.batteryapi, canvas: Modernizr.canvas, cors: Modernizr.cors, cssanimations: Modernizr.cssanimations, emoji: Modernizr.emoji, forcetouch: Modernizr.forcetouch, fullscreen: Modernizr.fullscreen, gamepads: Modernizr.gamepads, geolocation: Modernizr.geolocation, getusermedia: Modernizr.getusermedia, localstorage: Modernizr.localstorage, lowbattery: Modernizr.lowbattery, notification: Modernizr.notification, pointerlock: Modernizr.pointerlock, proximity: Modernizr.proximity, requestanimationframe: Modernizr.requestanimationframe, sessionstorage: Modernizr.sessionstorage, speechrecognition: Modernizr.speechrecognition, speechsynthesis: Modernizr.speechsynthesis, svg: Modernizr.svg, touchevents: Modernizr.touchevents, vibrate: Modernizr.vibrate, webanimations: Modernizr.webanimations, webaudio: Modernizr.webaudio, webgl: Modernizr.webgl, websockets: Modernizr.websockets, webworkers: Modernizr.webworkers, video: Modernizr.video == true, audio: Modernizr.audio == true }; this._getBattery(function (battery) { result.isDesktop = !battery || (battery.charging && battery.chargingTime == 0); if (battery) { result.battery = { charging: battery.charging, chargingTime: battery.chargingTime, dischargingTime: battery.dischargingTime, level: battery.level }; } IOHelper.GetDevices(function (devices) { result.devices = devices; cb && cb(result); }); }); } }; FYO.IOHelper = IOHelper; })(); var FYO = FYO || {}; (function () { 'use strict'; function Picture(cb) { this.width = 320; // We will scale the photo width to this this.height = 0; // This will be computed based on the input stream this.streaming = false; this.video = null; this.canvas = null; this.photo = null; this.startbutton = null; this._resultCB = cb; this.Init(); } Picture.prototype = { Init: function () { var self = this; this.container = document.createElement('div'); this.container.setAttribute('class', 'fyo-container'); this.photoContainer = document.createElement('div'); this.photoContainer.setAttribute('class', 'fyo-picture'); this.video = document.createElement('video'); this.canvas = document.createElement('canvas'); this.canvas.setAttribute('style', 'display:none'); this.photo = document.createElement('img'); this.photo.setAttribute('style', 'display:none'); this.startbutton = document.createElement('a'); this.startbutton.setAttribute('href', 'javascript:void(0);'); this.startbutton.setAttribute('class', 'btn btn-primary'); this.startbutton.innerText = 'Take Picture'; this.cancelbutton = document.createElement('a'); this.cancelbutton.setAttribute('href', 'javascript:void(0);'); this.cancelbutton.setAttribute('class', 'btn btn-primary'); this.cancelbutton.innerTe