Mercurial > MadButterfly
view nodejs/mbapp.js @ 1477:e217c7743905
Make FSM button radio
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Sun, 24 Apr 2011 21:09:37 +0800 |
parents | b916bb0dc7ca |
children |
line wrap: on
line source
// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- // vim: sw=4:ts=8:sts=4 var mbfly = require("mbfly"); var svg = require("./svg"); var sys = require("sys"); var ldr = mbfly.img_ldr_new("."); var component = require("./component"); function _reverse(m1) { var rev = new Array(1, 0, 0, 0, 1, 0); var m = new Array(m1[0], m1[1], m1[2], m1[3], m1[4], m1[5]); rev[3] = -m[3] / m[0]; m[3] = 0; m[4] += rev[3] * m[1]; m[5] += rev[3] * m[2]; rev[1] = -m[1] / m[4]; rev[0] += rev[1] * rev[3]; m[1] = 0; m[2] += rev[1] * m[5]; rev[2] = -m[2]; rev[5] = -m[5]; rev[0] = rev[0] / m[0]; rev[1] = rev[1] / m[0]; rev[2] = rev[2] / m[0]; rev[3] = rev[3] / m[4]; rev[4] = rev[4] / m[4]; rev[5] = rev[5] / m[4]; return rev; } function _decorate_mb_rt(mb_rt) { var coord; mb_rt._mbapp_saved_coord_new = mb_rt.coord_new; mb_rt.coord_new = function(parent) { var coord; coord = this._mbapp_saved_coord_new(parent); coord.type = "coord"; coord.children = []; coord._mbapp_saved_mtx = [coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]]; coord._mbapp_saved_rev_mtx = _reverse(coord._mbapp_saved_mtx); coord.parent = parent; coord._mbapp_saved_add_shape = coord.add_shape; coord._mbapp_saved_clone_from_subtree = coord.clone_from_subtree; coord.add_shape = function(shape) { var coord; this._mbapp_saved_add_shape(shape); shape.parent = this; this.children.push(shape); } coord.clone_from_subtree = function(c) { var newcoord = this._mbapp_saved_clone_from_subtree(c); newcoord.parent = this; this.children.push(newcoord); // FIXME: This is incorrect. However, we have no way to fix it for now. // We need to implement a function which can get coord for a coord_t. newcoord.children=c.children; return newcoord; } parent.children.push(coord); return coord; }; /* * Decorate root coord */ coord = mb_rt.root; coord.type = "coord"; coord.children = []; coord._mbapp_saved_mtx = [coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]]; coord._mbapp_saved_rev_mtx = _reverse(coord._mbapp_saved_mtx); coord._mbapp_saved_add_shape = coord.add_shape; coord._mbapp_saved_clone_from_subtree = coord.clone_from_subtree; coord.add_shape = function(shape) { var coord; this._mbapp_saved_add_shape(shape); shape.parent = this; } coord.clone_from_subtree = function(c) { var newcoord; newcoord = this._mbapp_saved_clone_from_subtree(c); newcoord.parent = this; this.children.push(newcoord); // FIXME: This is incorrect. However, we have no way to fix it for now. // We need to implement a function which can get coord for a coord_t. newcoord.children=c.children; return newcoord; } } app=function(display, w, h) { var self = this; var mb_rt; if(typeof display == "undefined") display = ":0.0"; if(typeof w == "undefined") w = 720; if(typeof h == "undefined") h = 480; mb_rt = this.mb_rt = new mbfly.mb_rt(display, w, h); _decorate_mb_rt(mb_rt); var background = mb_rt.rect_new(0, 0, 720, 480, 0, 0); var paint = mb_rt.paint_color_new(1, 1, 1, 1); paint.fill(background); mb_rt.root.add_shape(background); this.mb_rt.kbevents.add_event_observer(exports.EVT_KB_PRESS, function(evt) { self.KeyPress(evt);}); this.keymap={}; this.onKeyPress = null; this.svg = new svg.loadSVG(this.mb_rt,this.mb_rt.root,null); this.frame_interval = 1000/12; // 12 frame per second this.timer = null; this._time = Date.now(); this._componentmanager = new component.ComponentManager(this); } app.prototype.setFrameRate=function(fps) { this.frame_interval = 1000/fps; } app.prototype.ts=function(m) { var now = Date.now(); var t = now-this._time; sys.puts("["+t+"] "+m); } app.prototype.loadSVG=function(fname) { this.svg.load(this.mb_rt,this.mb_rt.root,fname); this.changeScene(0); } app.prototype.KeyPress = function(evt) { if (this.onKeyPress) this.onKeyPress(evt.sym); sys.puts(this.keymap); if (evt.sym in this.keymap) { this.keymap[evt.sym](); } } app.prototype.loop=function() { this.mb_rt.redraw_all(); this.mb_rt.flush(); } app.prototype.update=function() { this.mb_rt.redraw_all(); this.mb_rt.flush(); } app.prototype.get=function(name) { return this.mb_rt.mbnames[name]; } app.prototype.getComponent=function(name) { var comp = new component.Component(this,name); this._componentmanager.dump(); comp.realize(); sys.puts("Search for "+name); var obj = comp.toCoord(); return comp; } app.prototype.addKeyboardListener=function(type,f) { return this.mb_rt.kbevents.add_event_observer(type,f); } app.prototype.refresh=function() { this.mb_rt.redraw_changed(); //this.mb_rt.redraw_all(); this.mb_rt.flush(); } app.prototype.dump=function() { sys.puts(this.onKeyPress); } app.prototype.addKeyListener=function(key,f) { if (typeof(key) == 'number') this.keymap[key] = f; else { for(k in key) { this.keymap[k] = f; } } } app.prototype.generateScaleTween=function(src,dest,p) { sys.puts("p="+ p); src.hide(); // Duplicate the group var nodes = src.children; //if (src.dup) { // src.dup.remove(); // src.dup = null; //} if (src.dup == null) { var dup = this.mb_rt.coord_new(src.parent); for (i in nodes) { var c = nodes[i]; var k = dup.clone_from_subtree(c); c.dup = k; c.dup.id = c.id; c.dup.refid = c.refid; // The following code should be relocated to the javascript wrapper // the clone_from_subtree in the future. try { k.bbox = c.bbox; k.bbox.owner = k; } catch(e) { } try { k.center = c.center; k.center.owner = c.owner; } catch(e) { } } src.dup = dup; } else { dup = src.dup; src.dup.show(); } //dup.hide(); //dest.hide(); //sys.puts(dup); for(i in nodes) { coord= nodes[i]; if (coord.target) { this._componentmanager.add(coord,coord.dup); this.generateScaleTweenObject(coord.dup,coord,coord.target,p,''); } else { sys.puts(coord.id); sys.puts(coord[0]); sys.puts(coord[1]); sys.puts(coord[2]); sys.puts(coord[3]); sys.puts(coord[4]); sys.puts(coord[5]); } } } function printcoord(s) { sys.puts(s[0]+" "+s[1]+" "+s[2]+" "+s[3]+" "+s[4]+" "+s[5]); } function mul(a,b) { return [a[0]*b[0]+a[1]*b[3], a[0]*b[1]+a[1]*b[4], a[0]*b[2]+a[1]*b[5]+a[2], a[3]*b[0]+a[4]*b[3], a[3]*b[1]+a[4]*b[4], a[3]*b[2]+a[4]*b[5]+a[5]]; } app.prototype.generateScaleTweenObject=function(coord,src,dest,p,id) { //sys.puts("xxxxxxx"); //sys.puts("dest="+dest); sys.puts("src=["+src.sx+","+src.sy+","+src.r+","+src.tx+","+src.ty); sys.puts("id="+id+" dest=["+dest.sx+","+dest.sy+","+dest.r+","+dest.tx+","+dest.ty); //sys.puts("src.center="+src.center); //sys.puts("src.center.x="+src.center.x+" src.center.y="+src.center.y); if (src == null) return; var p1 = 1-p; var x1 = src.center.x; var y1 = src.center.y; var y1 = 0; x1 = 0; // For the svg:use, the transform matrix is the transform of teh svg:use and the elements inside it var d,sx,sy,r,tx,ty; sx = src.sx*p+dest.sx*p1; sy = src.sy*p+dest.sy*p1; r = src.r*p+dest.r*p1; tx = src.tx*p+dest.tx*p1; ty = src.ty*p+dest.ty*p1; var mt = [1, 0, -x1, 0, 1, -y1]; var opacity; var ms; opacity = src.opacity*p1 + dest.opacity*p; coord.opacity = opacity; if (r == 0) { m = mt; } else { ms= [Math.cos(r), Math.sin(r),0,-Math.sin(r), Math.cos(r),0]; m = mul(ms,mt); } m = mul([sx,0,0,0,sy,0],m); m = mul([1,0,x1,0,1,y1],m); m = mul([1,0,tx,0,1,ty],m); //m[2] = -m[2]; coord[0] = m[0]; coord[1] = m[1]; coord[2] = m[2]; coord[3] = m[3]; coord[4] = m[4]; coord[5] = m[5]; //sys.puts("id="+id+" src.tx="+src.tx+" src.ty="+src.ty+" tx="+tx+" ty="+ty+" r="+r+" x1="+x1+" y1="+y1+" p="+p+" "+m[0]+","+m[1]+","+m[2]+","+m[3]+","+m[4]+","+m[5]); } app.prototype.changeScene=function(s) { var nth; sys.puts(s); sys.puts(typeof(s)); if (typeof(s)=='number') { var i; nth = s; } else { nth = this.svg.getFrameNumber(s); if (nth == -1) return; } this.ts("goto to scene "+nth); this.currentScene = nth; var scenes = this.svg.scenes; if (scenes == null) return; for(i=0;i<scenes.length-1;i++) { try { this.get(scenes[i].ref).hide(); if (nth >=scenes[i].start && nth <=scenes[i].end) { //this.get(scenes[i].ref).show(); if (this.get(scenes[i].ref).dup) this.get(scenes[i].ref).dup.show(); if (scenes[i].type == 'normal' || i == scenes.length-1) { this.get(scenes[i].ref).show(); } else if (scenes[i].type == 'scale') { if (scenes[i].end == (scenes[i+1].start-1)) { var p = 1-(nth-scenes[i].start)/(scenes[i].end-scenes[i].start+1); this.generateScaleTween(this.get(scenes[i].ref),this.get(scenes[i+1].ref),p); } else { // If there is no second key frame defined, fall back to the normal this.get(scenes[i].ref).show(); } //this.get(scenes[i+1].ref).hide(); } } else { this.get(scenes[i].ref).hide(); if (this.get(scenes[i].ref).dup) this.get(scenes[i].ref).dup.hide(); } } catch(e) { sys.puts(e); sys.puts(scenes[i].ref); } } this.get(scenes[i].ref).hide(); this.ts("refresh"); this.refresh(); this.ts("refresh done"); } app.prototype.runToScene=function(s) { if (typeof(s)=='number') { var i; nth = s; } else { nth = this.svg.getFrameNumber(s); if (nth == -1) return; } var self = this; sys.puts(this.currentScene+","+nth); if (nth > this.currentScene) { this.skipdir = 1; } else { this.skipdir = -1; } this.targetScene = nth; this.startScene = this.currentScene; this.starttime = Date.now(); if (this.timer == null) { this.skipFrame(); } } app.prototype.skipFrame=function() { var self = this; if (this.currentScene != this.targetScene) { var now = Date.now(); var step = Math.round((now - this.starttime)/this.frame_interval)*this.skipdir; nextframe = this.startScene + step //nextframe = this.currentScene + this.skipdir; this.ts("goto begin"); if (this.skipdir>0) { if (nextframe > this.targetScene) nextframe = this.targetScene; } else { if (nextframe < this.targetScene) nextframe = this.targetScene; } this.changeScene(nextframe); if (nextframe != this.targetScene) { var timegap = this.frame_interval - (Date.now()-now); if (timegap < 0) timegap = 0; this.timer = setTimeout(function() { self.skipFrame() }, timegap ); } else { this.timer = null; } now = Date.now(); this.ts("goto end"); } } app.prototype.addSceneListener=function(n, cb) { sys.puts("This is not implemented yet") } var app_with_win = function(display, win) { var self = this; var mb_rt; var background; var paint; if(typeof display == "undefined" || typeof win == "undefined") throw "Invalid argument"; mb_rt = this.mb_rt = new mbfly.mb_rt_with_win(display, win); _decorate_mb_rt(mb_rt); background = mb_rt.rect_new(0, 0, 720, 480, 0, 0); paint = mb_rt.paint_color_new(1, 1, 1, 1); paint.fill(background); mb_rt.root.add_shape(background); this.mb_rt.kbevents. add_event_observer(exports.EVT_KB_PRESS, function(evt) { self.KeyPress(evt); }); this.keymap = {}; this.onKeyPress = null; } app_with_win.prototype = app.prototype; exports.app=app; exports.app_with_win = app_with_win; // Put all key definition here exports.KEY_LEFT = 0xff51; exports.KEY_UP = 0xff52; exports.KEY_RIGHT = 0xff53; exports.KEY_DOWN = 0xff54; exports.KEY_ENTER = 0xff0d; exports.EVT_ANY=0; exports.EVT_MOUSE_OVER=1; exports.EVT_MOUSE_OUT=2; exports.EVT_MOUSE_MOVE=3; exports.EVT_MOUSE_BUT_PRESS4; exports.EVT_MOUSE_BUT_RELEASE=5 exports.EVT_KB_PRESS=6; exports.EVT_KB_RELEASE=7; exports.EVT_PROGM_COMPLETE=8; exports.EVT_RDMAN_REDRAW=9; exports.EVT_MONITOR_ADD=10; exports.EVT_MONITOR_REMOVE=11; exports.EVT_MONITOR_FREE=12; exports.EVT_MOUSE_MOVE_RAW=13; exports.ldr = ldr;