diff --git a/css/tc.app.css b/css/tc.app.css index c5fa1ec..67c4299 100644 --- a/css/tc.app.css +++ b/css/tc.app.css @@ -3,6 +3,9 @@ body { font-family:Helvetica,Arial,sans-serif;overflow:hidden; font-size:13px; a{ color:#6198bf; } a:visited{ color:#6198bf; } +canvas { visibility: hidden; position:absolute; + top:0px;left:0px; } + .tag { background-image:url('../images/tag5.2.png');background-repeat:no-repeat;color:transparent; position:absolute; top:-10px; left:150px; width:219px;height:100px;z-index:100; } diff --git a/scripts/tc.app.particle.context.canvas.js b/scripts/tc.app.particle.context.canvas.js new file mode 100644 index 0000000..7069329 --- /dev/null +++ b/scripts/tc.app.particle.context.canvas.js @@ -0,0 +1,57 @@ +if(!tc){ var tc = {}; } + +(function(tc) { + if(!tc.particle){ tc.particle = {}; } + if(!tc.particle.context){ tc.particle.context = {}; } + + tc.particle.context.canvas = function(app,dom,options){ + var _me, buffers, drawingBuffer; + _me = dom; + + _me.options = app.Y.merge({ + + },options); + + this.initialize = function(){ + tc.util.log('tc.particle.context.canvas.initialize'); + drawingBuffer = 0; + buffers = dom.getElementsByTagName('canvas')._nodes; + + _me.swap_buffers(); + _me.bounds = _me.options.bounds; + return _me; + } + + _me.draw_particles = function(particles,func,callback){ + var i; + _me.context.clearRect(0,0,_me.bounds.max_x,_me.bounds.max_y); + for(i = 0; i < particles.length; i++){ + if(app.Y.Lang.isFunction(func)){ + func.call(_me,particles[i]); + } + } + _me.swap_buffers(); + if(callback){ + callback(); + } + } + + _me.draw_particle = function(particle,func){ + var i; + //_me.context.clearRect(0,0,_me.bounds.max_x,_me.bounds.max_y); + if(app.Y.Lang.isFunction(func)){ + func.call(_me,particle); + } + } + + _me.swap_buffers = function(){ + buffers[1-drawingBuffer].style.visibility='hidden'; + buffers[drawingBuffer].style.visibility='visible'; + drawingBuffer = 1 - drawingBuffer; + _me.context = buffers[drawingBuffer].getContext('2d'); + } + + return this.initialize(); + } + +})(tc); \ No newline at end of file diff --git a/scripts/tc.app.particle.context.js b/scripts/tc.app.particle.context.js index 7fc5231..e7c6a72 100644 --- a/scripts/tc.app.particle.context.js +++ b/scripts/tc.app.particle.context.js @@ -8,17 +8,16 @@ if(!tc){ var tc = {}; } var _me; _me = dom; - this.options = app.Y.merge({ - framerate:30, - version:0, - gravity:0, - bounds: { - min_x: 0, - max_x: 1000, - min_y: 0, - max_y: 1000 - }, - labels:true + _me.options = app.Y.merge({ + draw:function(particle){ + this.context.fillStyle = _me.fill = "rgba("+tc.util.getRGBFromHex('r','000000')+","+tc.util.getRGBFromHex('g','000000')+","+tc.util.getRGBFromHex('b','000000')+",0.50)"; + this.context.fillRect( + particle.pos[0], + particle.pos[1], + particle.radius*2, + particle.radius*2 + ); + } },options); this.templates = { @@ -27,102 +26,117 @@ if(!tc){ var tc = {}; } this.initialize = function(){ tc.util.log('tc.particle.context.initialize'); - _me.forces = []; - _me.particles = []; - _me.labels = []; - _me.frame = 0; - _me.stopped = true; - _me.paused = false; - _me.timer = null; - _me.mouse_pos = null; - _me.mouse_down_pos = null; - _me.context = _me._node.getContext('2d'); - _me.bounds = this.options.bounds; + + //WebWorker!!!! + if(Worker){ + tc.util.log("Starting WebWorker"); + _me.worker = new Worker('scripts/tc.app.particle.context.worker.js'); + _me.worker.onmessage = function(e){ + _me.workerMessageHandler(e.data); + }; + } else { + tc.util.log("No WebWorker Available"); + _me.worker = new tc.particle.context.worker(app); + app.on('workerEvent') + } + + _me.canvas = new tc.particle.context.canvas(app,dom,_me.options); + + _me.worker.postMessage({ + action:'init', + data:{} + }); + + _me.updateBounds(); return _me; } + _me.workerMessageHandler = function(d){ + if(d.action){ + switch(d.action){ + case 'particleAdded': + tc.util.log('Particle Added'); + break; + case 'forceAdded': + tc.util.log('Force Added'); + break; + case 'particlesUpdated': + _me.canvas.draw_particles(d.data.particles,_me.options.draw,function(){ + + _me.worker.postMessage({ + action:'update' + }); + + }); + break; + case 'particleUpdated': + //_me.canvas.draw_particle(d.data.particle,_me.options.draw); + break; + } + } + } + _me.updateBounds = function(){ tc.util.log('tc.particle.context[_me.updateBounds]'); - _me.bounds = { - min_x: 0, - max_x: _me.get('winWidth'), - min_y: 0, - max_y: _me.get('winHeight') - }; + + _me.worker.postMessage({ + action:'setOption', + data:{ + name:'bounds', + value:{ + min_x: 0, + max_x: _me.get('winWidth'), + min_y: 0, + max_y: _me.get('winHeight') + } + } + }); + } _me.add_particle = function(particle){ //tc.util.log('tc.particle.context[_me.add_particle]'); - _me.particles.push(particle); - return _me.particles[_me.particles.length-1]; - } - - _me.add_global_force = function(pos, strength, radius){ - tc.util.log('tc.particle.context[_me.add_global_force]'); - var force; - if(pos.x && pos.y){ - force = { - pos:Vector.create([pos.x,pos.y]), - strength:strength, - radius:radius - }; - _me.forces.push(force); - return _me.forces[_me.forces.length-1]; - } - } - - _me.update = function(){ - //tc.util.log('tc.particle.context[_me.update]'); - _me.frame++; - if(!_me.stopped){ - for(i = 0; i < _me.particles.length; i++){ - _me.particles[i]['reset_forces'](); - _me.particles[i]['add_forces'](_me.forces); - _me.particles[i]['bounce_off_walls'](_me.bounds); - _me.particles[i]['handle_anchor'](); - //_me.particles[i]['collide_with_particles'](_me.particles,i); - _me.particles[i]['add_damping'](); - _me.particles[i]['update'](); + + _me.worker.postMessage({ + action:'addParticle', + data:{ + particle:particle } - } - _me.mouse_down_pos = null; - _draw(); + }); + } - _me.isPaused = function(){ - tc.util.log('tc.particle.context[_me.isPaused]'); - return _paused; + _me.add_force = function(force){ + tc.util.log('tc.particle.context[_me.add_force]'); + + _me.worker.postMessage({ + action:'addForce', + data:{ + force:force + } + }); + } _me.start = function(){ tc.util.log('tc.particle.context[_me.start]'); - _me.paused = false; - _me.mouse_pos = null; - _me.mouse_down_pos = null; - if(_me.stopped){ - _me.stopped = false; - _me.timer = app.Y.later(1000/30,_me,_me.update,{},true); - } - } - - _me.pause = function(){ - tc.util.log('tc.particle.context[_me.pause]'); - _me.paused = true; + + _me.worker.postMessage({ + action:'start', + data:{} + }); + } _me.stop = function(){ tc.util.log('tc.particle.context[_me.stop]'); - _me.stopped = true; - _me.timer.cancel(); - } - - function _draw(){ - //tc.util.log('tc.particle.context[_me.draw]'); - _me.context.clearRect(0,0,_me.bounds.max_x,_me.bounds.max_y); - for(var i = 0; i < _me.particles.length; i++){ - _me.particles[i].draw(_me.context,this.frame); - } + + _me.worker.postMessage({ + action:'stop', + data:{} + }); + } return this.initialize(); diff --git a/scripts/tc.app.particle.context.worker.js b/scripts/tc.app.particle.context.worker.js new file mode 100644 index 0000000..fdf52f0 --- /dev/null +++ b/scripts/tc.app.particle.context.worker.js @@ -0,0 +1,151 @@ +if(!tc){ var tc = {}; } + +if(typeof Worker != undefined){ + var worker; + if(typeof importScripts != 'undefined'){ + importScripts('lib/includes.sylvester.src.js'); + importScripts('tc.app.particle.particle.js'); + } +} else { + var onmessage; +} + +onmessage = function(e){ + if(e.data && e.data.action){ + switch(e.data.action){ + case 'init': + worker = new tc.particle.context.worker(); + break; + case 'setOption': + worker.set_option(e.data.data.name,e.data.data.value); + break; + case 'addParticle': + worker.add_particle(e.data.data.particle); + break; + case 'addForce': + worker.add_force(e.data.data.force); + break; + case 'update': + worker.update(); + break; + case 'start': + worker.start(); + break; + case 'stop': + worker.stop(); + break; + } + } +}; + +(function(tc) { + if(!tc.particle){ tc.particle = {}; } + if(!tc.particle.context){ tc.particle.context = {}; } + + tc.particle.context.worker = function(app){ + var _me, interval; + _me = this; + + this.options = { + framerate:30, + version:0, + gravity:0, + bounds: { + min_x: 0, + max_x: 1000, + min_y: 0, + max_y: 1000 + }, + labels:true + } + + this.templates = { + label: "

" + } + + this.initialize = function(){ + //tc.util.log('tc.particle.context.initialize'); + _me.forces = {}; + _me.particles = []; + _me.particles.get = function(){ + var i,arr; + arr = []; + for(i = 0; i < this.length; i++){ + arr.push(this[i].get()); + } + return arr; + } + return _me; + } + + //to handle incoming messages when not a WebWorker + _me.postMessage = function(d){ + onmessage({data:d}); + } + + _me.set_option = function(name,value){ + _me.options[name] = value; + } + + _me.start = function(){ + if(interval){ + clearInterval(interval); + } + //interval = setInterval(_me.update,1000/60); + _me.update(); + } + + _me.stop = function(){ + if(interval){ + clearInterval(interval); + interval = null; + } + } + + _me.add_particle = function(particle){ + var p; + p = new tc.particle.particle(particle); + + _me.particles.push(p); + + postMessage({ + message:'particleAdded' + }); + + } + + _me.add_force = function(force){ + force.pos = Vector.create([force.pos.x,force.pos.y]); + _me.forces[force.id] = force; + + postMessage({ + message:'forceAdded', + forceId:force.id + }); + } + + _me.update = function(){ + //tc.util.log('tc.particle.context[_me.update]'); + _me.frame++; + for(i = 0; i < _me.particles.length; i++){ + _me.particles[i]['reset_forces'](); + _me.particles[i]['add_forces'](_me.forces); + //_me.particles[i]['bounce_off_walls'](_me.bounds); + _me.particles[i]['handle_anchor'](); + //_me.particles[i]['collide_with_particles'](_me.particles,i); + _me.particles[i]['add_damping'](); + _me.particles[i]['update'](); + } + + postMessage({ + action:'particlesUpdated', + data:{ + particles:_me.particles.get() + } + }); + } + + return this.initialize(); + } + +})(tc); \ No newline at end of file diff --git a/scripts/tc.app.particle.panel.js b/scripts/tc.app.particle.panel.js index 4c29da1..548361e 100644 --- a/scripts/tc.app.particle.panel.js +++ b/scripts/tc.app.particle.panel.js @@ -7,7 +7,10 @@ if(!tc){ var tc = {}; } var _me, _domRef, _context, mouseforce; _me = this; - this.template = ""; + this.template = "
\ + \ + \ +
"; this.initialize = function(){ tc.util.log('particle.panel.initialize'); @@ -24,7 +27,7 @@ if(!tc){ var tc = {}; } ax = ( 200 + sq.x ); ay = ( sq.y ); - _context.add_particle(new tc.particle.particle(app,{ + _context.add_particle({ pos:{ x:tc.util.rand(0,_domRef.get('winWidth')), y:tc.util.rand(0,_domRef.get('winHeight')) @@ -34,17 +37,8 @@ if(!tc){ var tc = {}; } anchor:{ x:ax, y:ay - }, - draw:function(context,frame){ - context.fillStyle = this.fill; - context.fillRect( - this.pos.elements[0], - this.pos.elements[1], - this.options.radius*2, - this.options.radius*2 - ); } - })); + }); })(arr[i]); } } @@ -55,6 +49,8 @@ if(!tc){ var tc = {}; } if(!selector){ selector = app.selector; } app.Y.one(selector).append(_me.template); _domRef = app.Y.one("#particle-panel"); + _domRef.getElementsByTagName('canvas').set("width",_domRef.get('winWidth')); + _domRef.getElementsByTagName('canvas').set("height",_domRef.get('winHeight')); _domRef.set("width",_domRef.get('winWidth')); _domRef.set("height",_domRef.get('winHeight')); @@ -74,7 +70,15 @@ if(!tc){ var tc = {}; } }); _context.start(); - mouseforce = _context.add_global_force({x:500,y:500},-6,150); + _context.add_force({ + id:'mouseforce', + pos:{ + x:500, + y:500 + }, + strength:-3, + radius:200 + }); return _me; @@ -85,7 +89,6 @@ if(!tc){ var tc = {}; } for(j = 0; j < 15; j++){ ax = ( (_domRef.get('winWidth')/2-100) + (i * 12) ); ay = ( (_domRef.get('winHeight')/2-100) + (j * 12) ); - _context.add_particle(new tc.particle.particle(app,{ pos:{ x:tc.util.rand(0,_domRef.get('winWidth')), @@ -110,6 +113,8 @@ if(!tc){ var tc = {}; } } })(); + + return _me; } diff --git a/scripts/tc.app.particle.particle.js b/scripts/tc.app.particle.particle.js index 87763aa..48d169c 100644 --- a/scripts/tc.app.particle.particle.js +++ b/scripts/tc.app.particle.particle.js @@ -3,7 +3,7 @@ if(!tc){ var tc = {}; } (function(tc) { if(!tc.particle){ tc.particle = {}; } - tc.particle.particle = function(app,options){ + tc.particle.particle = function(options){ var _me, o, damping; _me = this; @@ -11,7 +11,7 @@ if(!tc){ var tc = {}; } vel, frc; - this.options = app.Y.merge({ + _me.options = { pos:{x:0,y:0}, vel:{x:0,y:0}, frc:{x:0,y:0}, @@ -29,7 +29,14 @@ if(!tc){ var tc = {}; } opacity:0.75, attraction_coefficient: 1.0, data:{} - },options); + }; + + (function(){ + var i; + for(i in options){ + _me.options[i] = options[i]; + } + })(); o = this.options; @@ -42,11 +49,6 @@ if(!tc){ var tc = {}; } _me.anchor = Vector.create([o.anchor.x,o.anchor.y]); } _me.hovered = false; - if(_me.options.opacity < 1.0){ - _me.fill = "rgba("+tc.util.getRGBFromHex('r',o.color)+","+tc.util.getRGBFromHex('g',o.color)+","+tc.util.getRGBFromHex('b',o.color)+","+o.opacity+")" - } else { - _me.fill = "#"+o.color - } } _me.worker = function(new_worker){ @@ -103,8 +105,8 @@ if(!tc){ var tc = {}; } } _me.add_forces = function(forces){ - var distance, length, pct, normal_distance; - for(var i = 0; i < forces.length; i++){ + var i,distance, length, pct, normal_distance; + for(i in forces){ distance = _me.pos.subtract(forces[i].pos); length = Math.sqrt(distance.dot(distance)); if(length < forces[i].radius){ @@ -225,10 +227,13 @@ if(!tc){ var tc = {}; } last_pos = _me.pos; } - _me.draw = function(context){ - if(app.Y.Lang.isFunction(this.options.draw)){ - this.options.draw.call(_me,context); + _me.get = function(){ + var me; + me = { + pos:[_me.pos.elements[0],_me.pos.elements[1]], + radius:o.radius } + return me; } return this.initialize();