UNPKG

foam-framework

Version:
324 lines (290 loc) 10.2 kB
/** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ CLASS({ package: 'com.google.watlobby', name: 'Lobby', extends: 'foam.graphics.CView', traits: [ 'com.google.misc.Colors', 'com.google.watlobby.RemoteTrait' ], requires: [ 'com.google.watlobby.SmallRemote', 'com.google.watlobby.Remote', 'com.google.watlobby.TopicApp', 'com.google.watlobby.TopicDAO', 'com.google.watlobby.Bubble', 'com.google.watlobby.TopicBubble', 'com.google.watlobby.AlbumBubble', 'com.google.watlobby.PhotoBubble', 'com.google.watlobby.Topic', 'com.google.watlobby.VideoBubble', // 'foam.demos.ClockView', 'foam.demos.physics.PhysicalCircle', 'foam.graphics.ImageCView', 'foam.physics.PhysicsEngine as Collider', 'foam.util.Timer' ], imports: [ 'timer', 'clearTimeout', 'setTimeout' ], exports: [ 'as lobby' ], properties: [ { name: 'timer' }, { name: 'clientMode', defaultValue: false, model_: 'BooleanProperty' }, { name: 'n', defaultValue: 25 }, { name: 'slideshowDelay', model_: 'IntProperty' }, { name: 'airBubbles', defaultValue: 0, model_: 'IntProperty' }, { name: 'width', defaultValue: window.innerWidth }, { name: 'height', defaultValue: window.innerHeight }, { name: 'background', defaultValue: '#ccf' }, { name: 'collider', factory: function() { var c = this.Collider.create(); var w = this.width; var h = this.height; var self = this; c.detectCollisions = function() { var cs = this.children; for ( var i = 0 ; i < cs.length ; i++ ) { var c1 = cs[i]; this.updateChild(c1); var r = c1.r + 10; // Add Coriolis Effect var a = Math.atan2(c1.y-h/2, c1.x-w/2); var d = Movement.distance(c1.y-h/2, c1.x-w/2); // Keeps topic bubbles from going too far off screen // if ( c1.topic && d > h / 2 - r) c1.out_ = false; if ( d > w / 2 - 2*r ) c1.out_ = false; if ( d < h/4 ) c1.out_ = true; // c1.color = c1.out_ ? 'orange' : 'blue'; // The 0.9 gives it a slight outward push if ( c1.mass != c1.INFINITE_MASS ) c1.applyMomentum((0.5+0.4*c1.$UID%11/10) * c1.mass/8, a+(c1.out_ ? 0.9 : 1.1)*Math.PI/2); // Make collision detection 5X faster by only checking every fifth time. if ( ( self.timer.i + i ) % 5 == 0 ) for ( var j = i+1 ; j < cs.length ; j++ ) { var c2 = cs[j]; if ( c1.intersects(c2) ) this.collide(c1, c2); } } }; return c; }}, { name: 'topics', lazyFactory: function() { return this.TopicDAO.create({ clientMode: this.clientMode }); } }, { name: 'dir', defaultValue: '', postSet: function(_, d) { var Topic = this.Topic; this.topics.where( AND( NEQ(Topic.PARENT_TOPIC, d), NEQ(Topic.TOPIC, d)) ).select({put: this.removeTopic}); this.topics.where( OR( EQ(Topic.PARENT_TOPIC, d), EQ(Topic.TOPIC, d) ) ).select({ put: function(t) { if ( ! this.findTopic(t.topic) ) this.putTopic(t); }.bind(this) }); } }, { name: 'selected', preSet: function(o, n) { if ( o === n ) return o; var oc = this.findTopic(o); if ( oc ) oc.setSelected(false); var nc = this.findTopic(n); if ( nc && nc.setSelected ) { // Move-to-Front var i = this.findTopicIndex(n); this.children[i] = this.children[this.children.length-1]; this.children[this.children.length-1] = nc; nc.setSelected(true); this.clearTimeout(this.timeout_); this.timeout_ = this.setTimeout(function() { this.selected = null; }.bind(this), nc.topic.timeout * 1000); return n; } return null; } } ], listeners: [ function putTopic(t) { if ( t.topic === this.root ) { if ( this.selected !== t.selected ) this.selected = t.selected; if ( this.dir !== t.dir && ( ! this.root || t.dir ) ) this.dir = t.dir; } if ( ! ( t.parentTopic == this.dir || t.topic == this.dir || ( this.selected && t.topic == this.selected ) ) ) { this.removeTopic(t); return; } // console.log('***** putTopic: ', t.topic); if ( t.model === 'Background' ) { document.body.style.backgroundImage = 'url(' + t.image + ')'; return; } var i = this.findTopicIndex(t.topic); if ( i != -1 ) this.children.splice(i, 1); if ( ! t.enabled ) return; var c = this.X.lookup('com.google.watlobby.' + t.model + 'Bubble').create({ x: Math.random() * this.width, y: Math.random() * this.height, border: t.color, scaleX: 0, scaleY: 0, alpha: 0 }, this.Y); c.topic = t; c.image = t.image; Movement.animate(1000, function() { c.alpha = 1; c.scaleX = c.scaleY = 1; })(); c.roundImage = t.roundImage; // if ( t.color ) c.border = t.color; if ( t.background ) c.color = t.background; this.addChild(c); if ( this.children.length > 1 ) { var cs = this.children; var l = cs.length; var tmp = cs[l-1]; cs[l-1] = cs[l-2]; cs[l-2] = tmp; } c.mass = t.r/150; c.gravity = 0; c.friction = 0.94; this.collider.add(c); }, function removeTopic(t) { var i = this.findTopicIndex(t.topic); if ( i != -1 ) { var child = this.children[i]; Movement.compile([ [ 800, function() { child.alpha = 0; child.scaleX = child.scaleY = 0.1; } ], function() { this.removeChild(child); this.collider.remove(child); }.bind(this) ])(); } } ], methods: [ function initCView() { this.SUPER(); GLOBAL.lobby = this; if ( ! this.timer ) { this.timer = this.Timer.create(); this.timer.start(); } this.addBubbles(); this.topics.pipe({ put: this.putTopic, remove: this.removeTopic }); document.body.addEventListener('click', this.onClick); var foam = this.ImageCView.create({x: 5, y: this.height-5-269/4, width: 837/4, height: 269/4, src: 'img/foampowered_red.png'}); this.addChild(foam); /* var clock = this.ClockView.create({ drawTicks: true, x: this.width-250, y: 250, r: (120-10)/2, scaleX: 4, scaleY: 4}); this.addChild(clock); */ this.collider.start(); if ( this.slideshowDelay ) { var i = 0; var l = function() { var t = this.topics[i++]; this.selected = t; if ( i == this.topics.length ) i = 0; this.X.setTimeout(l, t.hasOwnProperty('timeout') ? t.timeout*1000 : this.slideshowDelay*1000); }.bind(this); l(); } }, function findTopicIndex(t) { for ( var i = 0 ; i < this.children.length ; i++ ) { var c = this.children[i]; if ( c.topic && c.topic.topic === t ) return i; } return -1; }, function findTopic(t) { for ( var i = 0 ; i < this.children.length ; i++ ) { var c = this.children[i]; if ( c.topic && c.topic.topic === t ) return c; } }, function addBubbles() { var N = this.n; for ( var i = 0 ; i < N ; i++ ) { var color = this.COLORS[Math.floor(i / N * this.COLORS.length)]; var c = this.Bubble.create({ r: 10 + Math.random() * 60, x: Math.random() * this.width, y: Math.random() * this.height, color: null, border: color }); this.addChild(c); c.mass = c.r/150; c.gravity = 0; c.friction = 0.94; this.collider.add(c); } }, function openSmallRemoteUI() { var w = foam.ui.Window.create({window: window.open("", "Remote", "width=800, height=600, location=no, menubar=no, resizable=no, status=no, titlebar=no")}); w.document.innerHTML = ''; w.document.write('<html><head><title>Wat Lobby Remote</title></head><body></body></html>'); var r = this.SmallRemote.create({topics: this.topics}, w.Y); r.write(w.Y); }, function openRemoteUI() { var w = foam.ui.Window.create({window: window.open("", "Remote", "width=800, height=600, location=no, menubar=no, resizable=no, status=no, titlebar=no")}); // There's some timing issue that causes the remote to not open if you try to do it immediately after openeing the window. this.X.setTimeout(function() { w.document.innerHTML = ''; w.document.write('<html><head><title>Wat Lobby Remote</title></head><body></body></html>'); var r = this.Remote.create({topics: this.topics}, w.Y); r.write(w.Y); }.bind(this), 200); }, function openAdminUI() { var w = foam.ui.Window.create({window: window.open("", "Admin", "width=1200, height=700, location=no, menubar=no")}); w.document.innerHTML = ''; w.document.write('<html><head><title>Wat Lobby Admin</title><base href="/js/com/google/watlobby/"></head><body></body></html>'); var r = this.TopicApp.create({dao: this.topics}, w.Y); r.write(w.Y); }, function destroy() { this.SUPER(); this.collider.destroy(); } ] });