/*
~=~ SEGUNDA -> just another Javascript game framework <- ~=~
status: working hard

- to-do
  - fix ui detection bug seen during resizing
    (check sebastian.it horizontal scrollbar [open/close firebug console])
  - trovare metodo per applicare collision detection su
    altro livello di griglia così come avviene in pacman
    la collision detection viene fatta su una griglia che
    ha coordinate diverse rispetto a quelle utilizzate per
    il posizionamento dei tiles..
    usare photoshop per verifiche...
  - correggere problema pixel cannati in rotazione sprites..
    vedi editor
  - se metto cursore su tile editor su sprite automaticamente
    si accendono tutte le versioni dello sprite > ruotate
  - utilizzare viola per creare blocchi di sprite durante cattura
  (
   questo faciliterebbe enormemente definzione animazioni che
   possono essere fatte tranquillamente in photoshop
  )
  e poi rendere trasparente in run-time

- cooking...
  physics: (will be introduced on bubble bobble conversion)
    learning:
    http://chrishecker.com/Rigid_Body_Dynamics
    http://chrishecker.com/Physics_References
    examples
    http://www.blitzbasic.com/codearcs/codearcs.php?code=415
    http://www.blitzbasic.com/codearcs/codearcs.php?code=998
    http://www.gamedev.net/community/forums/topic.asp?topic_id=482402
    http://gpwiki.org/index.php/VB:Tutorials:Building_A_Physics_Engine:Basic_Intersection_Detection
    
    exile:
    http://www.violator.eclipse.co.uk/Exile/
  
    box2d javascript
    http://box2d-js.sourceforge.net/
    box2d
    http://www.box2d.org/
    box2d flash
    http://box2dflash.sourceforge.net/ <- flash 2d
    box2d+paperbox
    http://www.lamberta.org/blog/paperbox2d/ <- flash 3d

- rivals:
  GMP
  http://gogomakeplay.com/blog/gmp-game-engine-is-now-free

- related:
  20090720 Nice javascript games from Mr. Speaker
  http://www.mrspeaker.net/2009/07/12/more-javascript-madness/
  Tom's Halls - A JavaScript Platform Game Engine
  http://www.codeproject.com/KB/scripting/TomsHallsJavascriptGame.aspx
  game development with javascript and canvas
  http://www.brighthub.com/hubfolio/matthew-casperson/blog/archive/2009/06/29/game-development-with-javascript-and-the-canvas-element.aspx
  From same author: the demo
  http://www.chromeexperiments.com/detail/game-development-with-javascript-and-the-canvas-element/
  google accepts your experiments with chrome and eventualy publish them
  http://www.chromeexperiments.com

  Javascript gaming
  http://www.javascriptgaming.com/
  Nihilogic
  http://blog.nihilogic.dk/
  phun
  http://www.phunland.com/wiki/Home
  doodle
  http://www.lamberta.org/blog/doodle/

- TODO:

aggiungere window scroll a posizione...
per verificare attivare map edit
e fare zoom

se spostiamo scrollbar di finestra pincipale la detezione di proccessevents falliscceeeeee di brutto

- for any comment or question segunda@sebastian.it
- set your text editor tab size to 2 fro proper viewing
- direct url: http://www.sebastian.it/wordpress/wp-content/themes/revolucion/javascript/segunda.js 

to-do:

_firingEvent di ui processevents mi sa che non serve più

add replace color to sprite cloning??
http://www.permadi.com/tutorial/jsCanvasGrayscale/index.html

ok: 20090302
    map editor dovrebbe fare a meno dei div ed utilizzare oggetti



papervision
http://www.emanueleferonato.com/2009/06/14/papervision3d-understanding-plane-object-%E2%80%93-part-6/
http://www.emanueleferonato.com/triqui-mochiads-arcade-theme-for-wordpress-official-page/


other game engines and game coders
nihilogic - mad js game scientist
  digg attack
  http://blog.nihilogic.dk/2008/11/digg-attack-javascript-game.html
  super mario
  http://blog.nihilogic.dk/2008/04/super-mario-in-14kb-javascript.html
  blog
  http://blog.nihilogic.dk/
  canvas png compression
  http://ajaxian.com/archives/compression-using-canvas-and-png
  
javascript gaming from nihilogic
http://www.javascriptgaming.com/
  
  getimage data source securityu problem
  http://www.webdeveloper.com/forum/showthread.php?t=188021
  
  pacman with javafx
  http://www.insideria.com/2009/05/writing-the-pac-man-game-in-ja-2.html
  
  canvas for ie
  http://groups.google.com/group/google-excanvas
  
  mozilla developer tutorials
  https://developer.mozilla.org/En/Canvas_tutorial/Using_images
  https://developer.mozilla.org/En/Canvas_tutorial/Basic_animations
  https://developer.mozilla.org/En/Canvas_tutorial/Using_images
  https://developer.mozilla.org/samples/canvas-tutorial/2_1_canvas_rect.html
  
  
  wordpress tools
  http://lesterchan.net/portfolio/programming/php/
  
gogo js game framwork - nice but complex and cpu intensive
  http://gogomakeplay.com/wp-content/downloads/gmp-engine.1.7.2.js
  gogopop
  http://gogomakeplay.com/games/gogopop
  
*/

var Segunda=function(){ //we start by defining our main object, it will include all objects required to build our game logic
  /*
  function Welcome to SEGUNDA //let the editor source tree grab the classes
  */
  //constants
  var _VERSION='1.4.4';
  var _DEBUG=0;
  var _DEBUG2=0;
  var _INTERVAL=20;//20;//20; //main application event loop dispatch interval (in ms) default: 50
  //private singleton init
  /*
  function Timer - Global Application timer //let the editor source tree grab the classes
  */
  var Timer=function() { // a simple timer object
    return {
      //object methods and properties init
      define:function(o) { //parameters i:interval, f:function
        var _repeat=0;
        //var _cycles=0;
        var _ff;
        var _i;
        
        if (typeof o.repeat!='undefined')
          _ff=function(){_repeat++;if (_repeat<=o.repeat)o.f()}//_ff=function(){_cycles++;_repeat++;if (_repeat<=o.repeat)o.f()}
        else
          _ff=o.f;//_ff=function(){_cycles++;o.f()};
        
        _i=setInterval(_ff,o.interval);
        return {
          /*
          getCycles:function() {
            return _cycles
          },
          */
          getInterval:function() {
            return o.interval;
          },
          pause:function() { //pause the timer
            clearInterval(_i);
            _i=null;
          },
          stop:function() {//just a pause alias
            this.pause();
          },
          play:function(iInterval) { //start the timer
            if (!_i) {
              if (typeof iInterval=='undefined')
                _i=setInterval(_ff,o.interval);
              else {
                _i=setInterval(_ff,iInterval);
                o.interval=iInterval; //set new timing
              }
            }  
          },
          set:function(iInterval) {
            this.stop();
            this.play(iInterval);
          }
        }
      },
      run:function(o) { //just set a timeout
        setTimeout(o.f,o.interval)
      }  
      //object methods and properties end
    }
  }();
  //private singleton end

  //internal object initialization init
  var SegundaTimer=Timer.define({
    interval:_INTERVAL,
    f:function(){Segunda.Ui.processEvents();Segunda.Animator.processAnimations()} //declare as a function so Segunda.Ui.processEvents() is evaluated after Segunda object is defined
  });
  //internal object initialization end

  
  return {
    //singleton init
    debug:_DEBUG||_DEBUG2, //invoke application debug
    Clock:SegundaTimer, //the main application clock event listener. We can pause the whole app by invoking the clock.pause or stop method - , all events are processed by this timer that listens to all events (mouse and keyboard)
    /*
    function UI - User interface//let the editor source tree grab the classes
    */
    Timer:Timer, //expose the timer object,    
    Ui:function() { //user interface
      var _keys={
        downList:[],
        trapList:[],
        listenerInterval:1
      }
      //init some keys > down
      _keys.downList['CNTRL']=0;
      _keys.downList['SHIFT']=0;
      _keys.downList['ALT']=0;
      
      //var _windows=[]; //windows-> elements -> fixme..
      var _nElements=0;
      var _wins=[];
      //var _nWindowsElements=[];
      var _elements=[]; //id indexed array
      var _plainElements=[]; //flat array for faster cycling
      var _key_listener_counter=0;
      var _firingEvent=false;
      //var _keys_up=[];
      var _mouseButton=null;
      var _wheelDelta=null;
      var _clickedX,_clickedY=null;
      var _mousePressed;
      var _e={};

/*
      var _detectedKeys=[];      
      var _validKeys=[
        'DEL','SHIFT','ALT','CNTRL','CAPS_LOCK','SPACE','PAGE_UP','PAGE_DOWN','END','LEFT','UP','RIGHT','DOWN',
        'INS','CANC','WINDOWS_LEFT','WINDOWS_RIGHT','0','+','-','F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12'
      ];
      var _keyCodes=[8,16,18,17,20,32,33,34,35,37,18,39,40,45,46,91,92,96,107,109,112,113,114,115,116,117,118,119,120,121,122,123];
      for (var z=0;z<_keyCodes.length;z++) {
        //console.log(_keyCodes[z]);
        _detectedKeys[_keyCodes[z]+'']==_validKeys[z];
      }
      //console.dir(_detectedKeys);
*/

      /*
      ConvertKeyStrokes : function(){
      */         
      var getKeyIndex=function(iKeyCode) {
        var keyIdx=iKeyCode;//String.fromCharCode(iKeyCode);
/*
        console.log(iKeyCode+' ',_detectedKeys[iKeyCode+'']);
        if (typeof _detectedKeys[iKeyCode+'']!='undefined')
          keyIdx=_detectedKeys[iKeyCode+''];
*/
//        /*
        switch(iKeyCode) {
          case 8:  keyIdx='DEL';break;
          case 13: keyIdx='ENTER';break;
          case 16: keyIdx='SHIFT';break;
          case 18: keyIdx='ALT';break;
          case 17: keyIdx='CNTRL';break;
          case 20: keyIdx='CAPS_LOCK';break;
          case 32: keyIdx='SPACE';break;
          case 33: keyIdx='PAGE_UP';break;
          case 34: keyIdx='PAGE_DOWN';break;
          case 35: keyIdx='END';break;
          case 37: keyIdx='LEFT';break;
          case 38: keyIdx='UP';break;
          case 39: keyIdx='RIGHT';break;
          case 40: keyIdx='DOWN';break;
          case 45: keyIdx='INS';break;
          case 46: keyIdx='CANC';break;
          case 91: keyIdx='WINDOWS_LEFT';break;
          case 92: keyIdx='WINDOWS_RIGHT';break;
          case 96: keyIdx='0';break;
          //WITH CAPS LOCK ON  
          case 97: keyIdx='KEYPAD_1';break;
          case 98: keyIdx='KEYPAD_2';break;
          case 99: keyIdx='KEYPAD_3';break;
          case 100:keyIdx='KEYPAD_4';break;
          case 101:keyIdx='KEYPAD_5';break;
          case 102:keyIdx='KEYPAD_6';break;
          case 103:keyIdx='KEYPAD_7';break;
          case 104:keyIdx='KEYPAD_8';break;
          case 105:keyIdx='KEYPAD_9';break;
          case 110:keyIdx='KEYPAD_DOT';break;
          case 106:keyIdx='KEYPAD_ASTERISK';break;
          //WITH CAPS LOCK ON  
          case 107:keyIdx='+';break;
          case 109:keyIdx='-';break;
          case 112:keyIdx='F1';break;
          case 113:keyIdx='F2';break;
          case 114:keyIdx='F3';break;
          case 115:keyIdx='F4';break;
          case 116:keyIdx='F5';break;
          case 117:keyIdx='F6';break;
          case 118:keyIdx='F7';break;
          case 119:keyIdx='F8';break;
          case 120:keyIdx='F9';break;
          case 121:keyIdx='F10';break;
          case 122:keyIdx='F11';break;
          case 123:keyIdx='F12';break;
          //default:keyIdx=String.fromCharCode(keyIdx);break;
        }
//       */
        return keyIdx;
      }
      /*
      windowResizeTrapper : function(){
      */  
      var resizeTrapper=function(e) {
        _e=e;
        _e.resizeEvent=1;
        _e.clickedX=_clickedX;
        _e.clickedY=_clickedY;
      }        
      /*
      mouseTrapper : function(){
      */  
      var mouseTrapper=function(e) {
        if (!_firingEvent) {
          _e=e;
          _e.mouseMove=1;
          _e.mouseButton=_mouseButton;
          _e.wheelDelta=e.detail;
          _e.clickedX=_clickedX;
          _e.clickedY=_clickedY;
          _e.mousePressed=_mousePressed;
        }  
      }
      /*
      mouseWheelTrapper : function(){
      */        
      var mouseTrapperWheel=function(e) {
        //http://www.napolux.com/2006/gestione-della-rotella-del-mouse-in-javascript.html
        _wheelDelta=e.detail;
        _e.wheelDelta=e.detail;
        if (typeof _e.wheelDeltaCounter=='undefined')
          _e.wheelDeltaCounter=0;
        _e.wheelDeltaCounter++; 
        //console.log(e.detail);
        return false; 
      }
      /*
      mouseDownTrapper : function(){
      */         
      var mouseTrapperDown=function(e) {
        _mouseButton=e.button; //button - thanks: https://developer.mozilla.org/en/DOM/event.button, https://developer.mozilla.org/En/DOM:event
        _e.mouseButton=_mouseButton;
        _mousePressed=1;
        _e.mousePressed=_mousePressed;
        _clickedX=_e.clickedX=_e.clientX;
        _clickedY=_e.clickedY=_e.clientY;
      }
      /*
      mouseUpTrapper : function(){
      */        
      var mouseTrapperUp=function(e) {
        _mouseButton=null;
        _e.mouseButton=_mouseButton;
        //_e.clickedX=null;
        //_e.clickedY=null;
      }
      /*
      keyboardTrapper : function(){
      */               
      var keyboardTrapperKeyDown=function(e) {
        //console.log(e.which+' '+String.fromCharCode(e.which)); //debug keys
        var keyIdx=getKeyIndex(e.which);
        //console.log(keyIdx);
        if (keyIdx==parseInt(keyIdx))
          keyIdx=String.fromCharCode(keyIdx);
        //console.log(keyIdx);
        _keys.downList[keyIdx]=1;
        if (_keys.trapList[keyIdx]) //automatically trap used app keys
          return false;
        return 1;
      }        
      var keyboardTrapperKeyUp=function(e) {
        var keyIdx=getKeyIndex(e.which);
        if (keyIdx==parseInt(keyIdx))
          keyIdx=String.fromCharCode(keyIdx);
        _keys.downList[keyIdx]=0;
        //_keys_up[keyIdx]=1;
      }
      
      var _UIparseData=function(o) {
        var s=o.s;
        var uiParent=o.element.uiParent;
        var ele=o.element;
        if (typeof s=='string') {
          s=s.replace('PARENT_WIDTH',uiParent.offsetWidth);
          s=s.replace('PARENT_HEIGHT',uiParent.offsetHeight);
          s=s.replace('PARENT_LEFT',uiParent.offsetLeft);
          s=s.replace('PARENT_TOP',uiParent.offsetTop);
          s=s.replace('OBJECT_WIDTH',ele.dom.offsetWidth);
          s=s.replace('OBJECT_HEIGHT',ele.dom.offsetHeight);
          //console.log(s);
          s=eval(s);
        }
        return s;
      }

      /*
      UIMoveObject : function(){
      */         
      var _UIMoveObject=function(ele,_e,o) {
                        
        var u=Segunda.Utils;//shortcut
        
        if (u.undef(o))
          o={};
        
        if (!ele.dragging)
          Segunda.Event.launch({element:ele,userEvent:ele.onDragStart,event:_e,data:['Ui > processEvents > ele.onDragStart error','ele:',ele]});
  
        ele.dragging=1;
        
        var xx=(_e.clientX-ele.clickedX);
//FIXME - ERROR WHILE DRAGGING WINDOWS AND SCROLLBARS ARE ON
//        var sL=document.documentElement.scrollLeft?document.documentElement.scrollLeft:document.body.scrollLeft;
        //if (ele.isWindowObject)
//        xx-=window.pageXOffset;//sL;
        //console.log(sL);
          
        
        if (u.def(o.left))
          xx-=o.left;
        if (u.def(o.right))
          xx+=o.right;        
        var hmlr=ele.uiParent.offsetWidth;
        var hmll=ele.uiParent.offsetLeft;
        if (u.def(ele.horizontalMovementLimitLeft)) {//horizontal movement limit
          var limit=_UIparseData({s:ele.horizontalMovementLimitLeft,element:ele});
          hmll=limit;
          if (xx<limit)
            xx=limit;
        }    
        if (u.def(ele.horizontalMovementLimitRight)) {//horizontal movement limit
          var limit=_UIparseData({s:ele.horizontalMovementLimitRight,element:ele});
          hmlr=limit;
          if (xx>limit)
            xx=limit;
        }
        //document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop;
        
        //calculate horizontal movement properties
        ele.normalizedLeft=xx-hmll;
        ele.relativeLeftPercent=parseInt(ele.normalizedLeft*100/(hmlr-hmll));
        ele.widthLimit=hmlr-hmll;
  
        if (u.undef(_e.dontMove) || !_e.dontMove) {
          if (ele.movable) {
            if (u.undef(ele.constraintHorizontalMovement) || !ele.constraintHorizontalMovement)
              if ((u.undef(ele.relativePosition) || isNaN(ele.originalMarginLeft)))
                ele.dom.style.left=xx+'px';
              else
                ele.dom.style.marginLeft=(ele.originalMarginLeft*ele.uiParent.offsetWidth/ele.originalUiParentOffsetWidth)+(xx-(ele.originalLeft*ele.uiParent.offsetWidth/ele.originalUiParentOffsetWidth))+'px';
          }
        }  
          
        //vertical movement
        var vmlt=ele.uiParent.offsetTop;
        var vmlb=ele.uiParent.offsetHeight;
        
        var yy=(_e.clientY-ele.clickedY);
        if (u.def(o.down))
          yy+=o.down;
        if (u.def(o.up))
          yy-=o.up;
        if (u.def(ele.verticalMovementLimitTop)) {//vertical movement
          var limit=_UIparseData({s:ele.verticalMovementLimitTop,element:ele});
          vmlt=limit;
          if (yy<limit)
            yy=limit;
        }    
        if (u.def(ele.verticalMovementLimitBottom)) {//vertical movement
          var limit=_UIparseData({s:ele.verticalMovementLimitBottom,element:ele});
          vmlb=limit;
          if (yy>limit)
            yy=limit;
        }    
        
        //yy=yy/
            
        ele.normalizedTop=yy-vmlt;
        ele.relativeTopPercent=parseInt(ele.normalizedTop*100/(vmlb-vmlt));
        ele.heightLimit=vmlb-vmlt;
        
        if (u.undef(_e.dontMove) || !_e.dontMove) {
          if (ele.movable) {
            if (u.undef(ele.constraintVerticalMovement) || !ele.constraintVerticalMovement)
              if ((u.undef(ele.relativePosition) || isNaN(ele.originalMarginTop)))
                ele.dom.style.top=yy+'px';
              else //relative movement - uses marginTop offset
                ele.dom.style.marginTop=(ele.originalMarginTop*ele.uiParent.offsetHeight/ele.originalUiParentOffsetHeight)+(yy-(ele.originalTop*ele.uiParent.offsetHeight/ele.originalUiParentOffsetHeight))+'px';
          }
        }  
        
        ele.offsetLeft=ele.dom.offsetLeft;
        ele.offsetTop=ele.dom.offsetTop;
        
        //console.log(ele.objectId,' ',ele.offsetLeft,' ',ele.offsetTop);
        
        if (typeof _e.isFake!='undefined' && _e.isFake==true) //unset dragging prop if this event is fake
          ele.dragging=false;
          
        Segunda.Event.launch({elements:o.eles,element:ele,userEvent:ele.onDrag,event:_e,data:['Ui > processEvents > ele.onDrag error','ele:',ele]});
      }
      
      //internal object initialization init
      //parse events
      //window.ondommousescroll =function(){alert('x')};
      if (navigator.userAgent.match(/firefox/i))
        window.addEventListener('DOMMouseScroll',mouseTrapperWheel,false); //http://adomas.org/javascript-mouse-wheel/
      else 
        window.onmousewheel=document.onmousewheel=mouseTrapperWheel;       
      //window.onmousewheel = window.onmousewheel?function(e){window.onmousewheel();mouseTrapperWheel(e)}:mouseTrapperWheel;
      
      if (navigator.userAgent.match(/firefox/i))
        window.addEventListener('resize',resizeTrapper,false);
      else  
        window.onresize=window.onresize?function(e){window.onresize();resizeTrapper(e)}:resizeTrapper;
      
      window.onmousemove=window.onmousemove?function(e){window.onmousemove();mouseTrapper(e)}:mouseTrapper;
      window.onmousedown=window.onmousedown?function(e){window.onmousedown();mouseTrapperDown(e)}:mouseTrapperDown;
      window.onmouseup=window.onmouseup?function(e){window.onmouseup();mouseTrapperUp(e)}:mouseTrapperUp;
      window.onkeydown=window.onkeydown?function(e){window.onkeydown();keyboardTrapperKeyDown(e)}:keyboardTrapperKeyDown;
      window.onkeyup=window.onkeyup?function(e){window.onkeyup();keyboardTrapperKeyUp(e)}:keyboardTrapperKeyUp;
      //internal object initialization end
      
      //var _uiAutoIdCount=0;
      return {        
        //object methods and properties init
        //keys:_validKeys,
        dragging:null,
        clickedElement:null,
        keyboardStatus:_keys.downList,
        
        autoAdjustZIndex:1,
        
        define:function(o) {
          var _selectedElement=null;
          var u=Segunda.Utils;//shortcut
        
          if (!u.def(_elements[o.id]))
            _elements[o.id]=[];
          var obj=u.$(o.id);
          
          //console.log(o,obj);
          
          if (obj) {
            //_windows[o.id]=1;
            var go=0;
            var elex;
            if (typeof o.childElement=='undefined')
              elex=u.domWalker({node:o.id,getNodeById:o.objectId});
            else
              elex=[o.childElement];
            var isWindowObject=null;
            var uiParent=obj;
            var x=0,y=0;
            var parentWindow=null;
            if (u.undef(o.objectId)) {
              //window object
              isWindowObject=1;
              o.objectId=o.id;
              x=elex[0].offsetLeft;
              y=elex[0].offsetTop;
              //parentWindow=elex[0];
            } else {
              //child object              
              //thnks https://developer.mozilla.org/en/DOM/element.offsetParent
              //thnks http://blogs.korzh.com/progtips/2008/05/28/absolute-coordinates-of-dom-element-within-document.html
              //thnks http://codingforums.com/showthread.php?t=146215
              //get real object coordinates
              parentWindow=_elements[o.id][o.id];
              var dele=elex[0];
              if (typeof o.noUI=='undefined' || o.noUI==false) {
                
                if (!dele) {
                  Segunda.Console.error('UI.define > an element is undefined: '+o.objectId);
                  Segunda.Clock.stop();
                  return;
               }
                
                while (dele.offsetParent) {
                  //console.log('xx');
                  x+=dele.offsetLeft;
                  y+=dele.offsetTop;
                  dele=dele.offsetParent;
                }
                if (parentWindow) {
                  x-=parentWindow.offsetLeft; //for child objects subtract parent position
                  y-=parentWindow.offsetTop;
                }  
              } else {
                //console.log(parentWindow.offsetLeft,'--',elex[0].offsetLeft);
                x=elex[0].offsetLeft; //just use real coordinates since this element has no gfx content
                y=elex[0].offsetTop;
              }  
            }
            
            //if (isWindowObject)
              _nElements++;
            
            var def_cfg={
              papaId:o.id,dom:elex[0],selected:0,mouseover:0,isWindowObject:isWindowObject,
              offsetWidth:elex[0].offsetWidth,offsetHeight:elex[0].offsetHeight, //lookup vars
              offsetLeft:x,offsetTop:y,
              movable:u.choose(o.movable,false),uiParent:uiParent,parentWindow:parentWindow,
              originalLeft:elex[0].offsetLeft,originalTop:elex[0].offsetTop,
              originalMarginTop:parseInt(elex[0].style.marginTop),
              originalMarginLeft:parseInt(elex[0].style.marginLeft),
              originalUiParentOffsetHeight:uiParent.offsetHeight,
              originalUiParentOffsetWidth:uiParent.offsetWidth,
              mousedDown:0,
              stopDraggingBubble:true //do not allow dragging of other objects while dragging this one
              /*
              horizontalMovementLimitLeft:u.choose(o.horizontalMovementLimitLeft,0),
              horizontalMovementLimitRight:u.choose(o.horizontalMovementLimitRight,0),
              verticalMovementLimitTop:u.choose(o.verticalMovementLimitTop,0),
              verticalMovementLimitBottom:u.choose(o.verticalMovementLimitBottom,0)
              */
            }
            if (isNaN(def_cfg.originalMarginTop))
              def_cfg.originalMarginTop=0;
            if (isNaN(def_cfg.originalMarginLeft))
              def_cfg.originalMarginLeft=0;
            if (o.keyId) { //trap keyboard events
              _elements[o.id][o.keyId]=u.d(def_cfg,o);
              _plainElements.push(_elements[o.id][o.keyId]);
              _keys.trapList[o.keyId]=1;
              return obj;
            }  
            _elements[o.id][o.objectId]=u.d(def_cfg,o);
            _plainElements.push(_elements[o.id][o.objectId]);
            obj.elements=_elements[o.id];
            var ele=_elements[o.id][o.objectId];

            if (isWindowObject) {
              _wins[o.id]=ele;
              if (Segunda.Ui.autoAdjustZIndex)              
                ele.dom.style.zIndex=_nElements-1;
            }
            
            //initialize object
            
            //console.log(ele.initialized);
            
            if (typeof ele.initialized=='undefined' || (!ele.initialized && (typeof ele.noUI!='undefined' && !ele.noUI))) {
              
              
              
              //var that=this;                    
              ele.initialized=1;
              //add some methods to the element
              /*
              eleMove : function(){
              */         
              ele.move=function(iLeft,iTop) {
                this.dom.style.left=iLeft+'px';
                this.dom.style.top=iTop+'px';
                this.offsetLeft=this.dom.offsetLeft; //set real position
                this.offsetTop=this.dom.offsetTop;
              }  
              /*
              eleClick : function(){
              */         
              ele.click=function(cfg) { //fires a click event for the element
                /*
                //that.dragging=ele;
                //_firingEvent=1;
                */
                if (u.undef(cfg))
                  cfg={};
                this.clickedX=0;
                this.dragging=1; //make sure the ondragend event is fired
                this.clickedY=0;
                this.selected=1;
                this.mouseover=1;
                var fakeEvent={}; //reset the event object
                fakeEvent.isFake=1;
                fakeEvent.mouseButton=0;
                fakeEvent.dontMove=u.choose(cfg.dontMove,0);
                //console.log(fakeEvent.dontMove);
                fakeEvent.clientX=this.uiParent.offsetLeft+this.dom.offsetLeft;
                fakeEvent.clientY=this.uiParent.offsetTop+this.dom.offsetTop;
                _UIMoveObject(this,fakeEvent,{eles:_elements[o.id]});
                Segunda.Event.launch({window:this,config:cfg,elements:_elements[o.id],element:this,userEvent:this.onActivate,event:_e,data:['Ui > processEvents > ele.onActivate error','ele:',ele]});
                Segunda.Event.launch({window:this,config:cfg,elements:_elements[o.id],element:this,userEvent:this.onMouseDownMouseOver,event:_e,data:['Ui > processEvents > ele.onMouseDownMouseOver error','ele:',ele]});
                //Segunda.Event.launch({elements:_elements[zz],element:ele,userEvent:ele.onMouseDown,event:_e,data:['Ui > processEvents > ele.onMouseDown error','ele:',ele]});
                //console.log(ele.dom.id,' ',_e.clientX,_e.clientY);
              }                     
              /*
              eleMoveDown : function(){
              */                    
              ele.moveDown=function() {
                this.clickedX=0;
                this.dragging=1; //make sure the ondragend event is fired
                this.clickedY=0;
                this.selected=1;
                this.mouseover=1;
                var fakeEvent={}; //reset the event object
                fakeEvent.isFake=1;
                fakeEvent.mouseButton=0;
                fakeEvent.clientX=this.uiParent.offsetLeft+this.dom.offsetLeft;
                fakeEvent.clientY=this.uiParent.offsetTop+this.dom.offsetTop;
                _UIMoveObject(this,fakeEvent,{down:25,eles:_elements[o.id]});
                //console.log(ele.dom.id,' ',_e.clientX,_e.clientY);
              }
              /*
              eleMoveUp : function(){
              */                      
              ele.moveUp=function(){
                this.clickedX=0;
                this.dragging=1; //make sure the ondragend event is fired
                this.clickedY=0;
                this.selected=1;
                this.mouseover=1;
                var fakeEvent={}; //reset the event object
                fakeEvent.isFake=1;
                fakeEvent.mouseButton=0;
                fakeEvent.clientX=this.uiParent.offsetLeft+this.dom.offsetLeft;
                fakeEvent.clientY=this.uiParent.offsetTop+this.dom.offsetTop;
                _UIMoveObject(this,fakeEvent,{up:25,eles:_elements[o.id]});
                //console.log(ele.dom.id,' ',_e.clientX,_e.clientY);
              },                    
              /*
              eleMoveToTop : function(){
              */                   
              ele.moveToTop=function(){
                this.clickedX=0;
                this.dragging=1; //make sure the ondragend event is fired
                this.clickedY=0;
                this.selected=1;
                this.mouseover=1;
                var fakeEvent={}; //reset the event object
                fakeEvent.mouseButton=0;
                fakeEvent.isFake=1;
                fakeEvent.clientX=this.uiParent.offsetLeft+this.dom.offsetLeft;
                fakeEvent.clientY=this.uiParent.offsetTop+this.dom.offsetTop;
                _UIMoveObject(this,fakeEvent,{up:1000000000,eles:_elements[o.id]}); //ehm...it should be enough...
                //console.log(ele.dom.id,' ',_e.clientX,_e.clientY);
              },
              /*
              eleMoveToBottom : function(){
              */                    
              ele.moveToBottom=function() {
                this.clickedX=0;
                this.dragging=1; //make sure the ondragend event is fired
                this.clickedY=0;
                this.selected=1;
                this.mouseover=1;
                var fakeEvent={}; //reset the event object
                fakeEvent.mouseButton=0;
                fakeEvent.isFake=1;
                fakeEvent.clientX=this.uiParent.offsetLeft+this.dom.offsetLeft;
                fakeEvent.clientY=this.uiParent.offsetTop+this.dom.offsetTop;
                _UIMoveObject(this,fakeEvent,{down:1000000000,eles:_elements[o.id]});
                //console.log(ele.dom.id,' ',_e.clientX,_e.clientY);
              },
              /*
              eleMoveToLeft : function(){
              */                    
              ele.moveToLeft=function() {
                this.clickedX=0;
                this.dragging=1; //make sure the ondragend event is fired
                this.clickedY=0;
                this.selected=1;
                this.mouseover=1;
                var fakeEvent={}; //reset the event object
                fakeEvent.isFake=1;
                fakeEvent.mouseButton=0;
                fakeEvent.clientX=this.uiParent.offsetLeft+this.dom.offsetLeft;
                fakeEvent.clientY=this.uiParent.offsetTop+this.dom.offsetTop;
                _UIMoveObject(this,fakeEvent,{left:1000000000,eles:_elements[o.id]});
                //console.log(ele.dom.id,' ',_e.clientX,_e.clientY);
              },
              /*
              eleMoveToRight : function(){
              */                                         
              ele.moveToRight=function() {
                this.clickedX=0;
                this.dragging=1; //make sure the ondragend event is fired
                this.clickedY=0;
                this.selected=1;
                this.mouseover=1;
                var fakeEvent={}; //reset the event object
                fakeEvent.isFake=1;
                fakeEvent.mouseButton=0;
                fakeEvent.clientX=this.uiParent.offsetLeft+this.dom.offsetLeft;
                fakeEvent.clientY=this.uiParent.offsetTop+this.dom.offsetTop;
                _UIMoveObject(this,fakeEvent,{right:1000000000,eles:_elements[zz]});
                //console.log(ele.dom.id,' ',_e.clientX,_e.clientY);
              },                      
              Segunda.Event.launch({window:this,elements:_elements[o.id],element:ele,userEvent:ele.onInitialize,event:_e,data:['Ui > processEvents > ele.onDragEnd error','ele:',ele]});
            }
            
            
          }
          return obj;
        },
                  
        processEvents:function(o) {
          
          var ui=Segunda.Ui;//shortcut
          var u=Segunda.Utils;//shortcut
          var ele;
          var x,y,w,h;          
          var xp,yp,wp,hp;          
          var _eMousePressed;
          var eClientX=0;
          var eClientY=0;
          var _eResizeEvent=0;
          var _eMouseMove=0;
          var _eWheelDelta=0;
          var _eClickedX,_eClickedY=null;
          var eMouseButton=null;
          var _adjustZ=0;
          
          //console.log(_e.mouseButton);

          if (_e) {
            eClientX=_e.clientX; //lookup vars
            eClientY=_e.clientY;
            eMouseButton=_e.mouseButton;
            _eResizeEvent=_e.resizeEvent;
            _eMouseMove=_e.mouseMove;
            _eWheelDelta=_e.wheelDelta;
            _eClickedX=_e.clickedX;
            _eClickedY=_e.clickedY;
            _eMousePressed=_e.mousePressed;
            //console.log(_e.mousePressed,_eClickedX,_eClickedY);
          } else {
            //console.log('x');
            return;
          }

          //console.log(_eClickedX,' ',_eClickedY,' ',this.clickedElement);

          //console.dir(_windows);

          //var idx=-1;
          //for (var zz in _windows) {
            //for (var z in _elements[zz]) {
          var zz;
          for (var z=0,zEnd=_plainElements.length;z<zEnd;z++) {
            //idx++;
            _key_listener_counter++;
            ele=_plainElements[z];
            zz=ele.papaId;
            
//            console.log(ele);

            if (!ele.hidden && !ele.disabled && !ele.uiParent.hidden && !ele.uiParent.disabled) { //if current element can handle events
              
              if (ele.main) {//run main function for the window
                Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.main,event:_e,data:['Ui > processEvents > ele.onDragEnd error','ele:',ele]});                    
                //ele.main(_e);
              }  
              //iterate trough keys
              
              if (ele.keyId) {
                //console.log(_key_listener_counter);
                var keycode=getKeyIndex(ele.keyId);
                if (_keys.downList[keycode]) {
                  ele.keyPressed=1;
                  if (_key_listener_counter>=u.choose(ele.keyDownWait,_keys.listenerInterval)) {
                    _key_listener_counter=0;
                    Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onKeyDown,event:_e,data:['Ui > processEvents > ele.onKeyDown error','ele:',ele]});
                  }
                } else {
                  if (ele.keyPressed) {
                    ele.keyPressed=0;
                    Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onKeyUp,event:_e,data:['Ui > processEvents > ele.onKeyUp error','ele:',ele]});
                  }
                }  
                continue;  //skip this cicle
              }  


/*
              if (!isKeyEvent) {

                //console.log(ele,ele.parentWindow,(ele==ele.parentWindow))
              }                  
*/                
              //DEBUG ME... QUESTO E' MEGLIO??!?!
              if (eMouseButton==null) { //mouseup event
                if (ele.mousedDown) {
                  if (ele.selected4Drag)
                    ele.selected4Drag=0;
                  if (ele.dragging) { //drag & drop is over
                    ele.dragging=0;
                    Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onDragEnd,event:_e,data:['Ui > processEvents > ele.onDragEnd error','ele:',ele]});
                  }  
                  this.dragging=null;
                  ele.mousedDown=0;
                  ele.mouseDownEventsFired=0;                    
                  //console.log(ele,ele.mousedDown,ele.selected4Drag,this.dragging);
                }
                this.clickedElement=null;
              }
              if (_eMouseMove) //a new mouse move event
                ele.moved=0;
              
              //console.log(_eResizeEvent);
              
              if (_e && (_eResizeEvent || _eMouseMove || _eMousePressed || _eWheelDelta)) {
              //if (_e && !isKeyEvent) {
                w=ele.offsetWidth;//ele.dom.offsetWidth; //use saved dim intead of real values - speed increased by 50%!
                h=ele.offsetHeight;//ele.dom.offsetHeight;
                //dele=ele.dom;
                x=ele.offsetLeft;
                y=ele.offsetTop;
                                  
                if (ele.parentWindow) { //add parent pos
                  x+=ele.parentWindow.offsetLeft;
                  y+=ele.parentWindow.offsetTop;
                }
                

               
                //mouse over detection init
                
                if (eClientX>x && eClientY>y && eClientX<=x+w && eClientY<=y+h) {
                  
                  //console.log(ele);
                  ele.mouseX=_e.clientX-ele.offsetLeft;
                  ele.mouseY=_e.clientY-ele.offsetTop;
                  
                  //console.log(ele.mouseX,ele.mouseY);
                  
                  if (!ele.mouseover) {                      
                    Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onMouseOver,event:_e,data:['Ui > processEvents > ele.onMouseOver error','ele:',ele]});
                    Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onMouseDownMouseOver,event:_e,data:['Ui > processEvents > ele.onMouseDownMouseOver error','ele:',ele]});
                    if (!ele.isWindowObject) {
                      //global mouseover from the parentwindow
                        Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.parentWindow.onGlobalMouseOver,event:_e,data:['Ui > processEvents > ele.onMouseOut error','ele:',ele]});
                      //ele.dom.style.color='white';
                      //ele.dom.style.background='orange';
                    }
                    
                    ele.mouseover=1;
                  }
                  
                  //console.log(_eClickedX,_eClickedY,_eMousePressed);
                  
                  if (typeof _eClickedX!='undefined' && _eClickedX!=null && _eMousePressed) {
                    //console.log('yo');
                    if (_eClickedX>x && _eClickedY>y && _eClickedX<=x+w && _eClickedY<=y+h) {
                      
                      //console.log(ele,this.clickedElement,' ',_eClickedX,' ',_eClickedY);
                      
                      if (this.clickedElement==null) {
                        this.clickedElement=ele;
                      } else {
                        if (ele.isWindowObject) {
                          if (this.clickedElement.dom.style.zIndex<ele.dom.style.zIndex)
                            this.clickedElement=ele;
                        } else {
                          //console.log(ele,' ',ele.parentWindow,this.clickedElement);
                          if (this.clickedElement==ele.parentWindow) {
                            //console.log(' a child of papa has been clicked')
                            this.clickedElement=ele;
                          }
                        }  
                      }
                      _adjustZ=this.clickedElement; //set the element to popup on view                              
                      //console.log('yo ',ele,this.clickedElement);
                    }
                  }                        
                  
                } else {
                  if (!_firingEvent) {
                    if (ele.mouseover) {
                      Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onMouseOut,event:_e,data:['Ui > processEvents > ele.onMouseOut error','ele:',ele]});
                      if (!ele.isWindowObject) { 
                        //console.log('x');
                        //global mouse out from the parentwindow
                          Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.parentWindow.onGlobalMouseOut,event:_e,data:['Ui > processEvents > ele.onMouseOut error','ele:',ele]});
                        //ele.dom.style.color='';
                        //ele.dom.style.background='';
                      }
                      ele.mouseover=0;
                    }
                  }
                  _firingEvent=false;
                }
                //mouse over detection end

                                  //continue;

                
                //mouse click detection init
                /*
                mouseDown : function(){
                */   
                if (eMouseButton==0 && (ele==this.clickedElement || (ele.parentWindow && ele.parentWindow==this.clickedElement))) { //mouse down - left click
                  //if (!idx)
                  //console.log('sito',ele);
                  if (ele.mouseover) {
                    if (ele.movable) {
                      //console.log('sebi',ele,ele.moved,!ele.moved);
                      if (!ele.moved) {
                        if (!ele.selected4Drag) {
                          
                          //do not drag if we are selecting html elements 
                          /*
                          mouseDownIgnoreObjectList: function(){
                          */
                          //console.log(_e.target.tagName);
                          switch (_e.target.tagName) {
                            case 'TEXTAREA':
                            case 'SELECT':
                            case 'OPTION':
                            case 'INPUT':
                            continue;
                          }                            
                          
                          ele.selected4Drag=1;
                          //console.log('sut',z,ele,this.dragging,' ',ele.uiParent);
                          if (
                              this.dragging==null || (ele.stopDraggingBubble && this.dragging.dom==ele.uiParent) ||
                              (this.dragging && this.dragging.dom.style.zIndex<ele.dom.style.zIndex)
                          )
                          {
                            //console.log(ele.dom.style.zIndex);
                            this.dragging=ele;
                          }
                          ele.clickedX=_e.clientX-ele.dom.offsetLeft;
                          ele.clickedY=_e.clientY-ele.dom.offsetTop;
                          //ele.moved=1;
                        }
                      }  
                    } else if (!ele.mouseDownEventsFired) {
                      //not movable -> gui element
                      //console.log(ele,ele.mousedDown,ele.selected4Drag,this.dragging);
                      ele.selected=1;
                      //analizza evento deactivate
                      if (typeof _elements[zz].selectedElement!='undefined' && _elements[zz].selectedElement!=ele) {//if an element has been selected
                        if (this.dragging==ele.parentWindow) { //non lanciare l'evento se stiamo trascinando un'altro oggetto
                          _elements[zz].selectedElement.selected=0;
                          //console.log(_elements[zz].selectedElement,' ',ele);
                          Segunda.Event.launch({window:this,elements:_elements[zz],element:_elements[zz].selectedElement,userEvent:_elements[zz].selectedElement.onDeactivate,event:_e,data:['Ui > processEvents > _selectedElement.onDeactivate error','ele:',_elements[zz].selectedElement]});
                        }  
                      }  
                      _elements[zz].selectedElement=ele;
                      if (!ele.selected4Drag && (this.dragging==null || this.dragging==ele.parentWindow)) {
                        ele.selected4Drag=1;
                        Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onActivate,event:_e,data:['Ui > processEvents > ele.onActivate error','ele:',ele]});
                        Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onMouseDownMouseOver,event:_e,data:['Ui > processEvents > ele.onMouseDownMouseOver error','ele:',ele]});
                      }                        
                      Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onMouseDown,event:_e,data:['Ui > processEvents > ele.onMouseDown error','ele:',ele]});
                      //if (this.dragging==ele.parentWindow || this.draggin.dom.style.zIndex<ele.)
                      //if (this.dragging)
                      //  console.log(this.dragging,' ',this.dragging.dom.style.zIndex,' ',ele.uiParent.style.zIndex);
                      
                      //if (this.dragging!=null)
                      //  if (ele.parentWindow!=this.dragging && ele.parentWindow.dom.style.zIndex>this.dragging.dom.style.zIndex)
                      //    this.dragging=null;
                      
                      if (this.dragging==ele.parentWindow)
                        this.dragging=null; //do not allow windows draggin if we have a mousedown over a child of the main window
                      
                      ele.mouseDownEventsFired=1;  
                    } else if (ele.mouseDownEventsFired) {
                      //console.log(ele.parentWindow,' ',this.dragging,' ',ele.parentWindow);
                      if (this.dragging==ele.parentWindow)
                        this.dragging=null; //do not allow windows draggin if we have a mousedown over a child of the main window
                    }
                    
                    ele.mousedDown=1;
                  }
                }
                //mouse click detection end

   
                //mouse dragging init
                if (ele.selected4Drag) { //always follow the mouse if selected
                    //console.log(ele);

                  if (ele.movable && this.dragging==ele && !ele.moved) { //allow drag and drop
                    
                    //horizontal movement
                    /*
                    questa azione aggiorna automaticamente delle proprietà
                    o.element.normalizedLeft,
                    movimento relativo che andrà da zero a limite di movimentox
                    
                    o.element.relativeLeftPercent
                    o.element.relativeTopPercent
                    percentuale di movimento (slider) da 0 a 100
                    
                    widthLimit limite left
                    heightLimit limite top
                    
                    normalizedLeft da 0 a leftlimit
                    
                    normalizedTop  da 0 a limite y
                    
                    
                    */
                    //console.log('x');
                    _UIMoveObject(ele,_e,{eles:_elements[zz]});
                    ele.moved=1;

                  }  
                }  
                //mouse dragging end

                if (_e.resizeEvent)
                  Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onParentResize,event:_e,data:['Ui > processEvents > ele.onDragEnd error','ele:',ele]});                    
                if (_e.wheelDeltaCounter>0)
                  Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onMouseWheel,event:_e,data:['Ui > processEvents > ele.onDragEnd error','ele:',ele]});
                if (_e.mouseMove && ele.mouseover)
                  Segunda.Event.launch({window:this,elements:_elements[zz],element:ele,userEvent:ele.onMouseMove,event:_e,data:['Ui > processEvents > ele.onDragEnd error','ele:',ele]});                    
              }
            }  
          }
          
          //}
          
          //if
          //set z-index
          if (_adjustZ) {
            
            //console.log('adjust',' ',ele);            
            //_adjustZ=_adjustZ.parentWindow;
            var oldZ=_adjustZ.dom.style.zIndex;
            
            if (!_adjustZ.isWindowObject && Segunda.Ui.autoAdjustZIndex) {
              //adjust z for child elements
              for (var z in _elements[zz]) {
                ele=_elements[zz][z];
                if (!ele.isWindowObject && ele.parentWindow==_adjustZ.parentWindow) {
                  if (ele.dom.style.zIndex>oldZ)
                    ele.dom.style.zIndex--;                  
                }                
              }
              _adjustZ.dom.style.zIndex=_nElements-1;
              _adjustZ=_adjustZ.parentWindow;
            }
            
            //console.log(_adjustZ);
            if (Segunda.Ui.autoAdjustZIndex) {
              oldZ=_adjustZ.dom.style.zIndex;
              for (var ww in _wins) {
                if (_wins[ww].dom.style.zIndex>oldZ)
                  _wins[ww].dom.style.zIndex--;
              }
              _adjustZ.dom.style.zIndex=_nElements-1;
              //this.dragging=_adjustZ;
              _adjustZ=0;
            }    

          }  
          
          _e.resizeEvent=0;
          _e.mouseMove=0;
          _mousePressed=_e.mousePressed=0;
          if (_e.wheelDeltaCounter>0) {
            _e.wheelDeltaCounter--;
          }
          //_e=null;
        }  
        //object methods and properties end
      }

    }(),
    //singleton end

    //singleton init
    /*
    function Utils - Javascript utilities//let the editor source tree grab the classes
    */
    Utils:function() { //general utilities
      //thanks https://developer.mozilla.org/en/Whitespace_in_the_DOM
      var utils_is_all_ws=function( nod ) {
        // Use ECMA-262 Edition 3 String and RegExp features
        return !(/[^\t\n\r\s]/.test(nod.data));
      }
	
      var utils_is_ignorable=function( nod ) {
        return ( nod.nodeType == 8) || // A comment node
               ( (nod.nodeType == 3) && utils_is_all_ws(nod) ); // a text node, all ws
      }

      return {
        //object methods and properties init
        /*
        New:function //let the editor source tree grab the classes
        */           
        New:function(o) {
          var ele=o.element;
          if (typeof ele=='undefined')
            ele='div';
          var newElement=document.createElement(ele);
          newElement.style.position='absolute';
          if (typeof o.value!='undefined')
            newElement.value=o.value;
          if (typeof o.padding!='undefined')
            newElement.style.padding=o.padding+'px';
          if (typeof o.margin!='undefined')
            newElement.style.margin=o.margin+'px';
          if (typeof o.fontSize!='undefined')
            newElement.style.fontSize=o.fontSize+'px';
          if (typeof o.fontFamily!='undefined')
            newElement.style.fontFamily=o.fontFamily;
          if (typeof o.left!='undefined')
            newElement.style.left=o.left+'px';
          if (typeof o.x!='undefined')
            newElement.style.left=o.x+'px';
          if (typeof o.y!='undefined')
            newElement.style.top=o.y+'px';
          if (typeof o.top!='undefined')
            newElement.style.top=o.top+'px';
          if (typeof o.width!='undefined')
            newElement.style.width=o.width+'px';
          if (typeof o.height!='undefined')
            newElement.style.height=o.height+'px';
          if (typeof o.background!='undefined')
            newElement.style.background=o.background;
          if (typeof o.zIndex!='undefined')
            newElement.style.zIndex=o.zIndex;
          if (typeof o.border!='undefined')
            newElement.style.border=o.border;
          if (typeof o.type!='undefined')
            newElement.type=o.type;
          if (typeof o.id!='undefined')
            newElement.id=o.id;
          if (typeof o.parent=='string')
            Segunda.Utils.$(o.parent).appendChild(newElement);
          else {
            if (typeof o.parent!='undefined')
              o.parent.appendChild(newElement);
            else
              document.body.appendChild(newElement);
          }  
          return newElement;
        },
        random:function (min, max) { //from mootools > http://mootools.net
          return Math.floor(Math.random() * (max - min + 1) + min);
        },        
        $:function(s) { //simple document.getElementById shortcut
          return document.getElementById(s);
        },
        px:function(i) {
          return parseInt(i)+'px';
        },  
        d:function(x,y) { //return object x with object y properties
          if (typeof x=='undefined' && typeof y=='object') x={};
          if (typeof x=='object' && typeof y=='object') {
            for (var z in y)
              if (typeof y[z]!='undefined')
                x[z]=y[z];
            return x;
          }
          if (typeof x !='undefined') return x
          return y;
        },
        compareArrays:function(a1,a2) {
          var ctx=0;
          for (var z=0,zEnd=a1.length;z<zEnd;z++) {
            if (a1[z]==a2[z]) {
              ctx++;
            }
          }
          //console.log(ctx,a1.length,a2.length);
          if (ctx==a1.length && ctx==a2.length)
            return 1;
          else
            return 0;
        },
        getStyleSheetByIndex:function(sIndex) { //tnxs: http://snippets.dzone.com/posts/show/1660
          for (var z=0,zEnd=document.styleSheets.length;z<zEnd;z++) {
            if (z==sIndex)
              return document.styleSheets[z];
          }
          return null;
        },
        getStyleSheetClasses:function(o) { //tnxs: http://snippets.dzone.com/posts/show/1660
          if (typeof o.styleSheetIndex=='undefined')
            o.styleSheetIndex=0;
          var selector=o.selector;
          if (typeof o.selector=='string')         
            selector = o.selector.toLowerCase();
          var stylesheet = Segunda.Utils.getStyleSheetByIndex(o.styleSheetIndex);
          var retval=[];
          for(var i=0,n=stylesheet.cssRules.length; i<n; i++) {
             var selectors = stylesheet.cssRules[i].selectorText.toLowerCase().split(",");
             for(var j=0,m=selectors.length;j<m;j++) {
                var currentSel=selectors[j];
                if (currentSel) {
                  if (typeof selector=='string') {
                    if (currentSel.indexOf(selector)!=-1) {
                      retval.push({selector:currentSel,style:stylesheet.cssRules[i].style});
                      //var value = stylesheet.cssRules[i].style.getPropertyValue(attribute);
                    }
                  } else {
                    if (currentSel.match(selector)) {
                      retval.push({selector:currentSel,style:stylesheet.cssRules[i].style});
                      //var value = stylesheet.cssRules[i].style.getPropertyValue(attribute);
                    }
                  }  
                }  
             }
          }
          return retval;
        },
        undef:function(o) { //return true if object is undefined
          //console.log('undef:',o);
          return (o===null || typeof o=='undefined');
        },
        def:function(o) { //return true if object is defined
          return typeof o!='undefined';
        },
        choose:function() { //choose the first defined object
          for (var z=0;z<arguments.length;z++)
            //if (!Segunda.Utils.undef(arguments[z]) && Segunda.Utils.undef(arguments[z])!='')
            if (!Segunda.Utils.undef(arguments[z]))
              return arguments[z];
          return arguments[z-1]; //always return last value   
        },
        domWalker:function(o,depth,elements) { //walk trough dom and return object basing on specified rules
          typeof depth=='undefined'?depth=0:depth++;
          typeof elements=='undefined'?elements=[]:1;
          var currentElement=(typeof o.node=='string'?document.getElementById(o.node):o.node);
          if (!currentElement) return null;
          if (utils_is_ignorable(currentElement)) {
            return null;
          }

          var operation='';
          //operation parsing init
          if (typeof o.getNodeById!='undefined')
            operation+='_getNodeById';
          if (typeof o.getNodeByRegExpId!='undefined')
            operation+='_getNodeByRegExpId';
          if (typeof o.getNodeByClassName!='undefined')
            operation+='_getNodeByClassName';
          if (typeof o.getNodeByRegExpClassName!='undefined')
            operation+='_getNodeByRegExpClassName';
          if (typeof o.getNodeByTagName!='undefined')
            operation+='_getNodeByTagName';
          if (typeof o.getNodeWithDepthGreaterThan!='undefined')
            operation+='_getNodeWithDepthGreaterThan';            
          if (typeof o.getNodeWithDepthEqualTo!='undefined')
            operation+='_getNodeWithDepthEqualTo';            
          if (typeof o.getNodeWithDepthLessThan!='undefined')
            operation+='_getNodeWithDepthLessThan';            
          if (typeof o.getNodeWithChildren!='undefined')
            operation+='_getNodeWithChildren';
          if (typeof o.getNodeType!='undefined')
            operation+='_getNodeType';
          
          if (operation.indexOf('_getNodeById')>-1)
            if (currentElement.id==o.getNodeById)
               elements.push(currentElement);
          if (operation.indexOf('_getNodeByRegExpId')>-1)
            if (o.getNodeByRegExpId.match(currentElement.id))
              elements.push(currentElement);
          if (operation.indexOf('_getNodeByClassName')>-1)
            if (currentElement.className==o.getNodeByClassName)
              elements.push(currentElement);              
          if (operation.indexOf('_getNodeByRegExpClassName')>-1) {
            if (currentElement.className) {
              //console.log(currentElement.className);
              if (currentElement.className.match(o.getNodeByRegExpClassName))
                elements.push(currentElement);
            }    
          }    
          if (operation.indexOf('_getNodeByTagName')>-1) {
            if (currentElement && currentElement.tagName)
              if (currentElement.tagName.toLowerCase()==o.getNodeByTagName.toLowerCase())
                elements.push(currentElement);
          }

          if (operation.indexOf('_getNodeWithDepthLessThan')>-1) {
            if (depth<o.getNodeWithDepthLessThan)
              elements.push(currentElement);
          }  
          if (operation.indexOf('_getNodeWithDepthGreaterThan')>-1) {
            if (depth>o.getNodeWithDepthGreaterThan)
              elements.push(currentElement);
          }  
          if (operation.indexOf('_getNodeWithDepthEqualTo')>-1) {
            if (depth==o.getNodeWithDepthEqualTo)
              elements.push(currentElement);
          }  

          if (operation.indexOf('_getNodeWithChildren')>-1) {
            if (currentElement.childNodes)
              elements.push(currentElement);
          }  
          if (operation.indexOf('_getNodeType')>-1) {
            if (currentElement.nodeType==o.getNodeType)
              elements.push(currentElement);
          }  

          if (operation=='')
            elements.push(currentElement);
        
          if (currentElement.childNodes) {
            var cont=-1;
            while (++cont<currentElement.childNodes.length) {
              o.node=currentElement.childNodes[cont];
              this.domWalker(o,depth,elements);
            }  
          }
          return elements;
        }
        //object methods and properties end
      }
    }(),
    //singleton end

    //singleton init
/*
function Window //let the editor source tree grab the classes
*/
    Window:function(o) {
      var _windowAutoIdParent=0;
      var _windowAutoId=0;
      return {
        //object methods and properties init
        define:function(o) {
          var u=Segunda.Utils;//shortcut
          var ui=Segunda.Ui;//shortcut
          var contentId=o.contentId;
          var content=o.content;
          
          if (typeof contentId=='undefined') {
            var newId;
            if (typeof content.id!='undefined' && content.id!='') {
              newId=contentId=content.id;
            } else {  
              newId='_segundaWindowUI_'+_windowAutoIdParent;
              _windowAutoIdParent++;
              contentId=content.id=newId;
            }
            o.contentId=newId;
            //o.content=content=null;
          }
          
          var def_cfg={hidden:0,disabled:0,id:o.contentId,movable:u.choose(o.movable,true)};
          var def_cfg_ori={hidden:0,disabled:0,id:o.contentId,movable:u.choose(o.movable,true)};
          var cfg=u.d(def_cfg,o);
          var _windowUielement=ui.define(cfg);
          var ele=null;
          
          //build children list
          var children=u.domWalker({node:contentId,getNodeByTagName:'div'});
          var _children=[];
          if (children)
            for (var z=0,zEnd=children.length;z<zEnd;z++) {
              if (children[z].id)
                _children[children[z].id]=children[z];
            }
          //console.dir(_children);
          
          if (u.def(o.handlers)) {
            for (var z=0,zEnd=o.handlers.length;z<zEnd;z++) {
              //var dd=document.getElementById(o.handlers[z].objectId);
              //if (!dd) { //could be a keystroke id
              //Segunda.Console.error('Window > define > u.$(o.handlers[z]); > no result! '+o.handlers[z].objectId)
              //}
              var def_cfg={hidden:0,disabled:0,id:o.contentId,objectId:o.handlers[z].objectId};
              ele=ui.define(u.d(def_cfg,o.handlers[z]));
            }  
          }     
          var _content=u.$(o.contentId);
          if (!_content)
            _content=o.content;
          if (typeof _content=='string') {
            Segunda.Console.error('Window > define > you must use the contentId property to specify an object id.')
            Segunda.clock.stop();
            return;
          }  
            
          if (!_content) {
            Segunda.Console.error('Window > define > u.$(o.contentId); > no result! '+o.contentId);
            Segunda.Clock.stop();
            return;
          }
          _content.style.MozUserSelect='-moz-none'; //disable text selection on windows - thanks: https://developer.mozilla.org/En/CSS/-moz-user-select
          var _left=o.x;
          var _top=o.y;
          var _width=o.x1;
          var _height=o.y1;
          var retElements=null;
          if (ele)
            retElements=ele.elements;
          return u.d(o,{
            dom:_children,
            elements:retElements,
            left:_left,
            top:_top,
            content:_content,
            document:_content,
            hide:function(o) {
              _windowUielement.hidden=1;
              _content.style.display='none';
            },
            addObject:function(cfg) {
              var d;
              if (typeof cfg.noUI=='undefined' || cfg.noUI==false) {
/*
                d=u.New(u.d(cfg,{
                  id:'_segundaWindowChild_'+_windowAutoId,
                  position:'absolute',
                  parent:_content
                }));
                _windowAutoId++
*/
                
                d=document.createElement('div');
                d.id='_segundaWindowChild_'+_windowAutoId;
                _windowAutoId++;
                d.style.position='absolute';              
                d.style.left=u.choose(cfg.x,cfg.left)+'px';
                d.style.top=u.choose(cfg.y,cfg.top)+'px';
                d.style.width=cfg.width+'px';
                d.style.height=cfg.height+'px';
                //d.style.background='red';
                _content.appendChild(d);
                
              } else {
                d={};;
                d.id='_segundaWindowChild_'+_windowAutoId;
                _windowAutoId++;
                d.style={};
                d.style.position='absolute';
                var x=u.choose(cfg.x,cfg.left);
                var y=u.choose(cfg.y,cfg.top);
                d.style.left=x+'px';
                d.offsetLeft=x;
                d.style.top=y+'px';
                d.offsetTop=y;
                d.style.width=cfg.width+'px';
                d.style.height=cfg.height+'px';
                d.offsetWidth=cfg.width;
                d.offsetHeight=cfg.height;
              }  
              cfg.objectId=d.id; //pass objectid so the element is not treated as a window object
              cfg.childElement=d; //pass the children directly so ui.define does not need to traverse the dom to find it
              ui.define(u.d(def_cfg_ori,cfg));
              return d;
            },
            show:function(cfg) {
              if (u.undef(cfg))
                cfg={};
              if (_content) {
                var x=u.choose(cfg.x,_left,0);
                var y=u.choose(cfg.y,_top,0);
                _content.style.display='block';
                _content.style.position='absolute';
                _content.style.left=x+'px';
                _content.style.top=y+'px';
                _content.style.width=u.choose(cfg.x1,_width,_content.offsetWidth)+'px';
                _content.style.height=u.choose(cfg.y1,_height,_content.offsetHeight)+'px';
                //update object window
                //console.log(this.content.elements[o.contentId].offsetLeft);
                this.content.elements[o.contentId].offsetLeft=x;
                this.content.elements[o.contentId].offsetTop=y;
                //console.log(this.content.elements[o.contentId].offsetLeft);
              } else {
                Segunda.Console.error('Window > show > _content is not defined')
              }  
            }
          });
        }  
        //object methods and properties end
      }
    }(),
    //singleton end

    //singleton init
/*
function ISO //let the editor source tree grab the classes
*/
    Iso:function() { //very simple isometric engine
      //var _cfg;
      //var _lookup;
      return {
        //object methods and properties init
        define:function(o) {
          var _cfg=o;
          var _map=[];
          var _castShadows=1;
          
          var u=Segunda.Utils;//shortcut
          
          for (var w=0,wEnd=o.mapHeight;w<wEnd;w++) { //init iso array map
            for (var v=0,vEnd=o.mapWidth;v<vEnd;v++) {
              if (u.undef(_map[w]))
                _map[w]=[];
              _map[w][v]=[];
            }
          }
          for (var w=0,wEnd=o.mapHeight;w<wEnd;w++) { //fill specified default level with default tile object
            for (var v=0,vEnd=o.mapWidth;v<vEnd;v++) {
              _map[v][w][o.defaultLevel]={x:v,y:w,z:o.defaultLevel,spriteId:o.defaultTile,offsetX:0,offsetY:0};
            }
          }  
          
          return {
            id:_cfg.id,
            tileXStep:_cfg.tileXStep,
            tileYStep:_cfg.tileYStep,
            tileZStep:_cfg.tileZStep,
            xDim:_cfg.xDim,
            hXDim:_cfg.xDim/2, //half xdim
            yDim:_cfg.yDim,
            hYDim:_cfg.yDim/2, //half ydim
            zDim:_cfg.zDim,
            x:_cfg.left,
            y:_cfg.top,
            canvas:_cfg.canvas,
            del:function(o) { //delete a tile from the map
              _map[o[2]][o[1]][o[0]]=null;              
            },
            get:function(o) { //obtain a tile from the map -> level,x,y
              return _map[o[2]][o[1]][o[0]];              
            }, 
            set:function(o) { //set a tile into the map > level,x,y the tile must be an object having spriteId, offsetx, offsetY, x,y,z
              //var def_cfg={spriteId:curData[3],offsetX:u.choose(curData[4],0),offsetY:u.choose(curData[5],0),x:curData[1],y:curData[2],z:curData[0]};
              //var cfg=u.d(def_cfg,o[3]);
              _map[o[2]][o[1]][o[0]]=o[3];              
            }, 
            setData:function(o) { //a more complex set tile unction to allow easier definition of maps
              //[1,0,0,'batman_d1'],[2,0,0,'batman_d1']
              var curData;
              for (var z=0,zEnd=o.length;z<zEnd;z++) {
                curData=o[z];
                var def_cfg={spriteId:curData[3],offsetX:u.choose(curData[4],0),offsetY:u.choose(curData[5],0),x:curData[1],y:curData[2],z:curData[0]};
                var cfg=u.d(def_cfg,o);
                _map[curData[2]][curData[1]][curData[0]]=cfg;
              }
            },
            setTileXStep:function(w) {
              _cfg.tileXStep=w;
            },
            setTileYStep:function(h) {
              _cfg.tileYStep=h;
            },
            getScreenCoordinates:function(o) { //ret screen coordinates from tile coordinates
              var incWidth=_cfg.tileXStep;
              var incHeight=_cfg.tileYStep;
              var incZHeight=u.choose(_cfg.tileZStep,0);
              var tileX = (o.x - o.y) * incWidth
              var tileY = (o.x + o.y) * incHeight-(o.z*incZHeight);                    
              return {x:tileX,y:tileY};
            },
            paint:function(o) { //paint the iso scene
              var canvas=o.canvas;
              this.canvas=canvas; //set current canvas
              var tiles=_cfg.tiles;
              var incWidth=_cfg.tileXStep;
              var incHeight=_cfg.tileYStep;
              var incZHeight=_cfg.tileZStep;
              var offsetX=_cfg.left;
              var offsetY=_cfg.top;
              var screenX=(o.x-o.y)*incWidth;
              var screenY=(o.x+o.y)*incHeight-(incZHeight*o.z);              
              var tileX,tileY,zHeight;
              var tileSX,tileSY,isCharacter;
              for (var z=o.z,zEnd=_cfg.viewportZHeight+o.z;z<zEnd;z+=1) {
                zHeight=incZHeight*z;
                for (var x=o.x,xEnd=_cfg.viewportWidth+o.x;x<xEnd;x++) {
                  for (var y=o.y,yEnd=_cfg.viewportHeight+o.y;y<yEnd;y++) {
                    var currentMapTileArray=_map[y][x];
                    if (currentMapTileArray) {
                      if (currentMapTileArray[z]) {
                        
                        tileX =((x - y) * incWidth)-screenX;
                        tileY =((x + y) * incHeight-zHeight)-screenY;                    
                        currentMapTile=currentMapTileArray[z];
                        
                        if (currentMapTile.paint) {//if the current tile is an object with its own paint method, invoke it
                          currentMapTile.animate(); //invoke the object animate method
                          tileSX=currentMapTile.offsetX+offsetX-screenX;
                          tileSY=currentMapTile.offsetY+currentMapTile.offsetZ+offsetY-screenY;
                          isCharacter=1;
                          //canvas.putIsoSprite(tiles[currentMapTile.spriteId],tileSX,tileSY,x,y,z,1,currentMapTile,tileX,tileY+zHeight);
                        } else {
                          isCharacter=0;
                          tileSX=tileX+currentMapTile.offsetX+offsetX;
                          tileSY=tileY+currentMapTile.offsetY+offsetY;
                          //canvas.putIsoSprite(tiles[currentMapTile.spriteId],tileSX,tileSY,x,y,z,0,currentMapTile,tileX,tileY+zHeight);
                        }
                        canvas.putIsoSprite(tiles[currentMapTile.spriteId],tileSX,tileSY,x,y,z,isCharacter,currentMapTile,tileX,tileY+zHeight);
                        if (0 && _castShadows) {
                          var zDown=z;
                          var goDown=(z>1 && (_map[y][x][z-1]==null || typeof _map[y][x][z-1]=='undefined'));
                          var curTile;
                          while (goDown) {
                            zDown--;
                            //tileY =((x + y) * incHeight-(incZHeight*zDown))-screenY;
                            curTile=_map[y][x][zDown];
                            if (curTile!=null && typeof curTile !='undefined') {
                              canvas.putIsoSprite(tiles['batman_dshadow'],tileSX,tileSY+zHeight-(incZHeight*zDown),x,y,zDown,0,currentMapTile,tileX,tileY+(incZHeight*zDown));
                              //canvas.putIsoSprite(tiles['batman_dtest2'],tileX+currentMapTile.offsetX+offsetX,tileY+currentMapTile.offsetY+offsetY,x,y,zDown,0,currentMapTile,tileX,tileY+(incZHeight*zDown));
                              goDown=0;
                            }
                            if (zDown==0) {
                              goDown=0;
                            }  
                          }  
                        }  
                        
                        if (_DEBUG)
                          if (!confirm(tileX+' '+tileY))
                            return 0;
                      }
                    }
                  }  
                }
              }  
            }
            
            //----------------
          }          
        }
        //object methods and properties end
      }
    }(),
    //singleton end

    //singleton init
    /*
    function Canvas //let the editor source tree grab the classes
    */
    Canvas:function() {
      return {
        //object methods and properties init
        define:function(o) {
          var _cfg;
          var _sprites=[];
          var _2d;
          var _castShadows=0;
          //var _tiles=[];
          var _width,_height;

          var _zoom=1;
          _cfg=o;
          var u=Segunda.Utils;//shortcut
          var c=document.createElement('canvas');
          //what the heck happens if i set width and height???
          //c.style.width=o.x1+'px'; //wrong - alters the coordinate space
          if (typeof o.x1!='undefined')
           _width=o.x1; //tnx -> http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element
          else  
            _width=o.width;

          var _left=_top=0;
          if (typeof o.x!='undefined')
            _left=o.x;
          if (typeof o.left!='undefined')
            _left=o.left;            
          if (typeof o.y!='undefined')
            _top=o.y;
          if (typeof o.top!='undefined')
            _top=o.top;

          if (typeof o.y1!='undefined')
            _height=o.y1;
          else  
            _height=o.height;

          c.setAttribute('width',_width); //tnx -> http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element
          //c.style.height=o.y1+'px'; //wrong - alters the coordinate space
          c.setAttribute('height',_height);
          
          //c.style.border='2px solid red';

          //c.setAttribute('z-index',0);
          var p=u.choose(o.parent,document.body);
          
          //console.log(o.parent,'->',p);
          var zIndex=0;
          if (typeof o.zIndex!='undefined')
            zIndex=o.zIndex;
          var canvasContainer=u.New({zIndex:zIndex,left:_left,top:_top,width:_width,height:_height,parent:p});
          p.appendChild(canvasContainer);
          canvasContainer.appendChild(c);
          
          _2d=c.getContext("2d");
          _sprites=[];
          var _spritesIdx=0;
          //if (typeof o.tiles!='undefined')
          //  _tiles=o.tiles;
          return {
            container:canvasContainer,
            sprites:_sprites,
            context:_2d,
            width:_width,
            height:_height,
            parent:p,
            setZoom:function(iZoom) {
              if (iZoom>0.01)
                _zoom=iZoom;
              else  
                _zoom=0.01;
            },
            /*
            putSprite:function(currentSprite,sx,sy,x,y,z,isCharacter,tileObject,tileX,tileY) {
              if (currentSprite) {
                if (isCharacter && z>0) { //THANKS GOEST TO http://www.servo7.co.uk/iso/masking.aspx FOR INSPIRATION                  
                  depth=x*y*z;
                  _sprites.push({depth:(x+y)*(z+2),s:currentSprite,x:sx,y:sy,z:sy,offsetTop:0,height:10,obj:0});
                  _sprites.push({depth:(x+y)*(z+1),s:currentSprite,x:sx,y:sy+10,z:sy,offsetTop:10,height:11,obj:0});
                  _sprites.push({depth:(x+y)*z,z:z,s:currentSprite,x:sx,y:sy+20,z:sy,offsetTop:20,height:12,obj:tileObject,tileX:tileX,tileY:tileY});
                  
                  //sarebbe intessante farlo direttamente così
                  //e non usare sort sotto...
                  //_sprites[z+x+y]={depth:z+x+y,z:z,s:currentSprite,x:sx,y:sy+20,offsetTop:20,height:12,isObject:obj};
                } else { 
                  //depth=z*(x*16+y*16);
                  _sprites.push({depth:(x+y)*z,z:z,s:currentSprite,x:sx,y:sy,z:sy,obj:tileObject,tileX:tileX,tileY:tileY});
                  
                  //sarebbe intessante farlo direttamente così
                  //e non usare sort sotto...
                  //_sprites[z+x+y]={depth:z+x+y,z:z,s:currentSprite,x:sx,y:sy,isObject:obj};
                }  
              }
            },
            */
            putIsoSprite:function(currentSprite,sx,sy,x,y,z,isCharacter,tileObject,tileX,tileY) { //do not use an object as a param to increase speed
            //put an iso sprite - maybe not needed anymore - check the cutted sprite method and adjust proper tile detection instead  
              if (currentSprite) {
                var depth=x+y+z;
                if (isCharacter && z>0) { //THANKS GOES TO http://www.servo7.co.uk/iso/masking.aspx FOR INSPIRATION
                  //do a simple trick to allow current depth splitting current sprite into tree parts
                  //to-do: split basing on actual sprite height
                  _sprites.push({depth:depth+2,s:currentSprite,x:sx,y:sy   ,offsetTop:0 ,height:10,obj:0}); //set obj to 0 pushing as 'special' sprite that will not be used for collision detection
                  _sprites.push({depth:depth+1,s:currentSprite,x:sx,y:sy+10,offsetTop:10,height:11,obj:0});
                  _sprites.push({depth:depth  ,s:currentSprite,x:sx,y:sy+20,obj:tileObject,tileX:tileX,tileY:tileY,offsetTop:20,height:12});
                } else { 
                  _sprites.push({depth:depth  ,s:currentSprite,x:sx,y:sy   ,obj:tileObject,tileX:tileX,tileY:tileY});
                }
              }
            },
            
            putSpriteNew:function(o) {
              if (o) {
               var currentSprite,oX,oY,x,y,t,h;
               _sprites[_spritesIdx]=o;//{depth:o.depth,s:currentSprite,x:sx,y:sy   ,obj:tileObject,tileX:tileX,tileY:tileY});
                _spritesIdx++;

                currentSprite=o.tiles[o.spriteId];
//                  var h=o.height;
                oX=o.offsetX;
                oY=o.offsetY;
                x=o.x;
                y=o.y;
                if (typeof oX!='undefined')
                  x+=oX;
                if (typeof oY!='undefined')
                  y+=oY;
                var t=currentSprite.top;
//                  var offsetTop=o.offsetTop;

//                  if (typeof h=='undefined')
                var h=currentSprite.height;
//                  if (typeof offsetTop!='undefined')
//                    t+=offsetTop;                    
                _2d.drawImage(
                  currentSprite.image,currentSprite.left,
                  t,currentSprite.width,h,
                  x*_zoom,y*_zoom,
                  currentSprite.width*_zoom,h*_zoom
                );
              }    
            },
            
            
            putSprite:function(o) {
              if (o) { 
                if (o.staticSprite)
                  return;

                currentSprite=o.tiles[o.spriteId]; //fixme: instead of referencing the o.tiles object we could build an array lookup with all width and heights of various sprites
                if (!currentSprite)
                  return;
//                  var h=o.height;
                oX=o.offsetX;
                oY=o.offsetY;
                x=o.x;
                y=o.y;

                if (typeof oX!='undefined')
                  x+=oX;
                if (typeof oY!='undefined')
                  y+=oY;
                t=currentSprite.top;
//                  var offsetTop=o.offsetTop;

//                  if (typeof h=='undefined')
                w=currentSprite.width;
                h=currentSprite.height;
//                  if (typeof offsetTop!='undefined')
//                    t+=offsetTop;                    
                
                _2d.drawImage( //use slicing to place the sprite image
                  currentSprite.image,
                  currentSprite.left,currentSprite.top,
                  w,h,
                  x,y,
                  w,h
                );
              }  
            },           
            
            putSpriteOld:function(o) {
            //put the current object into the sprite list - need the tiles object from the specified spriteId will be chosen
            //all objects painted with putSprite are analyzed and inserted into the collision detection loop of the character object
              /*parameters obj,x,y,tiles,spriteId top,height*/
              /*
              if (typeof o.width=='undefined')
                o.width=o.tiles[o.spriteId].width;
              if (typeof o.height=='undefined')
                o.height=o.tiles[o.spriteId].height;
              */  
              //o.width=16;
              //o.height=16;
              
              //if (o)
              //  _sprites.push(o);//{depth:o.depth,s:currentSprite,x:sx,y:sy   ,obj:tileObject,tileX:tileX,tileY:tileY});
              if (o) {
                _sprites[_spritesIdx]=o;//{depth:o.depth,s:currentSprite,x:sx,y:sy   ,obj:tileObject,tileX:tileX,tileY:tileY});
                _spritesIdx++;
              }
              //_sprites.push({depth:o.depth,s:currentSprite,x:sx,y:sy   ,obj:tileObject,tileX:tileX,tileY:tileY});
            },            
            /*
            putSprite:function(currentSprite,x,y) {
              if (currentSprite) {
                var depth=0;
                  _sprites.push({depth:depth  ,s:currentSprite,x:sx,y:sy   ,obj:tileObject,tileX:tileX,tileY:tileY});
                }
              }
            },*/            
            
            paint:function(){
              return;
              //return;
            //paint the current sprite list  
              /*parameters obj,x,y,tiles,spriteId top,height*/
//              _sprites.sort(function(a,b){return a.depth - b.depth}) //thanks to http://www.javascriptkit.com/javatutors/arraysort.shtml
              var o,currentSprite,oX,oY,x,y,t,w,h;
              for (var z=0;z<_spritesIdx;z++) {
                o=_sprites[z];
                if (o.staticSprite)
                  continue;
                
                if (o) { 
                  currentSprite=o.tiles[o.spriteId]; //fixme: instead of referencing the o.tiles object we could build an array lookup with all width and heights of various sprites
//                  var h=o.height;
                  oX=o.offsetX;
                  oY=o.offsetY;
                  x=o.x;
                  y=o.y;

                  if (typeof oX!='undefined')
                    x+=oX;
                  if (typeof oY!='undefined')
                    y+=oY;
                  t=currentSprite.top;
//                  var offsetTop=o.offsetTop;

//                  if (typeof h=='undefined')
                  w=currentSprite.width;
                  h=currentSprite.height;
//                  if (typeof offsetTop!='undefined')
//                    t+=offsetTop;                    
                  
                  
                  _2d.drawImage( //use slicing to place the sprite image
                    currentSprite.image,
                    currentSprite.left,currentSprite.top,
                    w,h,
                    x,y,
                    w,h
                  );
                  
                  /*
                  _2d.drawImage(
                    currentSprite.image,currentSprite.left,
                    t,currentSprite.width,h,
                    x*_zoom,y*_zoom,
                    currentSprite.width*_zoom,h*_zoom
                  );
                  */
                  
                }    
              }
            },
            draw:function(currentSprite,x,y,e) { //directly draw to canvas > do not use an object as a param to increase speed
            //draw a sprite object directly -> avoid collision detection  
              if (currentSprite) {
                //_2d.rotate(e.clientX);
                _2d.drawImage(
                  currentSprite.image,currentSprite.left,
                  currentSprite.top,currentSprite.width,currentSprite.height,
                  x*_zoom,y*_zoom,
                  currentSprite.width*_zoom,currentSprite.height*_zoom
                );
              }
              /*
                      _2d.fillStyle = "rgb(200,0,0)";
                      _2d.fillRect (10, 10, 55, 50);
              
                      _2d.fillStyle = "rgba(0, 0, 200, 0.5)";
                      _2d.fillRect (30, 30, 55, 50);
              */              
            },
            drawFromTile:function(tiles,currentSpritetileId,x,y) { //directly draw to canvas > do not use an object as a param to increase speed
            //directyle draw a sprite from the specified tileset -> avoid collision detection  
              if (currentSpritetileId) {
                var currentSprite=tiles[currentSpritetileId];
                _2d.drawImage(
                  currentSprite.image,currentSprite.left,
                  currentSprite.top,currentSprite.width,currentSprite.height,
                  x*_zoom,y*_zoom,
                  currentSprite.width*_zoom,currentSprite.height*_zoom
                );
              }  
            },
            /*
            paint:function(){
              _sprites.sort(function(a,b){return a.depth - b.depth}) //thanks to http://www.javascriptkit.com/javatutors/arraysort.shtml
              for (var z=0,zEnd=_sprites.length;z<zEnd;z++) {
                var o=_sprites[z];
                if (o) { 
                  var currentSprite=o.spriteId;
                  var h=o.height;
                  var t=currentSprite.top;
                  var offsetTop=o.offsetTop;
                  if (typeof h=='undefined')
                    h=currentSprite.height;
                  if (typeof offsetTop!='undefined')
                    t+=offsetTop;                    
                  _2d.drawImage(
                    currentSprite.image,currentSprite.left,
                    t,currentSprite.width,h,
                    o.x*_zoom,o.y*_zoom,
                    currentSprite.width*_zoom,h*_zoom
                  );
                }    
              }
            },
            */            
            clear:function() {
            //clear the canvas  
              _spritesIdx=_sprites.length=0;
              _2d.clearRect(0,0,_width,_height);
            },
            drawRectangle:function(x,y,x1,y1) {
            //clear the canvas
              _2d.fillRect(x,y,x1,y1);
            },            
            drawLine:function(x,y,x1,y1) {
            //clear the canvas
              _2d.beginPath();
              _2d.moveTo(x,y);
              _2d.lineTo(x1,y1);
              _2d.stroke();              
            },
            setStroke:function(o) {
              _2d.strokeStyle=o;
            },
            setWidth:function(w) {
            //set canvas width  
              c.setAttribute('width',w);
              //this.paint();
            },
            setFillStyle:function(f) {
              _2d.fillStyle = f;//"rgba(0, 0, 200, 0.5)";  
            },
            setHeight:function(h) {
            //set canvas height
              c.setAttribute('height',h);
              //this.paint();
            }
          }  
        }
        //object methods and properties end
      }
    }(),
    //singleton end

    //singleton init
    /*
    function Console //let the editor source tree grab the classes
    */
    Console:function() {
      var _stopNow=1;
      return {
        //object methods and properties init
        log:function(o) {
          try {
            console.log(arguments);
          } catch (er) {
            var logData=[];
            logData.push(arguments);
            for (var nn in arguments)
              logData.push(nn+' '+arguments[nn]);
            if (_stopNow)
              _stopNow=confirm('Log\n'+logData.join('\n')+'\n\n\nShow next message?');
          }
        },
        error:function(o) {
          try {
            console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
            console.error(o)
            var errorObj=o[1];
            console.error('Filename:',errorObj.fileName);
            console.error('Line number:',errorObj.lineNumber);
            console.error('Message:',errorObj.message);
          } catch (er) {
            if (_stopNow)
              _stopNow=confirm('Error!\n'+er+'\n\n\nShow next message?');
          }
        }
        //object methods and properties end
      }
    }(),
    //singleton end

    //singleton init
    /*
   function Event //let the editor source tree grab the classes
    */
    Event:function() {
      return {
        //object methods and properties init
        launch:function(o) {
          if (o.userEvent) {
            try {
              if (typeof o.defer=='undefined')
                o.userEvent(o);
              else
                setTimeout(function() {
                  o.userEvent(o);
                },o.defer);
            } catch(er) {
              Segunda.Console.log(['error:',er,'info:',o.data])
            }  
          }
        }
        //object methods and properties end
      }
    }(),
    //singleton end

    //singleton init
    /*
   function Sprites //let the editor source tree grab the classes
    */
    Sprites:function() { //Sprites object
      var _images=[];
      var _imageCacheCount=0; //return the total number of images that has been loaded
      var _x=0;
      return {
        totalImagesToLoad:1,
        //getImageCacheCount:function(){return _imageCacheCount},
        clone:function(o) { //clone source sprites and append into destination sprites using the specified transform
          for (var z in o.source)
            1;
          var c=document.createElement('canvas');
          var W=o.source[z].image.width;
          var H=o.source[z].image.height;
          
          c.setAttribute('width',o.source[z].image.width); //tnx -> http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element
          c.setAttribute('height',o.source[z].image.height);

          if (typeof o.rotate90!='undefined' && o.rotate90) {
            c.setAttribute('width',o.source[z].image.height); //tnx -> http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element
            H=o.source[z].image.height;
            c.setAttribute('height',o.source[z].image.width);
            W=o.source[z].image.width;
          }

          //debug
          if (typeof o.debug!='undefined' && o.debug) {
            document.body.appendChild(c);
            c.style.position='absolute';
            c.style.left=_x+'px'
            _x+=o.source[z].image.width;
            c.style.top='0px'
          }  

          //c.style.border='2px solid red';
          var _2d=c.getContext("2d");
          
          for (var z in o.source) {
            var currentSprite=o.source[z];

            if (typeof o.rotate90!='undefined' && o.rotate90) {
              var x,y,rx,ry,z0b,z1b;
              for (var z1=0;z1<=o.source[z].height;z1++) {
                for (var z0=0;z0<=o.source[z].width;z0++) {
                  z0b=o.source[z].width-z0;
                  z1b=o.source[z].height-z1;
                  if (o.rotate90) {
                    if (typeof o.flipVertical=='undefined' || !o.flipVertical) {
                      if (o.flipHorizontal) {
                        x=currentSprite.left+z0;y=currentSprite.top+z1;
                        rx=y;ry=x;
                      } else {
                        x=currentSprite.left+z0b-1;y=currentSprite.top+z1b-1;
                        //rx=currentSprite.left+z0;ry=currentSprite.top+z1;
                        //rx=currentSprite.top+z1;ry=currentSprite.left+z0;
                        rx=currentSprite.top+z1;ry=x;//currentSprite.left+z0;
                      }
                    } else {
                      if (o.flipHorizontal) {
                        x=currentSprite.left+z0b-1;y=currentSprite.top+z1;
                        rx=currentSprite.top+z1;ry=currentSprite.left+z0;//;
                      } else {
                        x=currentSprite.left+z0b-1;y=currentSprite.top+z1b-1;
                        //rx=currentSprite.left+z0;ry=currentSprite.top+z1;
                        //rx=currentSprite.top+z1;ry=currentSprite.left+z0;
                        rx=currentSprite.top+z1;ry=currentSprite.left+z0;//;
                      }
                    }  
                  }
                  _2d.drawImage(
                    currentSprite.image,
                    x,y,
                    1,1,
                    rx,ry,
                    1,1
                  );
                }
              }  
              var spr={};
              spr.left=currentSprite.top;
              spr.top=currentSprite.left;
              spr.width=currentSprite.height;
              spr.height=currentSprite.width;
              spr.halfWidth=parseInt(currentSprite.height/2);
              spr.halfHeight=parseInt(currentSprite.width/2);
              spr.css=currentSprite.css;
              spr.className=currentSprite.className;
              spr.image=c; //use transformed canvas as source
              spr.name=z+o.suffix;

              spr.objLeft=currentSprite.objLeft;
              spr.objTop=currentSprite.objTop;
              spr.objWidth=currentSprite.objWidth;
              spr.objHeight=currentSprite.objHeight;
              spr.objHalfWidth=currentSprite.objHalfWidth;
              spr.objHalfHeight=currentSprite.objHalfHeight;

              o.destination[z+o.suffix]=spr;//append transformed sprite into destination
              
              
            } else {
              
              /*
               //unused....
              if (o.replaceColor) {
                var colorCanvas=document.createElement('canvas');
                c.setAttribute('width',o.source[z].image.width); //tnx -> http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element
                c.setAttribute('height',o.source[z].image.height);                
              }
              */
              
              if (o.flipHorizontal) {
                for (var z0=o.source[z].width;z0>=0;z0--) {
                  _2d.drawImage(
                    currentSprite.image,
                    currentSprite.left+z0,currentSprite.top,
                    1,currentSprite.height,
                    currentSprite.left-z0+o.source[z].width-1,currentSprite.top,
                    1,currentSprite.height
                  );
                }
              }
              if (o.flipVertical) {
                for (var z0=o.source[z].height;z0>=0;z0--) {
                  _2d.drawImage(
                    currentSprite.image,
                    currentSprite.left,currentSprite.top+z0,
                    currentSprite.width,1,
                    currentSprite.left,currentSprite.top-z0+o.source[z].height-1,
                    currentSprite.width,1
                  );
                }
              }
              var spr={};
              spr.left=currentSprite.left;
              spr.top=currentSprite.top;
              spr.width=currentSprite.width;
              spr.css=currentSprite.css;
              spr.className=currentSprite.className;
              spr.height=currentSprite.height;
              spr.halfWidth=parseInt(currentSprite.height/2);
              spr.halfHeight=parseInt(currentSprite.width/2);
              spr.image=c; //use transformed canvas as source
              spr.name=z+o.suffix;

              spr.objLeft=currentSprite.objLeft;
              spr.objTop=currentSprite.objTop;
              spr.objWidth=currentSprite.objWidth;
              spr.objHeight=currentSprite.objHeight;
              spr.objHalfWidth=currentSprite.objHalfWidth;
              spr.objHalfHeight=currentSprite.objHalfHeight;
              
              o.destination[z+o.suffix]=spr;//append transformed sprite into destination
            }
            //console.log(z)              
          }

          //FIXME FIXMEFIXMEFIXMEFIXMEFIXMEFIXMEFIXMEFIXME
          //http://sourcegear.com/fortress/stackoverflow/
          //non va su localhost!!!
          //var myImageData = _2d.getImageData(0,0,100,100);
          
          
  //pixel manipulation!!!
  //https://developer.mozilla.org/En/HTML/Canvas/Pixel_manipulation_with_canvas

/*          
  var data;
  var sx=0;
  var sy=0;
  var sw=5;
  var sh=5;
  try {
    try {
      data = _2d.getImageData(sx, sy, sw, sh).data;
    } catch (e) {
      netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
      data = _2d.getImageData(sx, sy, sw, sh).data;
    }
  } catch (e) {
    //console.error(e);
    throw new Error("unable to access image data: " + e);
  }
  console.log(data);
*/
          
          
          //http://stackoverflow.com/questions/358538/getimagedata-in-firefox-3-causing-nserrordomsecurityerr
          //http://blog.nihilogic.dk/2008/03/jsimagefx-javascript-image-effects.html
          //qui ci sono un sacco di effetti oltre a rotate e flip..
          //vedere se questi effetti si possono usare per il cloning!!!!!
          //http://www.nihilogic.dk/labs/imagefx/
          //http://74.125.77.132/search?q=cache:uqVpCxe_OZYJ:blog.nihilogic.dk/2008/03/jsimagefx-javascript-image-effects.html+getImageData+security+issue&cd=2&hl=en&ct=clnk&gl=it&client=firefox-a
          //http://stackoverflow.com/questions/358538/getimagedata-in-firefox-3-causing-nserrordomsecurityerr
          
          
          /*
          if (o.replaceColor) {
            //tnx to http://www.permadi.com/tutorial/jsCanvasGrayscale/index.html
            //sadly if we run this from local we get a security exception
            //in addition it is not working...
            //discontinued from now..
            var imageData=_2d.getImageData(0,0,W,H);
            
            for (var j=0; j<imageData.height; j++) {
              for (var i=0; i<imageData.width; i++) {
                 var index=(i*4)*imageData.width+(j*4);
                 var red=imageData.data[index];	  
                 var green=imageData.data[index+1];
                 var blue=imageData.data[index+2];	  
                 var alpha=imageData.data[index+3];	 
                 var average=(red+green+blue)/3; 	  
                 imageData.data[index]=average;	  
                 imageData.data[index+1]=average;
                 imageData.data[index+2]=average;
                 imageData.data[index+3]=alpha;
                 
                 console.log(average);
                 
               }
            }
          }
          */
          
        },
        
        setData:function(destTiles,o) {
          var _sprites=destTiles;
          var data=o.data;
          var curObj,spr;
          for (var z=0,zEnd=data.length;z<zEnd;z++) {
            //collision detection properties
            curObj=data[z];
            //console.log(curObj.id);
            spr=_sprites[curObj.id];
            if (typeof curObj.objectLeft!='undefined')
              spr.objLeft=curObj.objectLeft;
            if (typeof curObj.objectTop!='undefined')
              spr.objTop=curObj.objectTop;
            if (typeof curObj.objectHeight!='undefined') {
              spr.objHeight=curObj.objectHeight;
              spr.objHalfHeight=parseInt(curObj.objectHeight/2);
            }
            if (typeof curObj.objectWidth!='undefined') {
              spr.objWidth=curObj.objectWidth;
              spr.objHalfWidth=parseInt(curObj.objectWidth/2);
            }
          }
        },
        
        
        define:function(o) {
          var _sprites=[];
          var u=Segunda.Utils;//shortcut
          var ss=u.getStyleSheetClasses({selector:o.cssSelector,styleSheetIndex:o.styleSheetIndex}); //obtain all classes from stylesheet that match the selector filter
          
          if (o.data) {
            //console.log(ss)
            //ss.concat(o.data);
            for (var z=0,zEnd=o.data.length;z<zEnd;z++) {
              ss.push(o.data[z]);
            }  
            //console.log(ss)
          }
          
          if (!ss.length) {
            Segunda.Console.error('Sprites > define > u.getStyleSheetClasses > no result!')
            return;
          }
          
          var backgroundImage;
          var curObj;
          var bp;
          var fromCss;
          var sel;
          for (var z=0,zEnd=ss.length;z<zEnd;z++) { //iterate them
            if (typeof ss[z].style!='undefined') { 
              curObj=ss[z].style;
              fromCss=1;
              backgroundImage=curObj.backgroundImage;
            } else {
              curObj=ss[z];
              fromCss=0;
              //console.log(_sprites[curObj.id].image);
              backgroundImage=curObj.image?curObj.image:_sprites[curObj.id].backgroundImage;
            }
            backgroundImage=backgroundImage.replace('url(',''); //get background image prop from class
            backgroundImage=backgroundImage.replace(/\)$/,'');
            backgroundImage=backgroundImage.replace(/^"/,''); //removes " from background name (opera)
            backgroundImage=backgroundImage.replace(/"$/,'');
            if (u.undef(_images[backgroundImage]))
              _images[backgroundImage]={loaded:false};
            var spr={}; //create the sprite object
            spr.backgroundImage=backgroundImage;
            if (fromCss) {
              bp=ss[z].style.backgroundPosition.replace('px','')
              var pos=bp.split(' ');
              spr.left=Math.abs(parseInt(pos[0]));
              spr.top=Math.abs(parseInt(pos[1]));
              spr.width=parseInt(ss[z].style.width.replace('px',''));
              spr.height=parseInt(ss[z].style.height.replace('px',''));
              spr.css=ss[z].style.background;//ss[z].style.background;
              spr.className=ss[z].selector;
              sel=ss[z].selector.replace(/^\./,'');
              //collision detection properties
              spr.objLeft=0;
              spr.objTop=0;
              spr.objWidth=spr.width;
              spr.objHeight=spr.height;
            } else {
              //if sprite coords are not defined use props from css
              spr.left =curObj.offsetLeft?curObj.offsetLeft:_sprites[curObj.id].left;
              spr.top  =curObj.offsetTop?curObj.offsetTop:_sprites[curObj.id].top;
              spr.width=curObj.width?curObj.width:_sprites[curObj.id].width;
              spr.height=curObj.height?curObj.height:_sprites[curObj.id].height;
              sel=curObj.id;
              //collision detection properties
              spr.objLeft=curObj.objectLeft?curObj.objectLeft:0;
              spr.objTop=curObj.objectTop?curObj.objectTop:0;
              spr.objWidth=curObj.objectWidth?curObj.objectWidth:_sprites[curObj.id].width;
              spr.objHeight=curObj.objectHeight;
              
              //console.log(spr.objHeight);
            } 
            spr.halfWidth=parseInt(spr.width/2);
            spr.halfHeight=parseInt(spr.height/2);
            spr.objHalfWidth=parseInt(spr.objWidth/2);
            spr.objHalfHeight=parseInt(spr.objHeight/2);
            _sprites[sel]=spr;
            spr.name=sel;
            var img;
            
            if (!_images[backgroundImage].loaded) { //create a new image object and cache the sprite main image only once
              //console.log('load new '+backgroundImage+' '+o.onLoad);
              img=new Image();
              var that=this;
              img.src=backgroundImage;
              //document.body.appendChild(img);
              _images[backgroundImage].img=img;
              _images[backgroundImage].loaded=1;
              img.onload=function(_tempCfg){
                _imageCacheCount++;
                _images[backgroundImage].ready=1;
                Segunda.Event.launch({userEvent:o.onLoad});
                //console.log(that.totalImagesToLoad+' '+_imageCacheCount);
                if (that.totalImagesToLoad==_imageCacheCount)
                  Segunda.Event.launch({defer:10,userEvent:Segunda.Sprites.onReady}); //launch with new thread so we have time to finalize image loading
              };
            } else {
              img=_images[backgroundImage].img;
            }
            spr.image=img;
          }
          
          return _sprites;
        }
      }
    }(),
    //singleton end

/*    
    //singleton init
    Cube:function() {
      return {
        //object methods and properties init
        define:function() {
          
        }  
        //object methods and properties end
      }
    }(),
    //singleton end
*/
    //singleton init
    /*
    function Character //let the editor source tree grab the classes
    */
    Character:function() { //Character object
      var _cfg;
      var _characters=[];      
      return {
        //object methods and properties init
//disabled if enabled don't forget the callback method down there..
        paint:function(o) {
          for (var z=0,zEnd=_characters.length;z<zEnd;z++) {
            _characters[z].paint();
          }
          //once all characters has been painted we can cycle
          //to detect all collisions
          //this can be done only when all sprites are already
          //assigned to the canvas for consistence
          for (var z=0,zEnd=_characters.length;z<zEnd;z++) {
            _characters[z].animate();
          }
        },
        define:function(o) {
          var u=Segunda.Utils;//shortcut
          var _cfg=o;
          var _ai=o.ai;
          var _anim=[];
          var _currentAnimationSid=o.defaultAnimation;
          var _frame=0; //sprite animation frame index
          var _timer=0; //sprite animation timer index
          var _offsetX=u.choose(o.offsetX,0);
          var _hox=_offsetX;
          var _offsetY=u.choose(o.offsetY,0);
          var _dx,_dy;
          var _hoy=_offsetY;
          var _screenX,_screenY; //used to restore previous coordinates in collision detection
          var _tile_h=0;
          var _tile_zh=0;
          var _paused=0; //if current character animation paused?
          if (_cfg.iso) {
            _tile_h=_cfg.iso.tileYStep;
            _tile_zh=_cfg.iso.tileZStep;
          }  
          var _hoz=((o.z-1)*_tile_zh);
          var _speedX=2;
          var _speedY=1;
          var _jumpLevel=1;
          var _fallLevel=1;
          var _z=0;
          if (u.def(o.z))
            _z=o.z;
          
          //var _xDim=o.width;
          //var _yDim=o.width;  
          
          //console.log(_currentAnimationSid);
          //_frame=0;
          //_timer=0;
          for (var z=0,zEnd=o.animations.length;z<zEnd;z++) {
            var sid=o.animations[z].id;
            //console.log(o.animations[z]);
            _anim[sid]={};            
            _anim[sid]=u.d(_anim[sid],o.animations[z]);
            //console.log(_anim[sid]);
          }

          var _paint=function(idx) {
            _characters[idx].paint();
          }
          var _makePaintCallback=function(idx) { //function factory used to have valid functions arguments when using closures inside loops tnxs https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Closures see Creating closures in loops: A common mistake
            return function() {
              _paint(idx);
            }
          }

          var coords={};
          if (_cfg.iso) {
            _cfg.iso.enabled=1;
            coords=_cfg.iso.getScreenCoordinates({x:o.x,y:o.y,z:o.z});
          } else {
            coords.x=o.x;
            coords.y=o.y;
            //Segunda.console.log(o.canvas);
            _speedX=1;
            _speedY=1;
            if (u.def(o.speed))
              _speedX=_speedY=o.speed;
            if (u.def(o.speedX))
              _speedX=o.speedX;
            if (u.def(o.speedY))
              _speedY=o.speedY;
            _cfg.iso={ //set fake iso data
              hXdim:_cfg.width/2,
              hYdim:_cfg.height/2,
              canvas:o.canvas,
              set:function(){},
              get:function(){},
              del:function(){},
              enabled:0
            }
          }
          
          //calculate sprite size as multiple in map tile blocks
          /*
          console.log(Math.ceil(o.width/o.map.tileWidth)*o.map.tileWidth);
          console.log(Math.ceil(o.height/o.map.tileHeight)*o.map.tileHeight);
          */
          //calculate sprite size as multiple in map tile blocks
          //used for collision detection
          var _tiledWidth=Math.ceil(o.width/o.map.tileWidth)*o.map.tileWidth;
          var _tiledHeight=Math.ceil(o.height/o.map.tileHeight)*o.map.tileHeight;

          var _return=u.d(o,{ //keep user-defined properties 
            currentAnimation:o.defaultAnimation,
            //screenX:coords.x,   //screen x coordinate
            //screenY:coords.y,  //screen y coordinate
            onCollision:o.onCollision,
            tiles:o.tiles,
            hit:null,
            dir:null,
            x:o.x,       //isometric x position
            y:o.y,       //isometric y position            
            width:o.width,
            height:o.height,
            //calculate sprite size as multiple in map tile blocks
            //used for collision detection
            tiledWidth:_tiledWidth,
            tiledHeight:_tiledHeight,
            //use normalized size to determine collision detection size in blocks
            blocksWidth:parseInt(_tiledWidth/o.map.tileWidth)+1,
            blocksHeight:parseInt(_tiledHeight/o.map.tileHeight)+1,
            
            halfWidth:parseInt(o.width/2),
            halfHeight:parseInt(o.height/2),
            sx:o.x,
            sy:o.y,
            sz:o.z,
            z:_z,       //isometric z position
            dx:o.x,      //isometric destination
            dy:o.y,
            dz:o.z-1,
            xDim:o.xDim, //dimension in pixels
            yDim:o.yDim,
            zDim:o.zDim,
            speedX:_speedX,   //speed in pixels
            speedY:_speedY,
//            width:o.width,   //debug use it?
//            height:o.height, //debug use it?
            offsetX:coords.x+_offsetX,  //init offsetX with proper screen position based on current tile - screen position left
            offsetY:coords.y+_offsetY,  //init offsetY with proper screen position based on current tile - screen position top
            offsetZ:0,
            hitLeft:null,
            hitRight:null,
            hitTop:null,
            hitDown:null,

            //discontinued??? can be deleted? fixme
            checkCollisions:function(characterX,characterY,xd2,yd2,obj_tile_x,obj_tile_y,otw2,oth2,currentObj) {
              //check if a collision occurs between character coords and object coords
              //thanks goes to frjanibo > http://code.google.com/p/isogame/
              //return;
              
  /*
                        hitT =this.checkCollision(characterX,characterY-this.speedY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height,currentObj);
                        hitB =this.checkCollision(characterX,characterY+this.speedY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height,currentObj);
                        hitL =this.checkCollision(characterX-this.speedX,characterY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height,currentObj);
                        hitR =this.checkCollision(characterX+this.speedX,characterY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height,currentObj);
  */            
              var sx=this.speedX;
              var sy=this.speedY;
              
              var sum_x= xd2 + otw2;
              var sum_y= yd2 + oth2;
            
              var centro_x1a = characterX + xd2; 
              var centro_x1b = centro_x1a + sx; 
              var centro_x1c = centro_x1a - sx; 
  
              var centro_y1a = characterY + yd2;
              var centro_y1b = centro_y1a + sy;
              var centro_y1c = centro_y1a - sy;
  
              var centro_x2 = obj_tile_x + otw2;
              var centro_y2 = obj_tile_y + oth2;
                
              //var delta_x,delta_y;
              
              //delta_x = Math.abs( centro_x1a - centro_x2 );
              if ( Math.abs(centro_x1a-centro_x2) <= sum_x) {
                if ( Math.abs(centro_y1c-centro_y2) <= sum_y) {
                  this.hitObjectsTop.push(currentObj);
                  if (!this.hitTop)
                    this.hitTop=currentObj;                    
                } else {
                  if (Math.abs(centro_y1b-centro_y2) <= sum_y) {
                    this.hitObjectsBottom.push(currentObj);
                    if (!this.hitBottom)
                      this.hitBottom=currentObj;                
                  }  
                }
              } else {
                if ( Math.abs(centro_y1a-centro_y2) <= sum_y ) {
                  if ( Math.abs(centro_x1c-centro_x2) <= sum_x) {
                    this.hitObjectsLeft.push(currentObj);                
                    if (!this.hitLeft)
                      this.hitLeft=currentObj;                    
                  } else {
                    if ( Math.abs(centro_x1b-centro_x2) <= sum_x) {
                      this.hitObjectsRight.push(currentObj);                
                      if (!this.hitRight)
                        this.hitRight=currentObj;                      
                    }
                  }
                }
              }
  
  
/*
              delta_x = Math.abs( centro_x1a - centro_x2 );
              delta_y = Math.abs( centro_y1c - centro_y2 );
              if( (delta_x <= sum_x) && (delta_y <= sum_y)) {
                //a=currentObj;
                this.hitObjectsTop.push(currentObj);
                if (!this.hitTop)
                  this.hitTop=currentObj;                
              }
  
              delta_y = Math.abs( centro_y1b - centro_y2 );
              if( (delta_x <= sum_x) && (delta_y <= sum_y)) {
                this.hitObjectsBottom.push(currentObj);
                if (!this.hitBottom)
                  this.hitBottom=currentObj;                
              }
  
              delta_x = Math.abs( centro_x1c - centro_x2 );
              delta_y = Math.abs( centro_y1a - centro_y2 );
              if( (delta_x <= sum_x) && (delta_y <= sum_y)) {
                this.hitObjectsLeft.push(currentObj);                
                if (!this.hitLeft)
                  this.hitLeft=currentObj;
              }
  
              delta_x = Math.abs( centro_x1b - centro_x2 );
              if( (delta_x <= sum_x) && (delta_y <= sum_y)){
                this.hitObjectsRight.push(currentObj);                
                if (!this.hitRight)
                  this.hitRight=currentObj;
              }
*/
            
            },

            
            checkCollision:function(characterX,characterY,xd2,yd2,obj_tile_x,obj_tile_y,otw2,oth2,currentObj) {
            //check if a collision occurs between character coords and object coords
              //return;
              /*
              var xd2=parseInt(_xDim/2);
              var yd2=parseInt(_yDim/2);
              var otw2=parseInt(obj_tile_width/2);
              var oth2=parseInt(obj_tile_height/2);
              */
              
              //console.log(characterX,characterY,xd2,yd2,' ',obj_tile_x,obj_tile_y,otw2,oth2,currentObj);

              if (0) {                
                var sid0='pachy';
                ddd=document.getElementById(sid0);
                if (!ddd) {
                  ddd=document.createElement('div');
                  ddd.id=sid0;
                  ddd.style.position='absolute';
                  gameWindow.content.appendChild(ddd);
                  ddd.style.background='red';
                }
                ddd.style.left=characterX+'px';
                ddd.style.top=characterY+'px';
                ddd.style.width=(xd2*2)+'px';
                ddd.style.height=(yd2*2)+'px';
                
                var sid='collision'+obj_tile_x+obj_tile_y+otw2+oth2;
                ddd=document.getElementById(sid);
                if (!ddd) {
                  ddd=document.createElement('div');
                  ddd.id=sid;
                  ddd.style.position='absolute';
                  ddd.style.left=obj_tile_x+'px';
                  ddd.style.top=obj_tile_y+'px';
                  ddd.style.width=(otw2*2)+'px';
                  ddd.style.height=(oth2*2)+'px';
                  ddd.style.background='blue';
                  gameWindow.content.appendChild(ddd);
                }
              }  

              var sum_x= xd2 + otw2;
              var sum_y= yd2 + oth2;
            
              var centro_x1 = characterX + xd2; //thanks goes to frjanibo > http://code.google.com/p/isogame/
              var centro_y1 = characterY + yd2;
              //var centro_z1 = theCharacter.z + (this.yDim/2);
              //current object coords
              var centro_x2 = obj_tile_x + otw2;
              var centro_y2 = obj_tile_y + oth2;
              //console.log(_cfg.iso.xDim,' ',_cfg.iso.yDim);
              //var centro_z2 = currentObj.z + (_cfg.iso.yDim/2);
              var delta_x = Math.abs( centro_x1 - centro_x2 );
              var delta_y = Math.abs( centro_y1 - centro_y2 );

              if( (delta_x <= sum_x) && (delta_y <= sum_y))
                return currentObj;
              else
                return 0;               
            },
            
            
            checkCollisionsTop:function() {
              var characterX=this.x;
              var characterY=this.y;
              var sx=this.speedX;
              var sy=this.speedY;
              var o;
              this.hitObjectsTop=[];
              for (var z=0;z<this.blocksWidth;z++) {
                o=this.map.get(characterX+(this.map.tileWidth*z),characterY-sy);
//                console.log(o);
                if (o) {
                  //console.log(o);
//                  if (this.checkCollision(characterX,characterY-sy,this.halfWidth,this.halfHeight,o.x+o.offsetX+o.objLeft,o.y+o.offsetY+o.objTop,o.spriteHalfWidth,o.spriteHalfHeight,1)) {
                  if (this.checkCollision(characterX,characterY-sy,this.halfWidth,this.halfHeight,o.x+o.offsetX+o.spriteObj.objLeft,o.y+o.offsetY+o.spriteObj.objTop,o.spriteObj.objHalfWidth,o.spriteObj.objHalfHeight,1)) {
                    this.hitObjectsTop.push(o);
                    this.hitTop=o;
                  }  
                }
              }              
              for (var z=0;z<_characters.length;z++) {
                o=_characters[z];
                if (o==this)
                  continue;
                if (o) {
                  if (this.checkCollision(characterX,characterY-sy,this.halfWidth,this.halfHeight,o.x,o.y,o.halfWidth,o.halfHeight,1)) {
                    this.hitObjectsTop.push(o);
                    this.hitTop=o;
                  }  
                }
              }
            },
            
            checkCollisionsBottom:function() {
              var characterX=this.x;
              var characterY=this.y;
              var sx=this.speedX;
              var sy=this.speedY;
              var o;
              this.hitObjectsBottom=[];
              for (var z=0;z<this.blocksWidth;z++) {
                o=this.map.get(characterX+(this.map.tileWidth*z),characterY+this.height+sy);
                if (o) {
                  //if (this.checkCollision(characterX,characterY+sy,this.halfWidth,this.halfHeight,o.x+o.offsetX,o.y+o.offsetY,o.spriteHalfWidth,o.spriteHalfHeight,1)) {
                  //console.log(o.spriteObj);
                  if (this.checkCollision(characterX,characterY+sy,this.halfWidth,this.halfHeight,o.x+o.offsetX+o.spriteObj.objLeft,o.y+o.offsetY+o.spriteObj.objTop,o.spriteObj.objHalfWidth,o.spriteObj.objHalfHeight,1)) {
                    this.hitObjectsBottom.push(o);
                    this.hitBottom=o;
                  }  
                }
              }

              for (var z=0;z<_characters.length;z++) {
                o=_characters[z];
                if (o==this)
                  continue;
                if (o) {
                  if (this.checkCollision(characterX,characterY+sy,this.halfWidth,this.halfHeight,o.x,o.y,o.halfWidth,o.halfHeight,1)) {
                    this.hitObjectsBottom.push(o);
                    this.hitBottom=o;
                  }  
                }
              }

            },            

            checkCollisionsLeft:function() {
              var characterX=this.x;
              var characterY=this.y;
              var sx=this.speedX;
              var sy=this.speedY;
              var o;
              this.hitObjectsLeft=[];
              for (var z=0;z<this.blocksHeight;z++) {
                o=this.map.get(characterX-sx,characterY+(this.map.tileHeight*z));                
                if (o) {
                  if (this.checkCollision(characterX-sx,characterY,this.halfWidth,this.halfHeight,o.x+o.offsetX+o.spriteObj.objLeft,o.y+o.offsetY+o.spriteObj.objTop,o.spriteObj.objHalfWidth,o.spriteObj.objHalfHeight,1)) {
                    this.hitObjectsLeft.push(o);
                    this.hitLeft=o;
                  }  
                } 
              }
              
              for (var z=0;z<_characters.length;z++) {
                o=_characters[z];
                if (o==this)
                  continue;               
                if (o) {
                  if (this.checkCollision(characterX-sx,characterY,this.halfWidth,this.halfHeight,o.x,o.y,o.halfWidth,o.halfHeight,1)) {
                    this.hitObjectsLeft.push(o);
                    this.hitLeft=o;
                  }  
                } 
              }              
            }, 
            
            checkCollisionsRight:function() {
              var characterX=this.x;
              var characterY=this.y;
              var sx=this.speedX;
              var sy=this.speedY;
              var o;
              this.hitObjectsRight=[];
              for (var z=0;z<this.blocksHeight;z++) {
                o=this.map.get(characterX+this.width+sx,characterY+(this.map.tileHeight*z));
                if (o) {
                  if (this.checkCollision(characterX+sx,characterY,this.halfWidth,this.halfHeight,o.x+o.offsetX+o.spriteObj.objLeft,o.y+o.offsetY+o.spriteObj.objTop,o.spriteObj.objHalfWidth,o.spriteObj.objHalfHeight,1)) {
                    this.hitObjectsRight.push(o);
                    this.hitRight=o;
                  }  
                }
              }

              for (var z=0;z<_characters.length;z++) {
                o=_characters[z];
                if (o==this)
                  continue;  
                if (o) {
                  if (this.checkCollision(characterX+sx,characterY,this.halfWidth,this.halfHeight,o.x,o.y,o.halfWidth,o.halfHeight,1)) {
                    this.hitObjectsRight.push(o);
                    this.hitRight=o;
                  }  
                }
              }

            },              
            
            getCoords:function() {
              
              return;
              
              var characterX=this.x;
              var characterY=this.y;
              var sx=this.speedX;
              var sy=this.speedY;
              /*
              if (sx<this.map.tileWidth)
                sx=this.map.tileWidth;
              if (sy<this.map.tileHeight)
                sy=this.map.tileHeight;
              */  
              
              //this.hitObjectsTop    =this.map.get(characterX,characterY-this.speedY);
              //this.hitObjectsBottom =this.map.get(characterX,characterY+this.speedY);
              this.hitObjectsLeft=[];
              this.hitObjectsRight=[];
              this.hitObjectsTop=[];
              this.hitObjectsBottom=[];
              
              var o;

              for (var z=0;z<parseInt(this.height/this.map.tileHeight)+1;z++) {
                o=this.map.get(characterX-sx,characterY+(this.map.tileHeight*z),z);                
                if (o) {
                  if (this.checkCollision(characterX-sx,characterY,this.halfWidth,this.halfHeight,o.x,o.y,o.halfWidth,o.halfHeight,1)) {
                    this.hitObjectsLeft.push(o);
                    this.hitLeft=o;
                  }  
                }  
                o=this.map.get(characterX+this.width+sx,characterY+(this.map.tileHeight*z),z);
                if (o) {
                  if (this.checkCollision(characterX+sx,characterY,this.halfWidth,this.halfHeight,o.x,o.y,o.halfWidth,o.halfHeight,1)) {
                    this.hitObjectsRight.push(o);
                    this.hitRight=o;
                  }  
                }
              }
              
              for (var z=0;z<parseInt(this.width/this.map.tileWidth)+1;z++) {
                o=this.map.get(characterX+(this.map.tileWidth*z),characterY-sy,z);
                if (o) {
                  if (this.checkCollision(characterX,characterY-sy,this.halfWidth,this.halfHeight,o.x,o.y,o.halfWidth,o.halfHeight,1)) {
                    this.hitObjectsTop.push(o);
                    this.hitTop=o;
                  }  
                }
                o=this.map.get(characterX+(this.map.tileWidth*z),characterY+this.height+sy,z*3);
                if (o) {
                  if (this.checkCollision(characterX,characterY+this.height+sy,this.halfWidth,this.halfHeight,o.x,o.y,o.halfWidth,o.halfHeight,1)) {
                    this.hitObjectsBottom.push(o);
                    this.hitBottom=o;
                  }  
                }
              }  
              //this.hitLeft=this.hitObjectsLeft=this.map.get(characterX-this.speedX,characterY+5);
              //this.hitObjectsRight  =this.map.get(characterX+this.speedX,characterY);
              
              /*
              console.log(this.hitObjectsLeft);
              
              var collisionChecks=[
                this.map.get(characterX,characterY-this.speedY),
                this.map.get(characterX,characterY+this.speedY),
                this.map.get(characterX-this.speedX,characterY),
                this.map.get(characterX+this.speedX,characterY)
              ];
              
              this.hitObjects=collisionChecks;
              
              this.hitTop=collisionChecks[0];
              this.hitBottom=collisionChecks[1];
              this.hitLeft=collisionChecks[2];
              this.hitRight=collisionChecks[3];

              */

            },  

            getCoordsOld:function() { //get character coordinates and do collision detection
              
              //console.log(this.id,' ',this.sx,' ',this.width);
              
              var DEBUG=0;
              var characterX=this.x;
              var characterY=this.y;
              
              if (_cfg.iso.enabled) {
                var pixel_x=this.offsetX-_hox; //get character coordinates in pixels
                var pixel_y=this.offsetY-_hoy+_hoz;
                var pixel_z=this.offsetZ-_hoz;
                var screenTile_x=tile_x=characterX;
                var screenTile_y=tile_y=characterY;

                tile_x=Math.round((pixel_x/_speedX + pixel_y/_speedY)/2)+_hox; //convert character screen coordinates to tile coordinates - divide by 2 for better rounding
                tile_y=Math.round((pixel_y/_speedY - pixel_x/_speedX)/2)-_hoy;
                screenTile_x=tile_x*2; //mul by 2 to obtain real coord
                screenTile_y=tile_y*2;
                characterX=Math.round(tile_x/_cfg.iso.hXDim); //convert tile coordinates to tile position [discrete]
                characterY=Math.round(tile_y/_cfg.iso.hYDim); //we divide by half of the iso width and height since we have already divided by two
              }

              //collision detection code init
              var objs=_cfg.iso.canvas.sprites;//get every object painted on current frame from current canvas
              
              var currentSprite=this.tiles[this.spriteId];
              var _xDim=currentSprite.halfWidth;
              var _yDim=currentSprite.halfHeight;
              
              if (this.width)
                _xDim=this.halfWidth;
              if (this.height)
                _yDim=this.halfHeight;
                
              //console.log(_xDim,_yDim,' ',currentSprite,_xDim,currentSprite.halfWidth,currentSprite.halfHeight);

              var d,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height;
              //var hitObject=0;
              //collisionDeltaX,collisionDeltaY;
              //this.hitObject=null;
              this.hitObject=this.hitLeft=this.hitRight=this.hitBottom=this.hitTop=0;
              this.hitObjectsLeft=[];
              this.hitObjectsRight=[];
              this.hitObjectsTop=[];
              this.hitObjectsBottom=[];
              var currentObj,currentObjWidth,currentObjHeight;
              
              
              
              for (var z=0,zEnd=objs.length;z<zEnd;z++) { //iterate for every object we have in the scene
                currentObj=objs[z]; //save current object
                currentObjWidth=currentObj.halfWidth;
                currentObjHeight=currentObj.halfHeight;
                currentSprite=this.tiles[currentObj.spriteId];
                if (currentObj.obj) { //if this is not a special object (see canvas.putsIsoprite)
                  //inpect objects on the same level
                  //console.log(currentObj);
                  
                  if (currentObj.z==this.z) { //if this object z === our character z

                    if (DEBUG) {
                      d=document.getElementById('cuby'+z);
                      if (!d) {
                        d=document.createElement('div');
                        d.id='cuby'+z;
                        d.style.position='absolute';                        
                        u.$('mingodiv').appendChild(d);
                      }
                    }

                    if (_cfg.iso.enabled) {
                      obj_tile_x = Math.round(((currentObj.tileX)/2 + currentObj.tileY));
                      obj_tile_y = Math.round((currentObj.tileY - currentObj.tileX/2));
                      obj_tile_width=_cfg.iso.xDim;
                      obj_tile_height=_cfg.iso.yDim;
                    } else {
                      obj_tile_x=currentObj.x;
                      obj_tile_y=currentObj.y;
                      //take width from current tile sprite
                      obj_tile_width=currentSprite.halfWidth;
                      obj_tile_height=currentSprite.halfHeight;
                      //if specific width and height are defined
                      //use them for collision detection instead
                      if (currentObjWidth)
                        obj_tile_width=currentObjWidth;
                      if (currentObjHeight)
                        obj_tile_height=currentObjHeight;
                    }  
                    
                    if (DEBUG) {                        
                      //console.log(obj_tile_x,' ',obj_tile_y,' ',currentObj.width,' ',currentObj.height);                        
                      d.style.left=(obj_tile_x)+'px';
                      d.style.top=(obj_tile_y)+'px';
                      d.style.width=currentSprite.width+'px';
                      d.style.height=currentSprite.height+'px';
                      d.style.background='blue';
                      
                      if (currentObj.obj.id=='msPacman') {
                        d.style.background='red';
                        d.style.width=_xDim+'px';
                        d.style.height=_yDim+'px';
                        //console.log(currentObj.momy);
                      //d.style.visibility='visible';
                      }
                    }  

                    //var hit     =this.checkCollision(characterX,characterY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height);
                    //var hitt=0;

                    //console.log(obj_tile_width,obj_tile_height,' ',currentSprite.halfWidth,currentSprite.halfHeight,currentObj.halfWidth,currentObj.halfHeight);

                    var hitT=hitB=hitL=hitR=0;
                    
                    if (currentObj.obj!=this) { //if current object is not our current character
                      
/*
                      hitT =this.checkCollision(characterX,characterY-this.speedY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height,currentObj);
                      hitB =this.checkCollision(characterX,characterY+this.speedY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height,currentObj);
                      hitL =this.checkCollision(characterX-this.speedX,characterY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height,currentObj);
                      hitR =this.checkCollision(characterX+this.speedX,characterY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height,currentObj);

                      if (hitT)
                        this.hitObjectsTop.push(hitT);
                      if (hitB)
                        this.hitObjectsBottom.push(hitB);
                      if (hitL)
                        this.hitObjectsLeft.push(hitL);
                      if (hitR)
                        this.hitObjectsRight.push(hitR);

                      if (!this.hitTop && hitT)
                          this.hitTop=hitT;
                      if (!this.hitBottom && hitB)
                        this.hitBottom=hitB;
                      if (!this.hitLeft && hitL)
                        this.hitLeft=hitL;
                      if (!this.hitRight && hitR)
                        this.hitRight=hitR;
*/

                      //var hits=[0,0,0,0];
                      /*
                      var xEncumbrance=characterX+_xDim;
                      var yEncumbrance=characterY+_yDim;
                      
                      var obj_xEncumbrance=obj_tile_x+obj_tile_width;
                      var obj_yEncumbrance=obj_tile_y+obj_tile_height;
                      
                      if (obj_xEncumbrance>characterX-this.speedX)
                      */
                      
                      this.checkCollisions(characterX,characterY,_xDim,_yDim,obj_tile_x,obj_tile_y,obj_tile_width,obj_tile_height,currentObj); 
                      
                      /*
                      hitT=hits[0];
                      hitB=hits[1];
                      hitL=hits[2];
                      hitR=hits[3];
                      */


                    }  

                  }
                }  
              }
              
              /*
              if (this.hitLeft || this.hitRight || this.hitTop || this.hitBottom) { //if current character has hit something
                if (u.def(this.onCollision)) 
                  this.onCollision(this);
              }
              */

              if (DEBUG && this.id=='msPacman') {
                var html=[];
                html.push('hit     : '+this.hit);
                html.push('dir     : '+this.dir);
                html.push('l       : '+this.hitLeft);
                html.push('r       : '+this.hitRight);
                html.push('t       : '+this.hitTop);
                html.push('b       : '+this.hitBottom);
                html.push('sx      : '+this.speedX);
                html.push('sy      : '+this.speedY);
                html.push('hit?    : '+this.hitObject);
//                html.push('hit                : '+collisionDeltaX);
//                html.push('hit                : '+collisionDeltaY);
                //html.push('z                : '+(-Math.round(this.offsetZ/_tile_zh)));
                //html.push('z                : '+this.z);
                //html.push('x                : '+this.x);
                //html.push('y                : '+this.y);
                //html.push('char x           : '+tile_x);
                //html.push('char y           : '+tile_y);
                //html.push('character [violet]: '+characterX+','+characterY);
                u.$('debug0').innerHTML='<pre>'+html.join('<br>')+'</pre>';                  
              }    

              /*
              var currentObj;
              for (var z=0,zEnd=objs.length;z<zEnd;z++) { //iterate for every object we have in the scene
                currentObj=objs[z]; //save current object
                if (currentObj.obj) { //if this is not a special object (see canvas.putsIsoprite)
                  //inspect the terrain object
                  if (currentObj.obj.z==this.z-1 && currentObj.obj.y==this.x && currentObj.obj.x==this.y) {
                    if (DEBUG) {  
                      var d0=document.getElementById('cubyzp');
                      if (!d0) {
                        d0=document.createElement('div');
                        d0.id='cubyzp';
                        d0.style.position='absolute';                        
                        u.$('mingodiv').appendChild(d0);
                      }
                      var d=document.getElementById('cubyz'+z);
                      if (!d) {
                        d=document.createElement('div');
                        d.id='cubyz'+z;
                        d.style.position='absolute';                        
                        u.$('mingodiv').appendChild(d);
                      }
                    }  
                    var obj_tile_x = Math.round(((currentObj.tileX)/2 + currentObj.tileY));
                    var obj_tile_y = Math.round((currentObj.tileY - currentObj.tileX/2));

                    if (DEBUG) {  
                      d.style.left=(170+(obj_tile_x))+'px';
                      d.style.top=((pixel_z+16))+'px';
                      d.style.width='16px';
                      d.style.height='16px';
                      d.style.background='maroon';

                      d0.style.left=(170+(screenTile_x))+'px';
                      d0.style.top=((pixel_z))+'px';
                      d0.style.width='16px';
                      d0.style.height='16px';
                      d0.style.background='magenta';

                      //d.style.visibility='visible';
                    }  
                  }
                  //inpect objects on the same level
                  if (currentObj.obj.z==this.z) { //if this object z === our character z
                    
                    if (currentObj.obj!=this) { //if this object is not our character
                      
                      if (DEBUG) {  
                        var d=document.getElementById('cuby'+z);
                        if (!d) {
                          d=document.createElement('div');
                          d.id='cuby'+z;
                          d.style.position='absolute';                        
                          u.$('mingodiv').appendChild(d);
                        }
                      }  
                      var obj_tile_x = Math.round(((currentObj.tileX)/2 + currentObj.tileY));
                      var obj_tile_y = Math.round((currentObj.tileY - currentObj.tileX/2));
                      
                      if (DEBUG) {  
                        d.style.left=(obj_tile_x)+'px';
                        d.style.top=(obj_tile_y)+'px';
                        d.style.width='16px';
                        d.style.height='16px';
                        d.style.background='blue';
                        //d.style.visibility='visible';
                      }  
                      
                      //character coords
                      var centro_x1 = screenTile_x + (this.xDim/2); //thanks goes to frjanibo > http://code.google.com/p/isogame/
                      var centro_y1 = screenTile_y + (this.yDim/2);
                    	//var centro_z1 = theCharacter.z + (this.yDim/2);
                      //current object coords
                      var centro_x2 = obj_tile_x + (_cfg.iso.xDim/2);
                      var centro_y2 = obj_tile_y + (_cfg.iso.yDim/2);
                      //console.log(_cfg.iso.xDim,' ',_cfg.iso.yDim);
                  		//var centro_z2 = currentObj.z + (_cfg.iso.yDim/2);

                      var delta_x = Math.abs( centro_x1 - centro_x2 );
                      var delta_y = Math.abs( centro_y1 - centro_y2 );
                    	//var delta_z = Math.abs( centro_z1 - centro_z2 );
                  
                      var sum_x = (this.xDim/2) + (_cfg.iso.xDim/2);
                      var sum_y = (this.yDim/2) + (_cfg.iso.yDim/2);
                   		//var sum_z = (this.yDim/2) + (_cfg.iso.yDim/2);
                          
                      if( (delta_x <= sum_x) && (delta_y <= sum_y)) {
                        d.style.background='orange';
                        this.offsetX=_screenX;
                        this.offsetY=_screenY;
                        //this.collidesDir=this.dir;
                        //return;
                      }


                    }
                  }
                }  
              }  

              //settds();
              
              if (DEBUG) {
                var html=[];
                html.push('z                : '+(-Math.round(this.offsetZ/_tile_zh)));
                html.push('z                : '+this.z);
                html.push('x                : '+this.x);
                html.push('y                : '+this.y);
                html.push('char x           : '+tile_x);
                html.push('char y           : '+tile_y);
                html.push('character [violet]: '+characterX+','+characterY);
                u.$('debug0').innerHTML='<pre>'+html.join('<br>')+'</pre>';                  
              }

              _cfg.iso.del([this.z,this.x,this.y]);
              this.x=characterX;
              this.y=characterY;
              this.z=(-Math.ceil(this.offsetZ/_tile_zh))+o.z;
              if (this.z<0)
                this.z=0;
              //var terrainTile;
              var terrainTile=_cfg.iso.get([this.z-1,this.x,this.y]);
              //console.log(o.z,terrainTile);
              //if (!terrainTile)
              //  this.fall();
              
              if (DEBUG)
                u.$('tdg'+this.x+this.y).style.background='magenta';
            */    

//DISABILITATO!!!!              //this.animate();
            },  
            
            fly:function(o) {
              this.offsetZ--;
              this.getCoords();
              this.jumping=1;
              switch (this.dir) {
                
              }
            },
            jump:function(o) {
              this.jumping=1;
              _screenX=this.offsetX;
              _screenY=this.offsetY;
            },            
            fall:function(o) {
              if (!this.jumping) {
                this.offsetZ+=1;//_fallLevel;
                _fallLevel++;
              }
              _screenX=this.offsetX;
              _screenY=this.offsetY;
              //this.getCoords();  
              switch (this.dir) {
                
              }
            },
            
            canMove:function(sDir) { //check if movement to specified dir is allowed
              var _canMove=0;
              
              switch (sDir) {
                case 'top':
                  this.checkCollisionsTop();
                  if (this.hitTop) {
                    this.hitObject=this.hitTop;
                    this.hitObjects=this.hitObjectsTop;
                    if (this.onCollision(this))
                      _canMove=1;
                  } else {
                    _canMove=1;
                  }
                break;
                case 'bottom':
                  this.checkCollisionsBottom();
                  if (this.hitBottom) {
                    this.hitObject=this.hitBottom;
                    this.hitObjects=this.hitObjectsBottom;
                    if (this.onCollision(this))
                      return 1;
                  } else {
                    _canMove=1;
                  }
                break;
                case 'left':
                  this.checkCollisionsLeft();
                  if (this.hitLeft) {
                    this.hitObject=this.hitLeft;
                    this.hitObjects=this.hitObjectsLeft;
                    if (this.onCollision(this))
                      return 1;
                  } else {
                    _canMove=1;
                  }
                break;  
                case 'right':
                  this.checkCollisionsRight();
                  if (this.hitRight) {
                    this.hitObject=this.hitRight;
                    this.hitObjects=this.hitObjectsRight;
                    if (this.onCollision(this))
                      return 1;
                  } else {
                    _canMove=1;
                  }
                break;  
              }
              return _canMove;
            },
            
            paused:_paused,
            
            pause:function(o) { /*pauses the character (animation)*/
              this.paused=_paused=1;
            },

            play:function(o) { /*pauses the character (animation)*/
              this.paused=_paused=0;
            },
            
            moveLeft:function(o) { //move character to the left
              var move=1;
              this.checkCollisionsLeft();
              if (this.hitLeft) {
                this.hitObject=this.hitLeft;
                //console.log('hit!',this.hitObject);
                
                this.hitObjects=this.hitObjectsLeft;
                //if (this.onCollision)
                move=this.onCollision(this);
                //move=0;
              }  
              if (move) {
                this.hitObject=0;
                this.dir='left';              
                this.x-=this.speedX;
              }  
/*
              _dx=this.dx;
              this.dx=this.x-1;
              this.dy=this.y;
              _screenX=this.offsetX;
              _screenY=this.offsetY;
              this.offsetX-=this.speedX;
              this.offsetY-=this.speedY;
              if (!_cfg.iso.enabled)
                this.x-=this.speedX;
              //this.getCoords();
*/
            },
            moveRight:function(o) { //move character to the right
              var move=1;
              this.checkCollisionsRight();
              if (this.hitRight) {
                this.hitObject=this.hitRight;
                this.hitObjects=this.hitObjectsRight;
                //if (this.onCollision)
                move=this.onCollision(this);
                //move=0;
              }  
              if (move) {
                this.hitObject=0;
                this.dir='right';              
                this.x+=this.speedX;
              }  
              /*
              _dx=this.dx;
              this.dx=this.x+1;
              this.dy=this.y;
              _screenX=this.offsetX;
              _screenY=this.offsetY;
              this.offsetX+=this.speedX;
              this.offsetY+=this.speedY;
              if (!_cfg.iso.enabled)
                this.x+=this.speedX;
              */  
              //this.getCoords();
            },
            moveTop:function(o) { //move character up
              //this.command='moveTop';
              var move=1;
              this.checkCollisionsTop();
              if (this.hitTop) {
                this.hitObject=this.hitTop;
                this.hitObjects=this.hitObjectsTop;                
                //if (this.onCollision)
                move=this.onCollision(this);
                //move=0;
              }  
              if (move) {
                this.hitObject=0;
                this.dir='top';
                this.y-=this.speedY;
              }                
            },
            moveBottom:function(o) { //move character down
              //this.command='moveBottom';
              var move=1;
              this.checkCollisionsBottom();
              if (this.hitBottom) {
                this.hitObject=this.hitBottom;
                this.hitObjects=this.hitObjectsBottom;                
                //if (this.onCollision)
                move=this.onCollision(this);
                //move=0;
              }    
              if (move) {
                this.hitObject=0;
                this.dir='bottom';
                this.y+=this.speedY;
              }
            },
            getZ:function() {
              if (this.z>0) {
                var pavement=_cfg.iso.get([this.z-1,this.x,this.y]); //debug
                if (!pavement || !pavement.spriteId) {                
                  this.offsetZ++;
                  this.offsetY+=this.offsetZ;
                  _cfg.iso.del([this.z,this.x,this.y]);
                  this.z=this.z-Math.round(this.offsetZ/_tile_h);
                  if (this.z>0)
                    _hoz=((this.z-1)*_tile_zh);
                  else { 
                    _hoz=0;
                    this.z=0;
                  }  
                }  
              }
            },
            animate:function(o) {
              //animator + gravity engine

              if (_currentAnimationSid!=this.currentAnimation) {
                _timer=0;
                _frame=0;
                _currentAnimationSid=this.currentAnimation;
              }
              if (_ai) //if this characters has its own ai, run it
                _ai.call(this); //use current object scope >thanks goes to http://www.robertsosinski.com/2009/04/28/binding-scope-in-javascript/
              
              if (!_paused)  
                _timer+=_INTERVAL; //increase internal timer
              //console.log(_timer);
              if (_timer>=_anim[this.currentAnimation].timeLine[_frame]) { //check the frame to display
                _frame++;
                _timer=0;
                //console.log(this.frame,o.animation.length);
                if (_frame>=_anim[this.currentAnimation].timeLine.length)
                  _frame=0;            
              }

/*
              var terrainTile=_cfg.iso.get([this.z-1,this.x,this.y]);
              //console.log(o.z,terrainTile);
              if (!terrainTile || !terrainTile.spriteId)
                this.fall();
*/
              
              
              if (this.jumping) {
                this.offsetZ-=1;
                _jumpLevel++;
                if (_jumpLevel>10) {
                  _jumpLevel=1;
                  this.jumping=0;
                }                
              }
              
              this.getCoords();
              
              /*
              switch (this.command) {
                case 'moveTop':

                break;
                case 'moveBottom':
                break;  
              }
              this.command='';
              */
              
              //this.paint(); //paint the new frame
            },
            paint:function(o) {
              
              //console.log(this);
              
              this.sprOffsetX=0;
              this.sprOffsetY=0;

              this.spriteId=_anim[this.currentAnimation].sprites[_frame];
              if (_anim[this.currentAnimation].offsetX)
                this.sprOffsetX=_anim[this.currentAnimation].offsetX[_frame];
              if (_anim[this.currentAnimation].offsetY)
                this.sprOffsetY=_anim[this.currentAnimation].offsetY[_frame];
              //this.object=this;
              if (_cfg.iso.enabled)
                _cfg.iso.set([this.z,this.x,this.y,this]);
              else if (_cfg.canvas)
                _cfg.canvas.putSprite({z:this.z,obj:this,tiles:this.tiles,spriteId:this.spriteId,x:this.x,offsetX:this.sprOffsetX,y:this.y,offsetY:this.sprOffsetY,width:this.width,height:this.height});//_cfg.canvas.drawFromTile(this.spriteId,this.x+this.sprOffsetX,this.y+this.sprOffsetY);
            }
          });
          _return.paint(o); //paint the character onto its assigned iso map and coordinates
          if (o.init)
            o.init.call(_return) //call the character's init method
          _characters.push(_return);
          //console.log(_characters[z]);
          return _return;
        }
        //object methods and properties end
      }
    }(),
    //singleton end


    //singleton init
    /*
    function Animator //let the editor source tree grab the classes
    */
    Animator:function() {
      var _animations=[];  
      return {
        //object methods and properties init

        //Easing start
        //Easing Equations v2.0
        //September 1, 2003
        //(c) 2003 Robert Penner, all rights reserved.     
        //available functions:
        //linear - bounce - elastic - back - exponential  - [quadratic - cubic - quartic - quintic]
        //- circular - sinusoidal
        //i've just used translated javascript versions of Robert's equations
        //by this way anyone can add a new transition 
        //in moofx they were modified.. i've let them unthouched for easier reading and comprehension
        
        Easing:{
        
          linear: function (t,b,c,d) {
            return c*t/d + b;
          },
          
          bounce: {
            easeOut: function (t,b,c,d) {
              if ((t/=d) < (1/2.75)) {
                return c*(7.5625*t*t) + b;
              } else if (t < (2/2.75)) {
                return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
              } else if (t < (2.5/2.75)) {
                return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
              } else {
                return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
              }
            },
            easeIn: function (t,b,c,d) {
              return c - Segunda.Animator.bounce.easeOut(d-t, 0, c, d) + b;
            },
            easeInOut:function (t,b,c,d) {
              if (t < d/2) return Segunda.Animator.bounce.easeIn (t*2, 0, c, d) * .5 + b;
              else return Segunda.Animator.bounce.easeOut (t*2-d, 0, c, d) * .5 + c*.5 + b;
            }      
          },
  
          elastic: {
            easeIn: function (t,b,c,d,a,p) {
             if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
             if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
             else var s = p/(2*Math.PI) * Math.asin (c/a);
             return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
            },
            easeOut: function (t,b,c,d,a,p) {
             if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
             if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
             else var s = p/(2*Math.PI) * Math.asin (c/a);
             return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b);
            },
            easeInOut: function (t,b,c,d,a,p) {
              if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
              if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
              else var s = p/(2*Math.PI) * Math.asin (c/a);
              if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
              return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
            }
          },    
      
          back: {
            easeIn: function (t,b,c,d,s) {
              if (typeof(s)=='undefined') s=1.70158;
                return c*(t/=d)*t*((s+1)*t - s) + b;
            },
            easeOut: function (t,b,c,d,s) {
              if (typeof(s)=='undefined') s=1.70158;
              return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
            },
            easeInOut:function (t,b,c,d,s){
              if (typeof(s)=='undefined') s=1.70158; 
              if ((t/=d/2)<1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
                return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
            } 
          },
      
          circ: {
            easeIn: function (t,b,c,d) {
              return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
            },
            easeOut: function (t,b,c,d) {
              return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
            },
            easeInOut: function (t,b,c,d) {
              if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
              return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
            }
          },
          
          expo: {
            easeIn: function (t,b,c,d) {
              return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
            },  
            easeOut: function (t,b,c,d) {
              return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
            },
            easeInOut: function (t,b,c,d) {
              if (t==0) return b;
              if (t==d) return b+c;
              if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
              return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
            }
          },
      
          quad: {
            easeIn: function (t,b,c,d) {
              return c*(t/=d)*t + b;
            },
            easeOut: function (t,b,c,d) {
             return -c *(t/=d)*(t-2) + b;
            },
            easeInOut: function (t,b,c,d) {
              if ((t/=d/2) < 1) return c/2*t*t + b;
              return -c/2 * ((--t)*(t-2) - 1) + b;
            }
          },
      
          cubic: {
            easeIn: function (t,b,c,d) {
              return c*(t/=d)*t*t + b;
            },
            easeOut: function (t,b,c,d) {
              return c*((t=t/d-1)*t*t + 1) + b;
            },
            easeInOut: function (t,b,c,d) {
              if ((t/=d/2) < 1) return c/2*t*t*t + b;
              return c/2*((t-=2)*t*t + 2) + b;
            }
          },
          
          quart: {
            easeIn: function (t,b,c,d) {
              return c*(t/=d)*t*t*t + b;
            },
            easeOut: function (t,b,c,d) {
              return -c * ((t=t/d-1)*t*t*t - 1) + b;
            },
            easeInOut: function (t,b,c,d) {
              if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
              return -c/2 * ((t-=2)*t*t*t - 2) + b;
            }
          },
      
          quint: {
            easeIn: function (t,b,c,d) {
              return c*(t/=d)*t*t*t*t + b;
            },
            easeOut: function (t,b,c,d) {
              return c*((t=t/d-1)*t*t*t*t + 1) + b;
            },
            easeInOut: function (t,b,c,d) {
              if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
                return c/2*((t-=2)*t*t*t*t + 2) + b;
            }
          },
      
          sine: {
            easeIn: function (t,b,c,d) {
              return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
            },
            easeOut: function (t,b,c,d) {
              return c * Math.sin(t/d * (Math.PI/2)) + b;
            },
            easeInOut: function (t,b,c,d) {
              return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
            }
          },
        
        },

        //Easing end

        define:function(o) {
          var _ret={};
          
          _ret.objects=o.objects;
          _ret.animation=o.animation;
          _ret.frame=0;
          _ret.animationIndex=0;
          _ret.totalAnimations=0;
          if (o.animation)
            _ret.totalAnimations=o.animation.length;
          _ret.paused=1;

          _ret.play=function(cfg) {            
            if (typeof cfg!='undefined' && typeof cfg.wait!='undefined') {
              clearInterval(_ret.playTimer);
              _ret.playTimer=setTimeout(function(){_ret.paused=0},cfg.wait);  
            } else {
              _ret.paused=0;
            }  
          }
          _ret.pause=function(cfg) {
            _ret.paused=1;
          }
          
          _animations[_animations.length]=_ret;          
          return _ret;
        },
        processAnimations:function() { //play all animations wich state is not 'paused'
          var u=Segunda.Utils;//shortcut          
          var $=u.$;//shortcut
          for (var z=0,zEnd=_animations.length;z<zEnd;z++) { //cicle through all animations
            var curAni=_animations[z],anis=curAni.animation,paused=curAni.paused;
            var frame=curAni.frame
            var idx=curAni.animationIndex;
            if (!paused) {
              for (var y=0,yEnd=_animations[z].objects.length;y<yEnd;y++) { //cicle through all objects for current animation
                var obj=_animations[z].objects[y],x=idx;
                if (!anis)
                  continue;
                var ani=anis[x];
                if (!ani)
                  continue;
                var duration=ani.duration;
                if (u.undef(duration))
                  duration=_INTERVAL;
                if (duration<_INTERVAL)
                  duration=_INTERVAL;
                var steps=duration/_INTERVAL;
                for (var w=0,wEnd=ani.properties.length;w<wEnd;w++) { //for all animated properties
                  var property=ani.properties[w];
                  var from;
                  if (ani.from)
                    from=ani.from[w];
                  else
                    ani.from=[];
                  if (!ani.easing)
                    ani.easing=[];
                  if (curAni.frame==0) {
                    if (u.undef(from)) {
                      var fromSelector=property;
                      switch(property) {
                        case 'left':fromSelector='offsetLeft';break;
                        case 'top':fromSelector='offsetTop';break;
                        case 'width':fromSelector='offsetTop';break;
                        case 'height':fromSelector='offsetTop';break;
                      }
                      from=$(obj)[fromSelector];
                    }
                    ani.from[w]=from; //store value
                  }  
                  var to=ani.to[w];
                  var onEnd;
                  if (ani.onEnd)
                    onEnd=ani.onEnd[w];
                  var stepValue=Math.abs(to-from)/steps;
                  var px='px';
                  var oType=0; //otype=0 int
                  switch(property) {
                    case 'opacity':oType=1;px='';break; //otype=1 float
                    case 'display':oType=2;px='';break; //otype=2 string
                  }
                  var val='';
                  var oo=$(obj);
                  var isObject=0;
                  if (!oo) {
                    oo=obj;
                    isObject=1;
                  }
                  if (!isObject)
                    val=$(obj).style[property];
                  else
                    val=oo.value=property(oo); //read value
                  if (val==='' || ani.Frame==0 || typeof val=='undefined') {
                    val=from;
                    if (isObject) //set init from value
                      oo.value=property(oo,from);
                  }

                  if (typeof val=='string') {
                    if (oType===0)
                      val=parseInt(val);
                    if (oType===1)
                      val=parseFloat(val);
                  }
/*
 //discontinued - use easing instead
                  if (to>from) { //up
                    val+=stepValue;
                    if (val>to) val=to;
                  } else { //down
                    val-=stepValue;
                    if (val<to) val=to;
                  }                   
*/
                  var easing=ani.easing[w];
                  if (!easing || typeof easing=='undefined')
                    easing=Segunda.Animator.Easing.linear;
                  val=easing(frame,from,to-from,steps); //apply the transformation
                  //console.log(frame);
                  
                  if (!isNaN(val))
                    if (!isObject)
                      oo.style[property]=val+px;
                    else  
                      oo.value=property(oo,val);
                  //console.log(val);
                  if (curAni.frame==steps) {
                    //console.log('eccoci',' ',property);
                    if (!isObject)
                      oo.style[property]=to+px;
                    else  
                      oo.value=property(oo,to);
                    if (onEnd)
                      onEnd();
                  }
                }
              }
              curAni.frame++;
              if (curAni.frame>steps) {
                curAni.animationIndex++
                curAni.frame=0;
              }
              //console.log(curAni.animationIndex,' ',curAni.totalAnimations);
              if (curAni.animationIndex==curAni.totalAnimations) { //stop
                curAni.frame=0;
                curAni.animationIndex=0;
                curAni.paused=1;
              }
            }
          }  
        }  
        //object methods and properties end
      }
    }(),
    //singleton end


    //singleton init
    /*
    function Mapper //let the editor source tree grab the classes
    */
    Mapper:function() {
      var _maps=[]; //all maps 
      return {
        //object methods and properties init
        maps:_maps,

        define:function(o) {
          var _virtualCanvas,_virtualCanvasContext=null;
          var _tilesXWidth=0;
          var _tilesXHeight=0;
          var _isStatic=0;
          var _GOX=1;
          var _GOY=1;
          var _ret={};
          var u=Segunda.Utils;//shortcut
          var _mapData=[];
          var _editMode=0;
          var _canvasMapEditor=null;
//deleteme init
//          var _mapMatrix=[];
//deleteme end
          var _tileWidth=o.tileWidth;
          var _tileHeight=o.tileHeight;
          var _canvas=o.canvas;
          var _canvasWidth=0;
          var _canvasHeight=0;
          var _tiles=o.tiles;
          var _currentEditMapId='';
          var xxc=0;
          for (var xx in _maps)
            xxc++;
          var _UID='_'+xxc; //unique id
          //console.log(_UID);
          

          var _z=0;
          if (u.def(o.z))
            _z=o.z;

          _ret.tileHeight=_tileHeight;
          _ret.tileWidth=_tileWidth;

          /*
          virtualPaint : function(){
          */    
          _ret.virtualPaint=function(id) { //paint the map
            if (_mapData) {
              //var currentTile=null;
              //console.log(_mapData[cfg.id][0]);
              var currentObj,currentSprite;
//              for (var z=0,zEnd=_mapData[id].length;z<zEnd;z++) {
//              console.dir(_mapData[id]);
              _virtualCanvasContext.clearRect(0,0,_canvasWidth,_canvasHeight);

              for (var zx=0,zxEnd=_mapData[id].length;zx<zxEnd;zx++) {
                if (!_mapData[id][zx])
                  continue;
                for (var zy=0,zyEnd=_mapData[id][zx].length;zy<zyEnd;zy++) {
                  currentObj=_mapData[id][zx][zy];
                  if (currentObj) {
                    currentSprite=currentObj.tiles[currentObj.spriteId];                
                    _virtualCanvasContext.drawImage(
                      currentSprite.image,currentSprite.left,
                      currentSprite.top,currentSprite.width,currentSprite.height,
                      currentObj.x+currentObj.offsetX,currentObj.y+currentObj.offsetY,
                      currentSprite.width,currentSprite.height
                    );
                  }  
                }  
              }  
            }  
          }

          /*
          maskPaint : function(){
          */    
          _ret.maskPaint=function(id) { //paint the map
            if (_mapData) {
              var currentObj,currentSprite;
              _canvasMapEditor.setFillStyle('rgba(0,255,0,0.5)');
              for (var zx=0,zxEnd=_mapData[id].length;zx<zxEnd;zx++) {
                if (!_mapData[id][zx])
                  continue;
                for (var zy=0,zyEnd=_mapData[id][zx].length;zy<zyEnd;zy++) {
                  currentObj=_mapData[id][zx][zy];
                  if (currentObj) {
                    currentSprite=currentObj.tiles[currentObj.spriteId];
                    if (currentSprite) {
                      
                      /*
                      console.log(
                        currentSprite,
                        currentObj.x+currentObj.offsetX+currentSprite.objLeft,
                        currentObj.y+currentObj.offsetY+currentSprite.objTop,
                        currentSprite.objWidth,currentSprite.objHeight
                      );
                      */
                      
                      _canvasMapEditor.drawRectangle(
                        currentObj.x+currentObj.offsetX+currentSprite.objLeft,
                        currentObj.y+currentObj.offsetY+currentSprite.objTop,
                        currentSprite.objWidth,currentSprite.objHeight
                      );
                    }  
                  }  
                }  
              }  
            }  
          }

          
          //initialize map data
          var userMapData=o.data;
          if (u.def(userMapData)) {
            var currentTile=null;
            for (var z0=0,z0End=userMapData.length;z0<z0End;z0++) {
              
              var currentMapData=userMapData[z0].data;
              if (z0===0)
                _currentEditMapId=userMapData[z0].id;
              //console.log(userMapData[z0].id);                
              if (typeof _mapData[userMapData[z0].id]=='undefined')
                _mapData[userMapData[z0].id]=[];
              for (var z=0,zEnd=currentMapData.length;z<zEnd;z++) {
                currentTile=currentMapData[z];
                if (typeof currentTile.offsetX=='undefined')
                  currentTile.offsetX=0;
                if (typeof currentTile.offsetY=='undefined')
                  currentTile.offsetY=0;
                
                //check if this is a static map
                
                //if ()
                
                if (o.staticTiles)
                  currentTile.staticSprite=1;
                //else
                //  currentTile.staticTile=0;

//deleteme init
/*
                if (typeof _mapMatrix[currentTile.x]=='undefined') {
                  //console.log(currentTile.x,currentTile.y);
                  _mapMatrix[currentTile.x]=[];
                }  
                _mapMatrix[currentTile.x][currentTile.y]=z;
*/
//deleteme end
                var tTile=_tiles[currentTile.sprite];
                var sW=tTile.width;
                var sHW=parseInt(tTile.width/2);
                var sH=tTile.height;
                var sHH=parseInt(tTile.height/2);
                var sX=currentTile.x*_tileWidth+currentTile.offsetX;
                var sY=currentTile.y*_tileWidth+currentTile.offsetY;

                if (typeof _mapData[userMapData[z0].id][currentTile.x]=='undefined') {
                  //console.log(currentTile.x,currentTile.y);
                  _mapData[userMapData[z0].id][currentTile.x]=[];
                }  
                
                //NOTE: -> new properties must be set on onMouseDownMouseOver also
                _mapData[userMapData[z0].id][currentTile.x][currentTile.y]=u.d(currentTile,
                {
                  spriteObj:tTile,
                  objLeft:tTile.objLeft,objTop:tTile.objTop,
                  objWidth:tTile.objWidth,objHeight:tTile.objHeight,
                  objHalfWidth:parseInt(tTile.objWidth/2),objHalfHeight:parseInt(tTile.objHeight/2),
                  spriteLeft:sX,spriteTop:sY,
                  spriteWidth:sW,spriteHeight:sH,spriteHalfWidth:sHW,
                  spriteHalfHeight:sHH,halfWidth:parseInt(_tileWidth/2),
                  halfHeight:parseInt(_tileHeight/2),width:_tileWidth,
                  height:_tileHeight,offsetX:currentTile.offsetX,
                  offsetY:currentTile.offsetY,index:z,self:userMapData[z],
                  obj:this,z:_z,tiles:_tiles,spriteId:currentTile.sprite,
                  x:currentTile.x*_tileWidth,y:currentTile.y*_tileHeight
                });
              }
              _mapData[userMapData[z0].id].collisionMapId=userMapData[z0].collisionMapId;
              //console.log(_mapData[_mapData[z0].id]);

              _tilesXWidth=parseInt(_canvas.width/_tileWidth);
              _tilesXHeight=parseInt(_canvas.height/_tileHeight);              

              if (o.staticTiles) { //create the virtual canvas and paint the map on it
                _virtualCanvas=document.createElement('canvas');
                _canvasWidth=_canvas.width;
                _canvasHeight=_canvas.height;
                _virtualCanvas.setAttribute('width',_canvasWidth); //tnx -> http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element
                _virtualCanvas.setAttribute('height',_canvasHeight);
                _virtualCanvasContext=_virtualCanvas.getContext("2d");
                _ret.virtualPaint(_currentEditMapId);
                _isStatic=1;
              }  

            }
            //console.log(_mapMatrix);
          }
          
          if (!_currentEditMapId) {
            //data has not been defined -> autoset
            _currentEditMapId='level'+_UID+'_0';
            _mapData=[];
            _mapData[_currentEditMapId]=[];//{data:[],id:_currentEditMapId};
            //console.log(_mapData[_currentEditMapId],_currentEditMapId);            
          }
          
          //returned methods
          /*
          get : function(){
          */
          _ret.get=function(x,y) { //return map element given x,y in pixels
//            return 0;           
            if (typeof _mapData!='undefined') {

              var mapId=null;//mapId=_currentEditMapId;//_mapData[_currentEditMapId].collisionMapId;
              if (typeof _mapData[_currentEditMapId].collisionMapId!='undefined')
                mapId=_mapData[_currentEditMapId].collisionMapId;
              else  
                mapId=_currentEditMapId;
                
                //console.log(_mapData[_currentEditMapId].collisionMapId,mapId);
/*
              if (typeof mapId=='undefined')
                mapId=_mapData[_currentEditMapId].collisionMapId;
              if (typeof mapId=='undefined')
                mapId=_currentEditMapId;
*/
              if (!_mapData[mapId]) //_mapData[_currentEditMapId][currentTile.x][currentTile.y];
                return 0;
              
              var coordX=parseInt(x/_tileWidth);
              var coordY=parseInt(y/_tileHeight);
              if (!_mapData[mapId][coordX]) //_mapData[_currentEditMapId][currentTile.x][currentTile.y];
                return 0;
//deleteme init
//              if (!_mapMatrix[coordX])
//                return 0;
//              var tile=_mapData[_currentEditMapId][_mapMatrix[coordX][parseInt(y/_tileHeight)]];
//deleteme end
              var tile=_mapData[mapId][coordX][parseInt(y/_tileHeight)]
//              console.log(_mapData[_currentEditMapId][_mapMatrix[coordX][parseInt(y/_tileHeight)]]);
              //console.log(tile);              
              if (0) {
                var sid=x+y;
                var dd=document.getElementById('dd'+sid);
                if (!dd) {
                  dd=document.createElement('div');
                  dd.style.position='absolute';
                  dd.id='dd'+sid;
                  dd.style.width=_tileWidth+'px';
                  dd.style.height=_tileHeight+'px';
                  dd.style.background='red';
                  dd.style.border='1px solid white';
                  dd.style.opacity=.5;
                  o.canvas.parent.appendChild(dd);
                }
                dd.style.left=(coordX*_tileWidth)+'px';
                dd.style.top=(coordY*_tileHeight)+'px';
              }  
//deleteme init
//              if (_mapMatrix[coordX]) {
//deleteme end
              if (_mapData[mapId][coordX]) {
                if (0 && tile) {
                  //console.log(tile);
                  dd.style.left=tile.spriteLeft+'px';
                  dd.style.top=tile.spriteTop+'px';
                  dd.style.width=tile.spriteWidth+'px';
                  dd.style.height=tile.spriteHeight+'px';
                }
                
                //console.log(tile);
                
                return tile;
              }
            }
            return 0;
          }
          
          /*
          del : function(){
          */    
          _ret.del=function(mapElement) {

            if (u.def(_mapData)) {

              if (_isStatic) {
                var xxt=parseInt(mapElement.x)/_tileWidth;
                var yyt=parseInt(mapElement.y)/_tileHeight;
                var ele=_mapData[_currentEditMapId][xxt][yyt];
                _mapData[_currentEditMapId][xxt][yyt]=null;
                if (ele) {
                  //console.log(ele);
                  _virtualCanvasContext.clearRect(ele.x+ele.offsetX,ele.y+ele.offsetY,ele.spriteWidth,ele.spriteHeight);
                  if (_editMode)
                    _canvasMapEditor.context.clearRect(ele.x+ele.offsetX,ele.y+ele.offsetY,ele.spriteWidth,ele.spriteHeight);
                }  
              }  

              //_mapData[_currentEditMapId][mapElement.index]=null;
                
              /*
              currentObj.tiles[currentObj.spriteId];   
              var ele=_mapData[id][mapElement.index];
              var s=ele.tiles[ele.spriteId];
              */
              //_virtualCanvasContext.clearRect(ele.x,ele.y,ele.x+s.width,ele.y+s.height);
            }  
          }


          /*
          paint : function(){
          */    
          _ret.paint=function(id) { //paint the map
            if (_mapData) {
              //var currentTile=null;
              //console.log(_mapData[cfg.id][0]);
/*
              for (var z=0,zEnd=_mapData[id].length;z<zEnd;z++) {
                //currentTile=_mapData[z];
                _canvas.putSprite(_mapData[id][z]);//{id:currentTile.id,obj:this,z:_z,tiles:_tiles,spriteId:currentTile.sprite,x:currentTile.x*_tileWidth,y:currentTile.y*_tileHeight});
              }
*/
              if (_isStatic) 
                _canvas.context.drawImage(_virtualCanvas,0,0)
            }  
          }

          /*
          edit : function(){
          */    
          _ret.edit=function(cfg) {
            //2d map editor!
            
            _editMode=1;
            
            var _undo=[];
            var _undoIndex=[];
            var _width=o.canvas.width;
            var _height=o.canvas.height;

            var p=u.choose(o.parent,document.body);            
            
            var MAPX=0; //position of the map editor canvas
            var MAPY=50;

            var buttonStyle='float:left;cursor:default;text-align:center;padding:2px;color:white;border:1px solid white;background:gray;width:30px;height:15px;font-family:arial;font-size:10px;';
            
            //property editor
            var panelPEditor=u.New({left:_width*3+25,top:10,width:_width,height:330,background:'black',parent:p}); //new div
            //define html init
            var pHData=[];
            pHData.push('<div style="padding:10px;color:white;font-family:arial;font-size:10px;">');
              pHData.push('<div style="clear:both;margin-bottom:5px;width:100%;height:100%;border:1px solid white">');
                pHData.push('<div id="button_newmap'+_UID+'" style="'+buttonStyle+'">+ Map</div>');
                pHData.push('<div id="segundaMapEditorP_map_'+_UID+'" style="clear:both">');
                pHData.push('</div>');
              pHData.push('</div>');
              pHData.push('<div id="segundaMapEditorP_tile_'+_UID+'" style="width:100%;height:100%;border:1px solid white">');
              pHData.push('</div>');
            pHData.push('</div>');
            panelPEditor.innerHTML=pHData.join('');
            //define html end
            
            /*
            PropertyEditorWindow : function(){
            */    
            var panelPEditorWindow=Segunda.Window.define({
              movable:true,
              content:panelPEditor,
              currentTile:null,
              onGlobalMouseOver:function(o) {
                if (o.element.dom.id)
                  o.element.dom.style.background='red';
              },
              onGlobalMouseOut:function(o) {
                if (o.element.dom.id)
                  o.element.dom.style.background='gray';
              },
              handlers:[
                {
                  /*
                  buttonNewMap : function(){
                  */    
                  objectId:'button_newmap'+_UID,
                  onActivate:function() { //add a new map
                    var xx=0;
                    for (var z in _mapData)
                      xx++;
                    var mapId=xx;
                    _currentEditMapId='level'+_UID+'_'+mapId;
                    _mapData[_currentEditMapId]=[];//[{data:[],id:_currentEditMapId}];
                    propertyEditorUpdate();
                    editorMapUpdate();
                  }
                }
              ]
            });
            
            //map editor
            var panel2=u.New({left:_width*2+20,top:10,width:_width,height:_height+MAPY,background:'black',parent:p}); //new div

                      
            //map editor cursor            
            var cursor=u.New({zIndex:12,width:_tileWidth,height:_tileHeight,border:'1px solid white',parent:panel2}); //new div

            //map editor text
            /*
            MAPEDITORWINDOWbuttons : function(){
            */             
            var tt=u.New({left:0,top:0,width:_width,height:MAPY,parent:panel2}); //new div
            var hdata=[];
            hdata.push('<div style="padding:3px;">');
            hdata.push('<div id="button_clear'+_UID+'" style="'+buttonStyle+'">Clear</div>');
            hdata.push('<div id="button_build'+_UID+'" style="'+buttonStyle+'">Build</div>');
            hdata.push('<div id="button_opacity'+_UID+'" style="'+buttonStyle+'">Alpha</div>');
            hdata.push('<div id="button_grid'+_UID+'" style="'+buttonStyle+'">Grid</div>');
            hdata.push('<div id="button_undo'+_UID+'" style="'+buttonStyle+'">Undo</div>');
            hdata.push('<div id="button_redo'+_UID+'" style="'+buttonStyle+'">Redo</div>');
            hdata.push('</div>');
            tt.innerHTML=hdata.join('');;

            //map editor canvas
            _canvasMapEditor=Segunda.Canvas.define({ //create special canvas obj
              width:_width,height:_height,parent:panel2,
              left:MAPX,top:MAPY,
              tiles:o.tiles,zIndex:10
            });
            //canvas background
            var dd=u.New({border:'none',left:MAPX,top:MAPY,width:_width,height:_height,background:'gray',parent:panel2});
            
            //p.appendChild(panel2);

            /*
            MAPEDITORWINDOW : function(){
            */                      
            var mapEditorWindow=Segunda.Window.define({
              showMasks:0,
              movable:true,
              content:panel2,
              onGlobalMouseOver:function(o) {
                //console.log(o);
                if (o.element.dom.id)
                  o.element.dom.style.background='red';
              },
              onGlobalMouseOut:function(o) {
                //console.log(o);
                if (o.element.dom.id)
                  o.element.dom.style.background='gray';
              },              
              //contentId:'segundaMapEditor',
              //onMouseMove:function(o) {
              //  console.log(o.event.target);
              //}
              handlers:[
                
                {
                  /*
                  right : function(){
                  */ 
                  keyId:'RIGHT',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==1) {
                      _GOX++;
                      editorMapUpdate();
                    }
                  }
                },                
                {
                  /*
                  right : function(){
                  */ 
                  keyId:'LEFT',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==1) {
                      _GOX--;
                      editorMapUpdate();
                    }
                  }
                },                
                {
                  /*
                  right : function(){
                  */ 
                  keyId:'UP',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==1) {
                      _GOY--;
                      editorMapUpdate();
                    }
                  }
                },                
                {
                  /*
                  right : function(){
                  */ 
                  keyId:'DOWN',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==1) {
                      _GOY++;
                      editorMapUpdate();
                    }
                  }
                },                

                {
                  /*
                  keypad_8 : function(){
                  */ 
                  keyId:'KEYPAD_8',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==1) {
                      if (mapEditorWindow.currentTile) {
                        mapEditorWindow.currentTile.offsetY--;
                        editorMapUpdate();
                      }
                    }
                  }
                },

                {
                  /*
                  keypad_6: function(){
                  */ 
                  keyId:'KEYPAD_6',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==1) {
                      if (mapEditorWindow.currentTile) {
                        mapEditorWindow.currentTile.offsetX++;
                        editorMapUpdate();
                      }
                    }
                  }
                },

                {
                  /*
                  keypad_4 : function(){
                  */ 
                  keyId:'KEYPAD_4',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==1) {
                      if (mapEditorWindow.currentTile) {
                        mapEditorWindow.currentTile.offsetX--;
                        editorMapUpdate();
                      }
                    }
                  }
                },

                {
                  /*
                  keypad_5 : function(){
                  */ 
                  keyId:'KEYPAD_5',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==1) {
                      if (mapEditorWindow.currentTile) {
                        
                        //search all tiles and when current map editor tile
                        //is found in tileeditor tile list
                        //reset tile map offset
                        for (var z in tileEditorWindow.elements) {
                          if (z.indexOf('_segundaWindowChild')>-1) {
                            if (mapEditorWindow.currentTile.spriteId==tileEditorWindow.elements[z].name) {
                              mapEditorWindow.currentTile.offsetX=tileEditorWindow.elements[z].offsetX;
                              mapEditorWindow.currentTile.offsetY=tileEditorWindow.elements[z].offsetY;
                            }
                          }
                        }

                        editorMapUpdate();
                      }
                    }
                  }
                },


                {
                  /*
                  keypad_2 : function(){
                  */ 
                  keyId:'KEYPAD_2',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==1) {
                      if (mapEditorWindow.currentTile) {
                        mapEditorWindow.currentTile.offsetY++;
                        editorMapUpdate();
                      }
                    }
                  }
                },
                
                {
                  objectId:'button_clear'+_UID,
                  /*
                  buttonClear : function(){
                  */
                  onActivate:function() {
                    //reset current map
                    _mapData[_currentEditMapId].length=0;
                    editorMapUpdate();
                  }
                },
                {
                  objectId:'button_build'+_UID,
                  /*
                  buttonBuild : function(){
                  */         
                  onActivate:function() {
                    var SEPARATOR=' '; //\n
                    
                    var fData=[];
                    fData.push('data:[');
                    fData.push('  {');
                    fData.push("    id:'"+_currentEditMapId+"',");
                    fData.push('\n    data:[');
                    var mapData=[];
                    
                    for (var zx=0,zxEnd=_mapData[_currentEditMapId].length;zx<zxEnd;zx++) {
                      if (!_mapData[_currentEditMapId][zx])
                        continue;
                      for (var zy=0,zyEnd=_mapData[_currentEditMapId][zx].length;zy<zyEnd;zy++) {
                        var tt=_mapData[_currentEditMapId][zx][zy];                        
                        if (!tt)
                          continue;
                        if (tt.offsetX==0 && tt.offsetY==0)
                          mapData.push('    {x:'+parseInt(tt.x/_tileWidth)+',y:'+parseInt(tt.y/_tileHeight)+",sprite:'"+tt.spriteId+"'}");
                        if (tt.offsetX!=0 && tt.offsetY==0)
                          mapData.push('    {x:'+parseInt(tt.x/_tileWidth)+',y:'+parseInt(tt.y/_tileHeight)+",sprite:'"+tt.spriteId+"',offsetX:"+tt.offsetX+"}");
                        if (tt.offsetX==0 && tt.offsetY!=0)
                          mapData.push('    {x:'+parseInt(tt.x/_tileWidth)+',y:'+parseInt(tt.y/_tileHeight)+",sprite:'"+tt.spriteId+"',offsetY:"+tt.offsetY+"}");
                        if (tt.offsetX!=0 && tt.offsetY!=0)
                          mapData.push('    {x:'+parseInt(tt.x/_tileWidth)+',y:'+parseInt(tt.y/_tileHeight)+",sprite:'"+tt.spriteId+"',offsetX:"+tt.offsetX+",offsetY:"+tt.offsetY+"}");

                        //currentObj=_mapData[id][zx][zy];
                        /*
                        if (currentObj) {
                          currentSprite=currentObj.tiles[currentObj.spriteId];                
                          _virtualCanvasContext.drawImage(
                            currentSprite.image,currentSprite.left,
                            currentSprite.top,currentSprite.width,currentSprite.height,
                            currentObj.x+currentObj.offsetX,currentObj.y+currentObj.offsetY,
                            currentSprite.width,currentSprite.height
                          );
                        }
                        */
                      }  
                    }  

/*                    
                    for (var z=0,zEnd=_mapData[_currentEditMapId].length;z<zEnd;z++) {
                      var tt=_mapData[_currentEditMapId][z];
                      if (tt.offsetX==0 && tt.offsetY==0)
                        mapData.push('    {x:'+parseInt(tt.x/_tileWidth)+',y:'+parseInt(tt.y/_tileHeight)+",sprite:'"+tt.spriteId+"'}");
                      if (tt.offsetX!=0 && tt.offsetY==0)
                        mapData.push('    {x:'+parseInt(tt.x/_tileWidth)+',y:'+parseInt(tt.y/_tileHeight)+",sprite:'"+tt.spriteId+"',offsetX:"+tt.offsetX+"}");
                      if (tt.offsetX==0 && tt.offsetY!=0)
                        mapData.push('    {x:'+parseInt(tt.x/_tileWidth)+',y:'+parseInt(tt.y/_tileHeight)+",sprite:'"+tt.spriteId+"',offsetY:"+tt.offsetY+"}");
                      if (tt.offsetX!=0 && tt.offsetY!=0)
                        mapData.push('    {x:'+parseInt(tt.x/_tileWidth)+',y:'+parseInt(tt.y/_tileHeight)+",sprite:'"+tt.spriteId+"',offsetX:"+tt.offsetX+",offsetY:"+tt.offsetY+"}");
                    }
*/                    
                    
                    fData.push(mapData.join(','+SEPARATOR));
                    fData.push('    ]\n');
                    fData.push('  }');
                    fData.push(']');
                    
                    //console.log(_tiles);                    
                    //fData.push('\n/* =~=~=~=~=~=~=~=~=~=~=~=~=~= */\n');
                    //fData.push('/*    Sprite collision data    */\n');
                    //fData.push('/* =~=~=~=~=~=~=~=~=~=~=~=~=~= */\n');
                    
                    var ushy=[];
                    var ushyd=[];
                    ushy.push('data:[');
                    
                    for (var z in _tiles) {
                      var ox=_tiles[z].objLeft;
                      var oy=_tiles[z].objTop;
                      var ow=_tiles[z].objWidth;
                      var oh=_tiles[z].objHeight;

                      var sw=_tiles[z].width;
                      var sh=_tiles[z].height;
                      
                      var pushy=[];
                      if (ox!=0 || oy!=0 || ow!=sw || oh!=sh) {
                        pushy.push("  { id:'"+_tiles[z].name+"'");
                        if (ox!=0)
                          pushy.push('objectLeft:'+ox);
                        if (oy!=0)
                          pushy.push('objectTop:'+oy);
                        if (ow!=sw)
                          pushy.push('objectWidth:'+ow);
                        if (oh!=sh)
                          pushy.push('objectHeight:'+oh);
                        ushyd.push(pushy.join(',')+'}');
                        
                        //console.log(_tiles[z].objLeft,_tiles[z].objTop,_tiles[z].objWidth,_tiles[z].objHeight,' ',_tiles[z].width,_tiles[z].height);
                        //console.log(ox,oy,ow,sw,oh,sh);
                      }
                      
                    }
                    ushy.push(ushyd.join(','))
                    ushy.push(']');
                    
                    //console.log(ushy.join('\n'));
                    u.$('segundaMapEditorP_mapData'+_UID).value=fData.join(SEPARATOR);
                    u.$('segundaMapEditorP_mapDataMask'+_UID).value=ushy.join('\n');
                    //alert('yeh2');                    
                  }
                },
                
                {
                  objectId:'button_opacity'+_UID,
                  /*
                  buttonOpacity: function(){
                  */
                  onActivate:function(o) {
                    if (typeof o.element.opa=='undefined' || !o.element.opa) {
                      o.element.parentWindow.dom.style.opacity=.8;
                      o.element.opa=1;
                    } else {
                      o.element.parentWindow.dom.style.opacity=1;
                      o.element.opa=0;
                    }  
                  }
                },                

                {
                  objectId:'button_grid'+_UID,
                  /*
                  buttonOpacity: function(){
                  */
                  onActivate:function(o) {
                    if (typeof mapEditorWindow.gridOn=='undefined' || !mapEditorWindow.gridOn) {
                      mapEditorWindow.gridOn=1;
                    } else {
                      mapEditorWindow.gridOn=0;
                    }
                    editorMapUpdate();
                  }
                },

                {
                  objectId:'button_undo'+_UID,
                  /*
                  buttonUndo : function(){
                  */
                  onActivate:function(o) {
                    if (_undoIndex[_currentEditMapId]>0) {
                      _undoIndex[_currentEditMapId]--;
                      _mapData[_currentEditMapId]=_undo[_currentEditMapId][_undoIndex[_currentEditMapId]].slice();
                      editorMapUpdate();
                    }  
                  }
                },                     
                
                {
                  objectId:'button_redo'+_UID,
                  /*
                  buttonRedo : function(){
                  */
                  onActivate:function(o) {
                    if (typeof _undo[_currentEditMapId]!='undefined')
                      if (_undoIndex[_currentEditMapId]<_undo[_currentEditMapId].length-1) {
                        _undoIndex[_currentEditMapId]++;
                        _mapData[_currentEditMapId]=_undo[_currentEditMapId][_undoIndex[_currentEditMapId]].slice();
                        editorMapUpdate();                      
                      }  
                  }
                }                     
                
              ]  
            });
            

            var tilesXWidth=parseInt(_width/_tileWidth);
            var tilesXHeight=parseInt(_height/_tileHeight);

            //console.log(tilesXWidth,' ',tilesXHeight);
            if (1) {
              //define map editor sensible tile areas
              /*
              MAPEDITORTILES : function(){
              */           
              for (var z1=MAPY,z1End=(tilesXHeight*_tileHeight)+MAPY;z1<z1End;z1+=_tileHeight) {
                for (var z=0,zEnd=tilesXWidth*_tileWidth;z<zEnd;z+=_tileWidth) {
                  var x=mapEditorWindow.addObject({
                    tx:parseInt(z/_tileWidth),ty:parseInt((z1-MAPY)/_tileHeight),
                    x:z,y:z1,width:_tileWidth,height:_tileHeight,noUI:1,
                    movable:false,
                    onMouseMove:function(o) {
                      cursor.style.left=o.element.offsetLeft+'px';
                      cursor.style.top=o.element.offsetTop+'px';
                      //var tileOver=getTileSpriteIdFromPos(o.element.x-MAPX,o.element.y-MAPY);
                      var tileOver='';
/*
                      //c'è già sotto stessa operazione solo che usa proprietà tile
                      if ([_currentEditMapId][parseInt((o.element.x-MAPX)/_tileWidth)])
                        tileOver=_mapData[_currentEditMapId][parseInt((o.element.x-MAPX)/_tileWidth)][parseInt((o.element.y-MAPY)/_tileHeight)];
*/
                      //var tileOver=panelPEditorWindow.currentTileObject;
                      //console.log(tileOver);
                      
                      //mapEditorWindow.currentTile=_ret.get(o.element.x-MAPX,o.element.y-MAPY);
                      //console.log(mapEditorWindow.currentTile);
                      //console.log(o.element.tx,o.element.ty);
                      //identico a tileOver -> tile corrente globale
                      if (_mapData[_currentEditMapId][o.element.tx]) {
                        tileOver=mapEditorWindow.currentTile=_mapData[_currentEditMapId][o.element.tx][o.element.ty];
                      }
                      
                      if (!tileOver || tileEditorWindow.oldTileOver!=tileOver) {
                        //rest tile hilite
                        if (tileEditorWindow.lited) {
                          tileEditorWindow.lited=0;
                          for (var zzz in tileEditorWindow.elements) {
                            var eleEle=tileEditorWindow.elements[zzz];
                            if (eleEle.name && eleEle.name!='delete') {
                              eleEle.dom.style.background='';
                              eleEle.dom.style.opacity=1;
                            }
                          }
                        }
                      }

                      if (tileOver && typeof tileOver.sprite!='undefined') {
                        
                        //console.log(tileOver);
                        u.$('segundaMapEditorP_mapTile'+_UID).innerHTML=tileOver.sprite;                        
                        
                        //set tile hilite
                        tileEditorWindow.oldTileOver=tileOver;
                        tileEditorWindow.lited=1;
                        //console.log(tileEditorWindow);
                        for (var zzz in tileEditorWindow.elements) {
                          var eleEle=tileEditorWindow.elements[zzz];
                          if (eleEle.name==tileOver.sprite) {
                            eleEle.dom.style.background='orange';
                            eleEle.dom.style.opacity=.5;
                          }  
                        }
                      }
                      //console.log(tileOver);
                    },
                    
                    /*
                    mapEditorPaintTile: function(){
                    */                    
                    onMouseDownMouseOver:function(o) {
                   
                      if (o.event.mouseButton!=null && typeof mapEditorWindow.currentTileName!='undefined') {
                        //console.log(o);
                        if (mapEditorWindow.currentTileName!='delete') {
                          var ox=panelPEditorWindow.currentTileObject.offsetX;
                          var oy=panelPEditorWindow.currentTileObject.offsetY;
//                          delFromMapAt(o.element.tx,o.element.ty);
                          //canvasMapEditor.drawFromTile(_tiles,mapEditorWindow.currentTileName,o.element.x-MAPX+ox,o.element.y-MAPY+oy);
                          //o.element.tileName=mapEditorWindow.currentTileName;
                          if (typeof _undo[_currentEditMapId]=='undefined') {
                            _undo[_currentEditMapId]=[];
                            _undoIndex[_currentEditMapId]=0;
                          }
                          _undo[_currentEditMapId].push(_mapData[_currentEditMapId].slice());
                          _undoIndex[_currentEditMapId]++;
                          var xx=o.element.x-MAPX;
                          var yy=o.element.y-MAPY;
                          var xxt=parseInt(o.element.x-MAPX)/_tileWidth;
                          var yyt=parseInt(o.element.y-MAPY)/_tileHeight;
                          //console.log(xx);
                          var ll=_mapData[_currentEditMapId].length;
                          
                          if (!_mapData[_currentEditMapId][xxt])
                            _mapData[_currentEditMapId][xxt]=[];
                          
/*
                          //{spriteLeft:sX,spriteTop:sY,spriteWidth:sW,spriteHeight:sH,spriteHalfWidth:sHW,spriteHalfHeight:sHH,halfWidth:parseInt(_tileWidth/2),halfHeight:parseInt(_tileHeight/2),width:_tileWidth,height:_tileHeight,offsetX:currentTile.offsetX,offsetY:currentTile.offsetY,index:z,self:userMapData[z],obj:this,z:_z,tiles:_tiles,spriteId:currentTile.sprite,x:currentTile.x*_tileWidth,y:currentTile.y*_tileHeight};  
                          var sW=_tiles[currentTile.sprite].width;
                          var sHW=parseInt(_tiles[currentTile.sprite].width/2);
                          var sH=_tiles[currentTile.sprite].height;
                          var sHH=parseInt(_tiles[currentTile.sprite].height/2);
                          var sX=currentTile.x*_tileWidth+currentTile.offsetX;
                          var sY=currentTile.y*_tileWidth+currentTile.offsetY;
*/
                          var spr=_tiles[mapEditorWindow.currentTileName];
                          //console.log(spr);
                          _mapData[_currentEditMapId][xxt][yyt]={
                            spriteObj:_tiles[mapEditorWindow.currentTileName],
                            objLeft:spr.objLeft,objTop:spr.objTop,
                            objWidth:spr.objWidth,objHeight:spr.objHeight,
                            objHalfWidth:parseInt(spr.objWidth/2),objHalfHeight:parseInt(spr.objHeight/2),
                            spriteWidth:spr.width,
                            spriteHeight:spr.height,
                            spriteHalfWidth:spr.halfWidth,spriteHalfHeight:spr.halfHeight,
                            width:_tileWidth,height:_tileHeight,tiles:_tiles,
                            sprite:mapEditorWindow.currentTileName,
                            spriteId:mapEditorWindow.currentTileName,x:xx,y:yy,
                            offsetX:ox,offsetY:oy
                          };
/*
//deleteme init
                          if (!_mapMatrix[xxt])
                            _mapMatrix[xxt]=[];
                          _mapMatrix[xxt][yyt]=ll;
                          _mapData[_currentEditMapId].push({width:_tileWidth,height:_tileHeight,tiles:_tiles,spriteId:mapEditorWindow.currentTileName,x:xx,y:yy,offsetX:ox,offsetY:oy});
//deleteme end
*/
                          editorMapUpdate();
                        } else {
                          delFromMapAt(o.element.tx,o.element.ty);
                          var ele=mapEditorWindow.currentTile;
                          //console.log(ele);
                          //_virtualCanvasContext.clearRect(ele.x+ele.offsetX,ele.y+ele.offsetY,ele.spriteWidth,ele.spriteHeight);
                          editorMapUpdate();
                        }
                      }
                      //o.element.dom.style.background='yellow';
                    }
                  });
                  //x.style.borderRight='1px solid white';
                  //x.style.borderBottom='1px solid white';
                }
                //console.log(z1);
              }
            }
            
            //tile editor
            //------------------------------------------------------------------
            var panel=document.createElement('div');
            panel.style.position='absolute';
            panel.style.left=(_width+15)+'px';
            panel.style.top='10px';
            panel.style.width=_width+'px';
            panel.style.height=_height+'px';
            panel.style.background='black';
            
            p.appendChild(panel);

            /*
            TILEEDITORWINDOW : function(){
            */           
            var tileEditorWindow=Segunda.Window.define({
              movable:true,
              content:panel,
              handlers:[
                {
                  /*
                  alt: function(){
                  */ 
                  keyId:'SHIFT',
                  onKeyDown:function() {
                    //panelPEditorWindow.altOn=1;
                    //console.log(panelPEditorWindow.altOn);
                  },
                  onKeyUp:function() {
                    //panelPEditorWindow.altOn=0;
                    //console.log(panelPEditorWindow.altOn);
                  }
                },

                {
                  /*
                  left : function(){
                  */ 
                  keyId:'KEYPAD_4',
                  onKeyDown:function() {
                    //console.log(Segunda.Ui.keyboardStatus['CNTRL'],(Segunda.Ui.keyboardStatus['CNTRL']==0 && panelPEditorWindow.currentTile && panelPEditorWindow.currentTile.name!='delete'),panelPEditorWindow.currentTile,' ','yyyy');
                    if (Segunda.Ui.keyboardStatus['CNTRL']==0 && panelPEditorWindow.currentTile && panelPEditorWindow.currentTile.name!='delete') {
                      panelPEditorWindow.currentTileObject.offsetX--;
                      propertyEditorUpdate();
                      //console.log('xxxx');
                      updateOffsets();
                      editorMapUpdate();
                    }
                  }
                },
                {
                  /*
                  right : function(){
                  */ 
                  keyId:'KEYPAD_6',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==0 && panelPEditorWindow.currentTile && panelPEditorWindow.currentTile.name!='delete') {
                      panelPEditorWindow.currentTileObject.offsetX++;
                      propertyEditorUpdate();
                      updateOffsets();
                      editorMapUpdate();
                    }
                  }
                },
                {
                  /*
                  up : function(){
                  */ 
                  keyId:'KEYPAD_8',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==0 && panelPEditorWindow.currentTile && panelPEditorWindow.currentTile.name!='delete') {
                      //if (typeof panelPEditorWindow.altOn=='undefined' || !panelPEditorWindow.altOn) {
                      //} else {  
                        panelPEditorWindow.currentTileObject.offsetY--;
                        propertyEditorUpdate();
                        updateOffsets();
                        editorMapUpdate();
                      //}
                    }
                  }
                },
                {
                  /*
                  down : function(){
                  */ 
                  keyId:'KEYPAD_2',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==0 && panelPEditorWindow.currentTile && panelPEditorWindow.currentTile.name!='delete') {
                      panelPEditorWindow.currentTileObject.offsetY++;
                      propertyEditorUpdate();
                      updateOffsets();
                      editorMapUpdate();
                    }
                  }
                },
                {
                  /*
                  canc : function(){
                  */ 
                  keyId:'KEYPAD_5',
                  onKeyDown:function() {
                    if (Segunda.Ui.keyboardStatus['CNTRL']==0 && panelPEditorWindow.currentTile && panelPEditorWindow.currentTile.name!='delete') {
                      panelPEditorWindow.currentTileObject.offsetX=0;
                      panelPEditorWindow.currentTileObject.offsetY=0;
                      propertyEditorUpdate();
                      updateOffsets();
                      editorMapUpdate();
                    }
                  }
                }
              
                
              ]
              //onMouseMove:function(o) {
              //  console.log(o.event.target);
              //}
            });              

            
            /*
            getTileOffsetFromSpriteId : function(){
            */ 
            var getTileOffsetFromSpriteId=function(s) {
              for (var z=0,zEnd=_mapData[_currentEditMapId].length;z<zEnd;z++) {
                var tt=_mapData[_currentEditMapId][z];
                //console.log(tt.spriteId,' ',panelPEditorWindow.currentTile.name);
                if (tt && tt.spriteId==s)
                  return [tt.offsetX,tt.offsetY];
              }
              return null;
            }            
            
            var c=Segunda.Canvas.define({ //create special canvas obj
              width:_width,height:_height,parent:panel,
              tiles:o.tiles
            });
            var stepX=12;
            var stepY=12;
            var xx=stepX;yy=stepY;
            var maxY=0;
            var currentTile;
            var counnt=0;
            var _tiloz=[];
            _tiloz.push({deleter:1});
            for (var z in o.tiles) {
              _tiloz.push(o.tiles[z]);
            }  
            _tiloz=_tiloz.concat(o.tiles);
            //_tiloz=o.tiles;
            //console.dir(_tiloz);
            
            var minWidth=8;
            for (var z in _tiloz) {
              var delez=0;
              currentTile=_tiloz[z];
              
              if (currentTile.deleter) {
                currentTile.name='delete';
                delez=1;
                currentTile.width=8;
                currentTile.height=8;
              }              

              if (!delez) {
                if (cfg && cfg.classNameReFilter) {
                  if (cfg.classNameReFilter.length) {
                    var matched=0;
                    for (var xz=0,xzEnd=cfg.classNameReFilter.length;xz<xzEnd;xz++) {
                      if (currentTile.className.match(cfg.classNameReFilter[xz]))
                        matched=1;
                    }
                    if (!matched)
                      continue;
                  } else {
                    if (!currentTile.className.match(cfg.classNameReFilter))
                      continue;
                  }
                }  
              }
              if (maxY<currentTile.height)
                maxY=currentTile.height;
                
              //console.log(z,' ',xx+currentTile.width+stepX,' ',_width);  
                
              if (xx+currentTile.width+stepX>_width) {
                xx=stepX;
                yy+=maxY+stepY;
              }
              
              var oox=ooy=0;
              var off=getTileOffsetFromSpriteId(currentTile.name);
              if (off) {
                oox=off[0];
                ooy=off[1];
              }
              /*
              TILESLIST : function(){
              */ 
              var ff=tileEditorWindow.addObject({ //add detectable areas to the window
                x:xx-3,y:yy-3,width:_tileWidth+3,height:_tileHeight+3,
                className:currentTile.className,name:currentTile.name,noUI:0,
                offsetX:oox,offsetY:ooy,
                movable:false,
                onMouseOver:function(o) {
                  if (o.window.dragging)
                    return;
                  o.element.dom.style.border='1px solid white';
                },
                onMouseOut:function(o) {
                  if (o.window.dragging)
                    return;
                  if (o.element.selected)
                    o.element.dom.style.border='1px solid red';
                  else
                    o.element.dom.style.border='1px solid gray';
                  //o.element.content.style.border='none';
                },
                onDeactivate:function(o) {
                  o.element.dom.style.border='1px solid gray';
                },
                onActivate:function(o) {
                  mapEditorWindow.currentTileName=o.element.name;
                  //console.log(o.element.name);
                  o.element.dom.style.border='1px solid red';
                  panelPEditorWindow.currentTile={sprite:_tiles[mapEditorWindow.currentTileName],name:mapEditorWindow.currentTileName,offsetX:o.element.offsetX,offsetY:o.element.offsetY};
                  panelPEditorWindow.currentTileObject=o.element;
                  propertyEditorUpdate();
                }
              });
              ff.style.border='1px solid gray';
              if (!delez)
                c.draw(currentTile,xx,yy);
                
              if (currentTile.width<minWidth)  
                mimi=minWidth;
              else
                mimi=currentTile.width;
              xx+=mimi+stepX;
            }

            /*
            getTileSpriteIdFromPos : function(){
            */ 
            var getTileSpriteIdFromPos=function(x,y) {
              for (var z=0,zEnd=_mapData[_currentEditMapId].length;z<zEnd;z++) {
                var tt=_mapData[_currentEditMapId][z];
                //console.log(tt.spriteId,' ',panelPEditorWindow.currentTile.name);
                if (tt && tt.x==x && tt.y==y)
                  return tt.spriteId;
              }
              return null;
            }

            /*
            updateOffsets : function(){
            */             
            var updateOffsets=function() {
              var id=_currentEditMapId;
              for (var zx=0,zxEnd=_mapData[id].length;zx<zxEnd;zx++) {
                if (!_mapData[id][zx])
                  continue;
                for (var zy=0,zyEnd=_mapData[id][zx].length;zy<zyEnd;zy++) {
                  tt=_mapData[id][zx][zy];
                  if (tt) {
                    if (tt.spriteId==panelPEditorWindow.currentTile.name) {
                      //console.log(tt);
                      tt.offsetX=panelPEditorWindow.currentTileObject.offsetX;
                      tt.offsetY=panelPEditorWindow.currentTileObject.offsetY;
                    }
                  }  
                }  
              }                
              /*
              for (var z=0,zEnd=_mapData[_currentEditMapId].length;z<zEnd;z++) {
                var tt=_mapData[_currentEditMapId][z];
                
                //console.log(tt.spriteId,' ',panelPEditorWindow.currentTile.name);
                if (tt) {
                  if (tt.spriteId==panelPEditorWindow.currentTile.name) {
                    tt.offsetX=panelPEditorWindow.currentTileObject.offsetX;
                    tt.offsetY=panelPEditorWindow.currentTileObject.offsetY;
                  }
                }  
              }
              */
            }

            /*
            delFromMapAt : function(){
            */                
            var delFromMapAt=function(tx,ty) {
              if (_mapData[_currentEditMapId][tx])
                _mapData[_currentEditMapId][tx][ty]=null;
/*
              return;

              var pp=[];
              for (var z=0,zEnd=_mapData[_currentEditMapId].length;z<zEnd;z++) {
                var tt=_mapData[_currentEditMapId][z];
                if (tt) {
                  var ttx=parseInt(tt.x/_tileWidth);
                  var tty=parseInt(tt.y/_tileHeight);
                  //console.log(z,' >',tt.x,' ',tt.y);                 
                  if (tx==ttx && ty==tty) {
                    //console.log(ttx,' ',tty);                              
                  } else {
                    pp.push(tt);
                  }
                }  
                //mapData.push('    {x:'+parseInt(tt.x/_tileWidth)+',y:'+parseInt(tt.y/_tileHeight)+",sprite:'"+tt.spriteId+"'}");
              }                          
              _mapData[_currentEditMapId]=pp;
*/              
            }

            /*
            editorMapUpdate : function(){
            */  
            var editorMapUpdate=function() {
              //update virtual canvas  
              _ret.virtualPaint(_currentEditMapId);
              _canvasMapEditor.context.clearRect(0,0,_canvasWidth,_canvasHeight);
              
              if (_canvasMapEditor)
                _canvasMapEditor.context.drawImage(_virtualCanvas,0,0);

              if (mapEditorWindow.showMasks) {
                //console.log('aaa');
                _ret.maskPaint(_currentEditMapId);
              }

              //console.log('xxx');
              return;
              //refresh canvas map editor
              if (u.def(_mapData)) {
                if (u.def(_mapData[_currentEditMapId])) {
                  //console.log(_currentEditMapId);
                  canvasMapEditor.clear();
                  //console.log(_mapData[_currentEditMapId].length);
                  for (var z=0,zEnd=_mapData[_currentEditMapId].length;z<zEnd;z++) {
                    //console.log(_mapData[_currentEditMapId][z]);
                    canvasMapEditor.putSprite(_mapData[_currentEditMapId][z]);//{id:currentTile.id,obj:this,z:_z,tiles:_tiles,spriteId:currentTile.sprite,x:currentTile.x*_tileWidth,y:currentTile.y*_tileHeight});
                  }
                  if (mapEditorWindow.gridOn) {
                    //console.log(x);
                    canvasMapEditor.context.lineWidth=0.2; //https://developer.mozilla.org/en/Canvas_tutorial/Applying_styles_and_colors
                    canvasMapEditor.context.strokeStyle='#ffffff';

                    for (var z1=0,z1End=(tilesXHeight*_tileHeight);z1<z1End;z1+=_tileHeight)
                      canvasMapEditor.drawLine(0,z1+_GOY,_width,z1+_GOY);                        
                    for (var z=0,zEnd=tilesXWidth*_tileWidth;z<zEnd;z+=_tileWidth)
                      canvasMapEditor.drawLine(z+_GOX,0,z+_GOX,_height);                        
                  }
                  canvasMapEditor.container.style.left=_GOX+'px';
                  canvasMapEditor.container.style.top=(_GOY+MAPY)+'px';
                  canvasMapEditor.paint();
                }
              }
            }   

            /*
            propertyEditorUpdate : function(){
            */  
            var propertyEditorUpdate=function() {
              var mData=[];
              /*
              var _select='<select onchange="console.log(this.value);_currentEditMapId=this.value;Segunda.Mapper.maps['+(_maps.length-1)+'].editorMapUpdate();propertyEditorUpdate();" style="width:80px;font-size:10px;">'+options.join('')+'</select>';
              */
              mData.push('<pre style="padding:2px;font-family:arial;">');
              mData.push('Map   : '+_currentEditMapId+' | display masks <span id="segundaMapEditorP_maskChanger'+_UID+'" style=""></span>');
              mData.push('Select: <span id="segundaMapEditorP_mapChanger'+_UID+'"></span>');
              mData.push('Data');
              mData.push('<textarea style="width:96%;height:15px;font-size:10px;font-family:arial;" id="segundaMapEditorP_mapData'+_UID+'"></textarea>');
              mData.push('<textarea style="width:96%;height:15px;font-size:10px;font-family:arial;" id="segundaMapEditorP_mapDataMask'+_UID+'"></textarea>');
              mData.push('</pre>');
              u.$('segundaMapEditorP_map_'+_UID).innerHTML=mData.join('\n');
              
              var _select=u.New({fontSize:10,element:'select',width:80,parent:'segundaMapEditorP_mapChanger'+_UID});
              _select.onchange=function(e) {
                _currentEditMapId=e.target.value;
                editorMapUpdate();
                propertyEditorUpdate();
              }
              var _checkbox1=u.New({type:'checkbox',element:'input',parent:'segundaMapEditorP_maskChanger'+_UID});
              _checkbox1.onclick=function(e) {
                mapEditorWindow.showMasks=0;
                if (e.target.checked)
                  mapEditorWindow.showMasks=1;
                editorMapUpdate();
              }
              //u.$('segundaMapEditorP_map_'+_UID).appendChild(_select);
              var oopt;
              for (var z in _mapData) {
                
                //console.log(z);
                
                sel='';
                oopt=u.New({element:'option',parent:_select});
                //console.log(z);
                oopt.text=oopt.value=z;
                if (z==_currentEditMapId)
                  oopt.selected=1;                  
                //options.push('<option '+sel+'>'+_mapData[z].id+'</option>');
              }

              var hData=[];
              hData.push('<pre style="padding:2px;font-family:arial;">');
              hData.push('Map tile: <span id="segundaMapEditorP_mapTile'+_UID+'"></span>');
              var currentTileOn=0;
              if (panelPEditorWindow.currentTile) {
                hData.push('Paint tile      : '+panelPEditorWindow.currentTile.name);
                hData.push('OffsetX : '+panelPEditorWindow.currentTileObject.offsetX);
                hData.push('OffsetY : '+panelPEditorWindow.currentTileObject.offsetY);
                hData.push('obj X : <span id="segundaMapEditorP_objx'+_UID+'"></span>');
                hData.push('obj Y : <span id="segundaMapEditorP_objy'+_UID+'"></span>');
                hData.push('obj W : <span id="segundaMapEditorP_objw'+_UID+'"></span>');
                hData.push('obj H : <span id="segundaMapEditorP_objh'+_UID+'"></span>');
                currentTileOn=1;
              } else {  
                hData.push('Paint tile: none');
              }  
              hData.push('Keypad Cursor : change global tile offset');
              hData.push('Keypad 5 key       : reset offset');
              hData.push('CNTRL+cursor  : change map position');
              hData.push('CNTRL+keypad  : change tile offset');
              hData.push('</pre>');
              u.$('segundaMapEditorP_tile_'+_UID).innerHTML=hData.join('\n');

              if (currentTileOn) {
                //console.log(panelPEditorWindow.currentTile);
                var tt=panelPEditorWindow.currentTile.sprite;
                if (tt) {
                  var _obj_x=u.New({width:30,fontFamily:'verdana',border:'none',value:tt.objLeft,fontSize:9,padding:0,margin:0,height:11,type:'text',element:'input',parent:'segundaMapEditorP_objx'+_UID});                
                  var _obj_y=u.New({width:30,fontFamily:'verdana',border:'none',value:tt.objTop,fontSize:9,padding:0,margin:0,height:11,type:'text',element:'input',parent:'segundaMapEditorP_objy'+_UID});
                  var _obj_w=u.New({width:30,fontFamily:'verdana',border:'none',value:tt.objWidth,fontSize:9,padding:0,margin:0,height:11,type:'text',element:'input',parent:'segundaMapEditorP_objw'+_UID});
                  var _obj_h=u.New({width:30,fontFamily:'verdana',border:'none',value:tt.objHeight,fontSize:9,padding:0,margin:0,height:11,type:'text',element:'input',parent:'segundaMapEditorP_objh'+_UID});
                  _obj_x.onkeyup=function(e) {
                    if (e.keyCode==13) {
                      var val=parseInt(e.target.value);
                      if (!isNaN(val)) {
                        panelPEditorWindow.currentTile.sprite.objLeft=val;
                        editorMapUpdate();
                      }
                    }
                  }
                  //-----------------
                  _obj_y.onkeyup=function(e) {
                    if (e.keyCode==13) {
                      var val=parseInt(e.target.value);
                      if (!isNaN(val)) {
                        panelPEditorWindow.currentTile.sprite.objTop=val;
                        editorMapUpdate();
                      }
                    }
                  }
                  //-----------------
                  _obj_w.onkeyup=function(e) {
                    if (e.keyCode==13) {
                      var val=parseInt(e.target.value);
                      if (!isNaN(val)) {
                        panelPEditorWindow.currentTile.sprite.objWidth=val;
                        panelPEditorWindow.currentTile.sprite.objHalfWidth=parseInt(val/2);
                        editorMapUpdate();
                      }
                    }
                  }
                  //-----------------
                  _obj_h.onkeyup=function(e) {
                    if (e.keyCode==13) {
                      var val=parseInt(e.target.value);
                      if (!isNaN(val)) {
                        panelPEditorWindow.currentTile.sprite.objHeight=val;
                        panelPEditorWindow.currentTile.sprite.objHalfHeight=parseInt(val/2);
                        editorMapUpdate();
                      }
                    }
                  }
                  //-----------------

                }  
                
              }   
              
              if (mapEditorWindow.currentTile)
                u.$('segundaMapEditorP_mapTile'+_UID).innerHTML=mapEditorWindow.currentTile.sprite;
              //keep state even if html is rewritten  
              if (mapEditorWindow.showMasks) {
                //console.log(u.$('segundaMapEditorP_maskChanger'+_UID).childNodes);
                u.$('segundaMapEditorP_maskChanger'+_UID).childNodes[0].checked=1;                
              }
            }
            
            propertyEditorUpdate();
            editorMapUpdate();
          }
          
          
          _maps[_maps.length]=_ret;          
          return _ret;
        }
        //object methods and properties end
      }
    }()
    //singleton end
  }//the end
}();

//create a character alias so we have a nicer character paintAll method
Segunda.Characters=Segunda.Character;
