/* 
 * Graphics Framework
 * copyright Dimitrios Al. Aggelis
 */
/* global THREE, Detector, ParticleSystem */
"use strict";


//////////////////////////////////////////////////////////////GF ///////////////////////////###################################################////////
var GF = function () {
    "use strict";
    var debug = !true;
    var debugs = [];

    var hidelist = [];// opened forms for hide ncdown
    var edeltay = 0;
    var interval = 1 / 1111; ///  1/fps
    var frames = 0;
    var fps = 0;
    var fpst = 0;
    var fpst0 = 0;
    var logw = 1280;
    var logh = 720;
    var mobile = false; // if touch screen mobile=true
    //var wheeldelta=0;
    var colorbutton = "#F0F0F1";
    var colorwin = "cyan";//#00FEFA";
    var colorbody = "#000000";
    var colorcheck = "#FCFFE6";
    var colortext = "#18005C";
    var colortitle = "#FF9900";
    var colortitle0 = "#fff0db";
    var image1;
    var check1;
    var check2;
    var radio1;
    var radio2;
    var iconhome;
    var icontrig;
    var iconinfo;
    var iconwave;
    var clock1;
    var clock2;
    var clock3, clock4, clock5, clock6, clock7;
    var iconrgb;
    var iconhelp, iconabout, iconclose;
    var icondropdown;
    var gsc = 1; //// global scale 
    var gok = false; /// if all ready then start scene manager 
    var vectorth = Math.PI * 0.85;
    var vectorlen = 10;
    var clicks = []; // list of clicked objects in a scene;
    var MOUSEDOWN = -1;
    var MOUSEUP = "MU";//-2;
    var MOUSEMOVE = -3;
    var TOUCHSTART = -4;
    var TOUCHMOVE = -5;
    var TOUCHEND = -6;
    var KEYDOWN = -7;
    var KEYUP = -8;
    var MOUSEWHEEL = -9;
    // Find the right method, call on correct element
    var MULTISTATE = -16; //// 
    var BUTTONCOMMAND = -17; /// command button with parameter list []
    var PUSHBUTTON = -18;
    var SCROLLBAR = -19;
    var WINDOW = -20,
            LABEL = -21,
            BUTTON = -22,
            VSCROLLBAR = -23,
            HSCROLLBAR = -24;
    var LIST = -25,
            MLIST = -26,
            CHECK = -27,
            RADIO = -28,
            LISTITEM = -29;
    var SCNEXT = -30, ///// commands 
            SCPREVIOUS = -31,
            SCLAST = -32,
            SCFIRST = -33,
            SCANY = -34; //// COMMANDS need parameter a scene num
    var FSON = -38; //fullscreen on
    var FSOFF = -39; //off
    var DRAGMOVE = -40;
    var DRAGCLONE = -41;
    var APP = -42;
    var SHAPE = -43;
    var degtorad = Math.PI / 180.0;
    var pi = Math.PI;
    var twopi = 2 * Math.PI;
    var mousex = 0;
    var mousey = 0;
    var pmousex = 0;
    var pmousey = 0;
    var mousedx = 0;
    var mousedy = 0;
    var key1 = false; //key 1 pressed
    var mousest = 122; // mousest=  mouse down =1 drag 2 up with drag=2 mst=3(drop)
    //// mst=4 just up 
    var mousemove = false;
    var mousex0 = 0;
    var mousey0 = 0; /// when drag start
    var dragx = 0;
    var dragy = 0; /// x,y of window dragged;
    var overover = undefined;
    var pressedobject = undefined;
    var overobject = undefined; // which instance button downed
    var inobject = undefined;
    var overobject2 = undefined;// id dragged previous over
    var draggedobject = undefined;
    var clickedobject = undefined;
    //var pressedpush=undefined; /// which pushbutton pressed
    var drop = 1;
    ////////////////////////////////
    var time0 = 0; // initial millis 
    var time1 = 0; // current 
    var time = 0; /// since program startd
    ///var timescale = 1;
    var timedelta = 0;
    ///// canvas, windoww ,winh 
    //// canvas2 and canvas3d logw logh
    var keysDown = {
        mx: 0,
        my: 0
    }; // holds keycode if pressed
    var keycode = -1; ///holds last key cod for test
    var canvas = document.getElementById("canvas");
    var canvas2 = document.getElementById("canvas2");
    var ctx2 = canvas2.getContext("2d");
    var imageresourcecount = 0;
    canvas.width = logw; //window.innerWidth; 
    canvas.height = logh; //window.innerHeight;
    var ctx = canvas.getContext("2d");
    var viewtr = new Transform();
    viewtr.scale(2.0, 2.0);
    var gtr1 = new Transform(); // global tranforms for debug use;
    var gtr2 = new Transform();
    /// --------------  3d globals app start ------------------------
    var pressedelement = 0; /// will receive window mouse up
    var raycaster, renderer, stats;
    var control3d = true; //// no controls cause a form no 3d pressed
    var focused;
    //var ratio; /// put by form3d 
    var container;
    var INTERSECTED = null;
    var can3d = false;
    var canvas3d;
    //------------------------------------------------- 
    function getlastchild() {
        if (clicks.length > 0)
            return clicks[clicks.length - 1];
        return undefined;
    } /// 
    //
    // 
    function getpreviouschild() {
        if (clicks.length > 1)
            return clicks[clicks.length - 2];
        return undefined;
    } /// 
    function unpress(aw) {
        if (aw)
            aw.pressed = 0;
    } /// 
    //
    function obtitle(ob) {
        if (ob === undefined)
            return "none";
        return ob.id + " " + ob.kind;
    }
    ;

    function objectcompare(ob1, ob2) {
        if (!ob1)
            return false;
        if (!ob2)
            return false;
        return (ob1 === ob2);
    }
    ;
    // Handle keyboard controls
    function setmouse(e, type) {
        var rect = canvas.getBoundingClientRect();
        mousex = e.clientX - rect.left;
        mousey = e.clientY - rect.top;
        var inv = new Transform(viewtr);
        inv.invert();
        //*************    mousex mouse y transformed by view 
        var poi = inv.transformPoint(mousex, mousey);
        mousex = poi[0];
        mousey = poi[1];
        ///***********
        mousemove = false;
        if (type === MOUSEWHEEL) {
            // wheeldelta+=e.deltaY;
            sm.onevent(e, type);
        }
        if (type === MOUSEDOWN) {
            mousest = 1;
            mousex0 = mousex;
            mousey0 = mousey; // for drag  
            sm.onevent(e, MOUSEDOWN);
        }
        if (type === MOUSEUP) {
            if (mousest === 2) {
                mousest = 3;
            } else {
                mousest = 4;
            }
            sm.onevent(e, MOUSEUP);
        }
        if (type === MOUSEMOVE) {
            if (mousest === 1) {
                mousest = 2;
            }
            ;
            if (mousest === 2)
                mousemove = true;
            sm.onevent(e, MOUSEMOVE);
        }
    }
    ; /// set mouse 
    // 
    function setkeys(e, type) {
        if (type === KEYDOWN) {
            sm.onevent(e, "KEYDOWN");
        }
        if (type === KEYUP) {
            sm.onevent(e, "KEYUP");
        }
        keycode = e.keyCode;
    }
    ;

    function initialize() { //// ------------E v e n t   f r o m  O S    -----------------------------
        /// class        
        // Register an event listener to call the resizeCanvas() function 
        // each time the window is resized.
        addEventListener('resize', onresize, false);
        addEventListener("wheel", function (e) {
            setmouse(e, MOUSEWHEEL);
        }, false);
        //window.addEventListener('orientationchange', resizeCanvas,false);
        addEventListener("keydown", function (e) {
            keysDown[e.keyCode] = true;
            setkeys(e, KEYDOWN);
            e.preventDefault();
        }, false);
        addEventListener("keyup", function (e) {
            delete keysDown[e.keyCode];
            setkeys(e, KEYUP);
            e.preventDefault();
            if (keycode === 33) {
                keycode = -1;
                fullscreenon();
            }
            if (keycode === 34) {
                keycode = -1;
                fullscreenoff();
            }
        }, false);
        addEventListener("mousedown", function (e) {
            setmouse(e, MOUSEDOWN);
            e.preventDefault();
        }, true);
        addEventListener("mousemove", function (e) {
            setmouse(e, MOUSEMOVE);
            e.preventDefault();
        }, !false);
        addEventListener("mouseup", function (e) {
            setmouse(e, MOUSEUP);
            e.preventDefault();
        }, !false);
        addEventListener("touchstart", function (e) {
            
            mobile = true; /// touch down no mouse  
            var touchobj = e.changedTouches[0];
            e.preventDefault();
            setmouse(touchobj, MOUSEDOWN);
        }, false);
        addEventListener("touchmove", function (e) {
            var touchobj = e.changedTouches[0];
            e.preventDefault();
            setmouse(touchobj, MOUSEMOVE);
        }, false);
        addEventListener("touchend", function (e) {
            var touchobj = e.changedTouches[0];
            e.preventDefault();
            setmouse(touchobj, MOUSEUP);
        }, false);
        //onresize();
    }

   

    function onresize() {
    
       canvas.width = window.innerWidth;
        canvas.height = canvas.width * logh / logw;
        var px = 0;
        var py = (window.innerHeight - canvas.height) / 2;
        if (canvas.height > window.innerHeight) {
            canvas.height = window.innerHeight;
          
            canvas.width = canvas.height * logw / logh;
            py = 0;
            px = (window.innerWidth - canvas.width) / 2;
        } 
       // if (canvas.width!==window.innerWidth&&canvas.height!==window.innerHeight ){ canvas.width = window.innerWidth;canvas.height = window.innerHeight;px=0;py=0;}
        setelementpos(canvas, px, py);
        if (can3d && canvas3d)
            setelementpos(canvas3d, px, py);     
        
             var scx = (canvas.width) / logw;
        var scy = (canvas.height) / logh;
        gsc = Math.min(scx, scy);
        //gsc=gsc/ window.devicePixelRatio;
        
        
    }
    //------------------   definition classes
    //
    //
    //
    //
    function Key(t, value) {
        this.t = t;
        this.value = value; /// eg 
        this.len = 0;
        this.totlen = 0;

    }
    Key.prototype.setkey = function (t, value) {
        this.t = t;
        this.value = value;
    }

    function Animation(kind) {
        this.kind = kind; /// "xy", "rot" "a" "col1" "col2"
        this.keys = [];
        this.period = 0;
        this.len = 0;

    }
    Animation.prototype.addkey = function (t, value) {
        this.keys.push(new Key(t, value));
    }
    Animation.prototype.addkeys = function (kind, array) {
        /// eg ("rot" ,[0,[4],7,[66] ...]) 
        this.kind = kind;
        var i;
        for (i = 0; i < array.length / 2; i++) {
            this.addkey(array[i * 2], array[2 * i + 1]);

        }


    }
    Animation.prototype.addpolygon = function (p, period) {
        var i;
        for (i = 0; i < p.length / 2; i++) {
            this.addkey(i, [p[i * 2], p[i * 2 + 1]])
        }
        period = period || 10;
        this.setperiod(period)
    }
    Animation.prototype.setkey = function (akey, pos) {
        if (pos >= this.keys.length)
            return;
        this.keys[pos].t = akey.t;
        this.keys[pos].value = akey.value;
    }
    Animation.prototype.insertkey = function (t, value) {
        var keys = this.keys;
        var nk = new Key(t, value);
        if (t < keys[0].t) {

            keys.splice(0, 0, nk);
            return 0;
        }
        var j;
        for (j = 0; j < keys.length - 1; j++) {
            if (keys[j].t <= t && keys[j + 1].t > t) {
                keys.splice(j + 1, 0, nk);
                return j + 1;

            }

        }

        keys.push(nk);
        return (keys.length - 1);
    }
Animation.prototype.setvelocity = function (velocity) {
      this.setperiod(10);// find len
      this.setperiod(this.len/velocity)
      
    }
Animation.prototype.addtime = function (dt) {
    var i;
     
      for (i = 0; i < this.keys.length; i++) {
                this.keys[i].t+= dt;

            }
      
    }
Animation.prototype.startafter = function (anim, dt) {
    var i;
    var t1=anim.getlastt()
   
      for (i = 0; i < this.keys.length; i++) {
                this.keys[i].t+=t1+ dt;

            }
      
    }
    
  Animation.prototype.getlastt = function () {
    var ii=this.keys.length-1;
    return this.keys[ii].t
    
      
    }  
    
    Animation.prototype.setperiod = function (at) {

        var i;
        var totl = 0;
        var le = [];

        var keys = this.keys;
        var t2 = keys[0].t;
        this.period = at;
        if (this.kind === "xy") {
            le.push(t2);
            for (i = 0; i < this.keys.length - 1; i++) {
                var cl = length(keys[i].value[0], keys[i].value[1], keys[i + 1].value[0], keys[i + 1].value[1]);
                totl += cl;
                le.push(totl);
            }
            this.len = totl;

            for (i = 1; i < this.keys.length; i++) {
                keys[i].t = t2 + le[i] / totl * at;

            }

        }
    }
    Animation.prototype.debug = function (frm) {
        var i;

        for (i = 0; i < this.keys.length; i++) {
            var key = this.keys[i];
            frm.drawtext(todecimal(key.t, 2), key.value[0], key.value[1], 10)


        }

    }
    Animation.prototype.drawimage = function (frm, imel, t, ofsx, ofsy, ni, vel) {
        ni = ni || 1
        vel = vel || 1;
        ofsx = ofsx || 0;
        ofsy = ofsy || 0;

        var vv = [];
        var i;
        var dt=0; if (ni>1) dt= this.period / (ni - 1)
      
        for (i = 0; i < ni; i++) {
            vv = this.getvalue(t * vel + i * dt);
             
        if(vv.length)    frm.drawimageto(imel, vv[0] - ofsx, vv[1] - ofsy)
        }

    }
    Animation.prototype.getvalue = function (t) {
        var i, j;
        var keys = this.keys;
        //t = t % this.period;

        var array = [];
        if (t<keys[0].t||t>keys[keys.length-1].t){ return array}
        for (j = 0; j < keys[0].value.length; j++) {

            array[j] = keys[0].value[j]

        }
     var res=[]
        for (i = 0; i < keys.length - 1; i++) {
            //
            if (t <= keys[i + 1].t && t >= keys[i].t) {
                for (j = 0; j < keys[i].value.length; j++) {

                    res[j] = keys[i].value[j] + (keys[i + 1].value[j] - keys[i].value[j]) * (t - keys[i].t) / (keys[i + 1].t - keys[i].t)

                }

            }
        }
        return res;
    }
    function Animator(man) {
        this.manager = man; /// get dt listener etc
        this.animation = 0;/// no 
        this.playing = false;
        this.t = 0;
        this.t0 = 0;  ///// when start?
        this.tofset = 0;   //// t ofset
        this.form = 0;
        this.value = [];// 
        this.loop = false;


    }
    //Animator.prototype.addanimation = function (aanim) {
    //    this.animations.push(aanim);
    //}
    Animator.prototype.update = function (dt) {
        //this.t += this.manager.dt;///dt * !this.manager.stopped;///this.playing;
        this.t = this.manager.t;
        if (this.t < 0)
            this.t = 0;
        var t1 = this.t - this.t0;
        var mt = this.maxt();
        if (t1 > mt)
            t1 = mt;
        if (this.loop)
            t1 = this.t % this.maxt();

        this.getvalue(t1);
        this.updateform();

    }
    Animator.prototype.getvalue = function (t) {

        this.value = this.animation.getvalue(t)



    }
    Animator.prototype.updateform = function () {

        /// apply to form  

        if (this.animation.kind === "rot") {


            this.form.rot = this.value[0];
        }

        if (this.animation.kind === "xy") {

            this.form.x = this.value[0];
            this.form.y = this.value[1];
        }
    }
    Animator.prototype.addkeys = function (kind, array) {
        if (!this.animation)
            this.animation = new Animation(kind)
        this.animation.addkeys(kind, array);
        this.manager.anims.push(this);

    }
    Animator.prototype.reset = function (stop) {

        this.t = 0;
        if (stop)
            this.stop();
    }
    Animator.prototype.restart = function (stop) {
        this.reset(stop);
        this.start();
    }
    Animator.prototype.start = function () {
        this.form.stopped = false;
        this.playing = true;

    }
    Animator.prototype.stop = function () {
        this.form.stopped = true;
        this.playing = false;
    }
    Animator.prototype.maxt = function () {
        var n = this.animation.keys.length;
        // if(n>1){
        return this.animation.keys[n - 1].t
        //}
        //  return this.animation.keys[0].t
    }


    /// class         ---------------------------- ImageResource     -----------------------------
    function ImageResource(filename) {
        this.filename = filename;
        this.image = new Image();
        this.isready = false;
        this.imw;
        this.imh;
        //this.ratio;
        var other = this;
        this.image.onload = function () {
            other.onloadcall();
        };
        this.image.src = filename;
        imageresourcecount++;
        this.onloadcall = function () {
            this.imw = this.image.naturalWidth;
            this.imh = this.image.naturalHeight;
            //this.ratio=this.imw/this.imh;
            this.isready = true;
            imageresourcecount--;

        };
        this.draw = function (ctx, x, y) {
            if (this.isready) {
                ctx.drawImage(this.image, x, y);
            }
        };
    } //// end ImageResource definition
    /// class         ---------------------------- Actor    -----------------------------
    function BBox() {
        this.init();
    }
    BBox.prototype.init = function () {
        this.xmin = Number.MAX_VALUE;
        this.ymin = Number.MAX_VALUE;
        this.zmin = Number.MAX_VALUE;
        this.xmax = Number.MIN_VALUE;
        this.ymax = Number.MIN_VALUE;
        this.zmax = Number.MIN_VALUE;
    };
    BBox.prototype.addpoint = function (x, y, z) {
        this.xmin = Math.min(x, this.xmin);
        this.xmax = Math.max(x, this.xmax);
        this.ymin = Math.min(y, this.ymin);
        this.ymax = Math.max(y, this.ymax);
        this.zmin = Math.min(z, this.zmin);
        this.zmax = Math.max(z, this.zmax);
    };



    function Actor(imres, x, y, rot, scx, scy) {
        this.imres = imres;
        this.pivotx = 128;
        this.pivoty = 16;
        this.x = x;
        this.y = y;
        this.rot = rot;
        this.scx = scx;
        this.scy = scy;
        this.v = 0;
        this.v0 = 0;
    }
    Actor.prototype.draw = function (ctx) {
        if (this.imres.isready) {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rot * degtorad);
            ctx.scale(this.scx, this.scy);
            ctx.translate(-this.pivotx, -this.pivoty);
            ctx.drawImage(this.imres.image, 0, 0);
            ctx.restore();
        }
    };

    function Actor2(imres, x, y, rot, scx, scy) {
        Actor.call(this, imres, x, y, rot, scx, scy);
    }
    Actor2.prototype = Object.create(Actor.prototype);
    Actor2.prototype.constructor = Actor2;
    Actor2.prototype.draw = function (ctx) {
        Actor.prototype.draw.call(this, ctx);
    };

    /// close opened forms eg menus drop downs 

    function Hitarea(x, y, w, h) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.type = "rect"; /// oval ngon line 
        this.p = [];

    }
    ;


    /// class         ---------------------------- F o r m    -----------------------------////////////////////////////////////////////////
    function Form(id, title, x, y, width, height, imageres) {
        "use strict"
        /// this.messages=[];////// message box for messages

        this.transformable = false;

        this.tr = new Transform();
        this.wtr = new Transform(); // view * tr
        this.tx = x;
        this.ty = y;
        this.scx = 1;
        this.scy = 1;
        this.rot = 0;
        this.pivx = 0;
        this.pivy = 0;
        this.animators = [];
        this.anims = [];
        this.stretch = !true;
        this.astep = 0;
        this.wrap = false;
        this.shadow = false;
        this.shadowdx = 3;
        this.shadowdy = 3;
        this.shadowcolor = "lightgrey";
        this.tasks = [];
        this.lastx = 0;
        this.lasty = 0;
        this.lastx1 = 0;
        this.lasty1 = 0;
        this.lastx2 = 0;
        this.lasty2 = 0;
        this.lastlen = 0;
        this.lastt = 0;
        this.lastth = 0;

        this.tooltip = undefined;// 
        this.hitareas = [];
        this.ctx = ctx;
        this.cursor = "default";
        this.picktype = 1; /// 1 rect 2  ellipse contains overrid e else i     //

        this.wheeldelta = 0;
        //// if want clip ellipse clip(1);
        this.cliptype = 0; /// 0 no clip 1 cliprect 2 clip circle; else override clip
        this.composition = "source-over";
        this.visible = true; /// use it in custom draw
        this.alpha=1;
        this.drawbackground = true;
        this.drawoutline = false;
        this.corner = 0; //if corner>0 draws roundrect outline
        this.clipped = false; // if clipped  then clips children too;
        this.commandlist = []; //   at any not defined go menu // 
        this.command = 0; ///no command 
        this.t = 0; ///time
        this.dt = 0;
        this.timescale = 1;
        this.stopped = true;
        this.pickable = true;
        ////// update in draw;
        this.id = id; /// no command  = 0 

        ///------------------------values--------------------
        this.min = 0;
        this.max = 100;
        this.value = 33; /// case scroll bar;

        this.valuename = "";
        this.valueunit = "";
        this.valuedigits = 2; // accuracy;
        this.valuedraw = false;
        this.valuex = 0;
        this.valuey = 0;
        this.kind = WINDOW;
        this.subkind = 0; /// or radio ///
        ///// if subkind =check then multi and appropriate images
        ////-----------------------
        //// if list ,mlist, check box, radio button
        this.checked = false; //// usefull as child
        this.selecteditem; /// last  checked each time usefull for list and radios
        this.selindex = -1;
        this.state = 0;
        this.states = 0; //// for multistate count childs 
        this.multiselect = false; //false;
        this.rows = 1; /// update columns; rows auto;
        this.cols = 1;
        this.backcolor = colorwin;
        this.textcolor = colortext;
        this.linecolor = "grey";
        this.lw = 1.33;
        this.draggable = false;
        this.dropable = false;
        this.dragtype = 0; /////  DRAGMOVE ,DRAFCLONE ;
        this.droptypes = [];
        ////////////////this.sm=0; //////no  scene manager no notify  //// 
        this.pressed = 0;
        this.depressed = 1;
        this.texth = 20; //text height 
        this.textcentered = true; //center left
        this.texthor = "";
        this.texver = "";
        this.parent = 0;
        if (imageres !== undefined)
            this.imageres = imageres;
        this.title = title;
        this.x = x; /// local
        this.y = y;
        this.xg = x; /// global by getparentpos;
        this.yg = y; /// 
        this.x0 = x;
        this.y0 = y;
        this.width = width;
        this.height = height;
        this.texts = []; /// 
        this.childs = []; ///
        this.xorig = 0; /// functions xo;yorigin
        this.yorig = 0;
        this.clickx = 0;
        this.clicky = 0; /// for click pos in win (local coords)
        this.setorigin(0, 0);
        this.limited = false;
        this.limit1x = 0;
        this.limit1y = 0;
        this.limit2x = 0;
        this.limit2y = 0;
        this.setpickarea(0, 0, 0, 0);
    } // end window definition 
    Form.prototype.getanimforms = function (ar, anlist) {


        if (this.animators.length > 0)
            ar.push(this)
        var j;

        for (j = 0; j < this.animators.length; j++) {

            anlist.push(this.animators[j]);
        }
        var i;
        for (i = 0; i < this.childs.length; i++) {
            this.childs[i].getanimforms(ar, anlist);
        }

    }
    Form.prototype.pivot = function (fx, fy) {
        this.pivx = fx * this.width;
        this.pivy = fy * this.height;
    }

    Form.prototype.gettimedelta = function ( ) {
        return timedelta;
    }
    Form.prototype.gettime = function ( ) {
        return time;
    }
    Form.prototype.addanimator = function (man) {
        var na = new Animator(man);
        na.form = this;
        this.animators.push(na);
        return na;
    }
    Form.prototype.createanimation = function (kind) {
        return new Animation(kind);
    }
    Form.prototype.transform = function ( ) {
        this.tr.copy(viewtr);
        //this.tr.translate(this.tx  - this.parent.xg +this.xg, this.ty -this.parent.yg +this.yg);
        this.tr.translate(this.tx, this.ty);

        this.tr.rotate(this.rot);
        this.tr.scale(this.scx, this.scy);
        this.tr.translate(-this.pivx, -this.pivy);
        settransform(ctx, this.tr);
    }

    Form.prototype.addtask = function (atype, aperiod, alife) {
        var nt = new Task(atype, aperiod, alife);
        nt.form = this;
        this.tasks.push(nt);
        return nt;
    }
    Form.prototype.debug = function (varname, value) {

        debugs.push(varname + ":" + value);
    }
    Form.prototype.move = function (ax, ay) {

        this.x = ax;
        this.y = ay;
    }
    Form.prototype.vectorlength = function (len) {

        vectorlen = len;
    }
    Form.prototype.vectortheta = function (th) {

        vectorth = th;
    }
    Form.prototype.addhitarea = function (x, y, w, h, type) {
        var nha = new Hitarea(x, y, w, h);
        var ntype = type || "rect";
        nha.type = ntype;
        this.hitareas.push(nha);
    }
    Form.prototype.setpickarea = function (dx, dy, w, h, picktype) {
        this.hitdx = dx;
        this.hitdy = dy;
        this.hitdw = w;
        this.hitdh = h;
        var ntype = picktype || 1;
        this.picktype = ntype;
    }
    Form.prototype.drawhitareas = function (ctx) {
        var i;
        this.styles("green", "black");
        //ctx.beginPath();
        this.drawrect(0, 0, this.width, this.height, 0);
        ctx.stroke();
        for (i = 0; i < this.hitareas.length; i++) {
            this.styles("green", "black");
            //ctx.beginPath();
            ctx.rect(this.hitareas[i].x + this.xg, this.hitareas[i].y + this.yg, this.hitareas[i].w, this.hitareas[i].h);
            ctx.stroke();
        }
    }

    Form.prototype.getpressed = function () {
        return pressedobject;
    }
    Form.prototype.limit = function (aminx, aminy, amaxx, amaxy) {

        this.limited = true;
        this.limit1x = aminx;
        this.limit1y = aminy;
        this.limit2x = amaxx;
        this.limit2y = amaxy;
        this.dolimit();

    }
    Form.prototype.unlimit = function () {

        this.limited = false;

    }
    Form.prototype.dolimit = function ( ) {
        if (this.x < this.limit1x)
            this.x = this.limit1x;
        if (this.y < this.limit1y)
            this.y = this.limit1y;
        if (this.x > this.limit2x)
            this.x = this.limit2x;
        if (this.y > this.limit2y)
            this.y = this.limit2y;
    }
    Form.prototype.sendmessage = function (msg) {
        sm.messages.push(msg);
    }

    Form.prototype.getmousepos = function () {
        return {x: mousex - this.xg, y: mousey - this.yg};
    }
    Form.prototype.getmouseposglobal = function () {
        return {x: mousex, y: mousey};
    }
    Form.prototype.getmousest = function () {
        return mousest;
    }
    Form.prototype.tofront = function (ch) {
        for (var i = 0; i < this.childs.length; i++) {

            if (ch === this.childs[i]) {
                var tmp = this.childs[i];
                var j;
                for (j = i; j < this.childs.length - 1; j++) {
                    this.childs[j] = this.childs[j + 1];
                }
                this.childs[this.childs.length - 1] = tmp;
                return;
                alert("to front");
            }

        }

    }
    Form.prototype.getcanvas2 = function () {
        return canvas2;
    }
    Form.prototype.getdragged = function () {
        return draggedobject;
    }
    Form.prototype.getover = function () {
        return overobject;
    }
    Form.prototype.getover2 = function () {
        return overobject2;
    }
    Form.prototype.center = function () {
        this.centerhor();
        this.centerver();

    }
    Form.prototype.centerforms = function (s, d) {

        d.x = s.x + s.width / 2 - (d.width / 2);
        d.y = s.y + s.height / 2 - (d.height / 2);

    }
    Form.prototype.centerhor = function () {
        var nx = 0;
        if (this.parent)
            nx = (this.parent.width - this.width) / 2;
        else
            nx = (logw - this.width) / 2;
        this.x = nx;

    }
    Form.prototype.centerver = function () {
        var nv = 0;
        if (this.parent)
            nv = (this.parent.height - this.height) / 2;
        else
            nv = (logh - this.height) / 2;
        this.y = nv;
    }
    Form.prototype.bottom = function (d) {
        var nv = 0;
        if (this.parent)
            nv = this.parent.height - this.height - d;
        else
            nv = logh - this.height - d;
        this.y = nv;
    }
    Form.prototype.right = function (d) {
        var nv = 0;
        if (this.parent)
            nv = this.parent.width - this.width - d;
        else
            nv = logw - this.width - d;
        this.x = nv;
    }

    Form.prototype.backout = function (drawbackground, drawoutline) {
        this.drawbackground = drawbackground;
        this.drawoutline = drawoutline || false;
    }
    Form.prototype.setvaluepos = function (ax, ay) {
        this.valuex = ax;
        this.valuey = ay;
    }
    Form.prototype.setvaluedescr = function (aname, aunit, adigits) {
        this.valuename = aname;
        this.valueunit = aunit;
        this.valuedigits = adigits;
    }
    Form.prototype.create = function () {}
    Form.prototype.init = function () {}
    Form.prototype.update = function () {


    }
    Form.prototype.render = function () {}
    Form.prototype.setbackcolor = function (r, g, b, a) {
        this.backcolor = rgba(r, g, b, 1 || a);
    }

    Form.prototype.drawimagetr = function (imageres, tx, ty, rot, sx, sy, pivx, pivy) {
        if (imageres.isready) {
            ctx.save();
            rot = rot || 0;
            sx = sx || 1;
            sy = sy || 1;
            pivx = pivx || 0;
            pivy = pivy || 0;
            //var tr2 = new Transform(viewtr);
            this.tr.copy(viewtr);
            this.tr.translate(tx + this.xg, ty + this.yg);
            this.tr.rotate(rot);
            this.tr.scale(sx, sy);
            this.tr.translate(-pivx, -pivy);
            // ***tr2.translate(pivx, pivy);
            settransform(ctx, this.tr);


            ctx.drawImage(imageres.image, 0, 0);


            ctx.restore();
        }

    }
    Form.prototype.fillimage = function () {
        if (!this.imageres)
            return;
        if (!this.imageres.image)
            return;
        this.ctx.drawImage(this.imageres.image, 0 + this.xg, 0 + this.yg, this.width, this.height);
    }
    Form.prototype.drawimage = function (imageres, tw, th, centered) {
        if (!imageres)
            return;
        if (!imageres.image)
            return;
        var imw = imageres.imw;
        if (!imw)
            imw = logw;
        var imh = imageres.imh;
        if (!imh)
            imh = logh;
        var nw, nh;
        nw = tw;
        nh = tw * imh / imw;
        var px = 0;
        var py = (th - nh) / 2;
        if (nh > th) {
            nh = th;
            nw = th * imw / imh;
            py = 0;
            px = (tw - nw) / 2;
        }
        if (!centered) {
            px = 0;
            py = 0
        }

        ctx.drawImage(imageres.image, this.xg + px, this.yg + py, nw, nh);
    }
    Form.prototype.drawimageto = function (imageres, x, y) {
        if (!imageres)
            return;
        if (!imageres.image)
            return;

        ctx.drawImage(imageres.image, this.xg + x, this.yg + y);
    }
    Form.prototype.drawimagefill = function (imageres) {
        if (!imageres)
            return;
        if (!imageres.image)
            return;

        ctx.drawImage(imageres.image, this.xg + 0, this.yg + 0, this.width, this.height);
    }
    Form.prototype.drawpolar = function (x, y, r, thrad) {
        drawpolar(ctx, x + this.xg, this.yg + y, r, thrad);
    }
    Form.prototype.clip = function () {
        ctx.save();
        var v = this.getparentpos();
        ctx.beginPath();
        ctx.lineWidth = "3";
        if (this.cliptype === 1)
            ctx.rect(v.x, +v.y, this.width, this.height);
        if (this.cliptype === 2)
            ctx.arc(v.x + this.width / 2, v.y + this.width / 2, this.width / 2, 0, twopi, false);
        ctx.clip();
    }
    Form.prototype.drawvector = function (x1, y1, x2, y2) {
        var thrad = Math.atan2(y2 - y1, x2 - x1);
        var r = Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
        if (r < 1)
            return;
        var vl = vectorlen;
        if (vectorlen > r / 2)
            vl = r / 2;
        this.drawpolar(x1, y1, r, thrad);
        this.drawpolar(x2, y2, vl, thrad + vectorth);
        this.drawpolar(x2, y2, vl, thrad - vectorth);
    }
    Form.prototype.drawvectorrev = function (x1, y1, x2, y2) {

        this.drawvector(x2, y2, x1, y1)
    }
    Form.prototype.drawpolarvector = function (x, y, r, thrad) {
        this.drawvector(x, y, x + r * Math.cos(thrad), y + r * Math.sin(thrad));
    }
    Form.prototype.dptolp = function (ax, ay) {
        /// tr -1 *  viewtr -1
        var inv = new Transform(this.tr);
        inv.invert();
        var sec = new Transform(viewtr);
        sec.invert();
        inv.multiply(sec);
        return inv.transformPoint(ax, ay)
    };
    Form.prototype.lptodp = function (ax, ay) {
        var inv = new Transform(this.wtr);
        inv.invert();
        //inv.multiply(this.tr);
        return inv.transformPoint(ax, ay)
    };
    Form.prototype.setorigin = function (xo, yo) {
        var v = this.getparentpos();
        this.xorig = v.x + xo;
        this.yorig = v.y + yo;
    }

    Form.prototype.drawarcfilled = function (xo, yo, r, st, en, anticlock, linestyle) {
        if (linestyle)
            ctx.fillStyle = linestyle;
        ctx.beginPath();

        st = twopi - st;
        en = twopi - en;
        if (st > en) {
            var tmp = st;
            st = en;
            en = tmp;
        }
        ctx.moveTo(xo + this.xorig, this.yorig - yo);
        ctx.arc(xo + this.xorig, this.yorig - yo, r, st, en, anticlock);
        ctx.fill();
    }
    Form.prototype.drawfilltext = function (str, x, y, linestyle) {
        if (linestyle)
            ctx.fillStyle = linestyle;
        ctx.fillText(str, x + this.xorig, -y + this.yorig);
    }

    Form.prototype.drawcirclefilled = function (xo, yo, r, linestyle) {
        this.drawarcfilled(xo, yo, r, 0, twopi, false, linestyle);
    }
/// to parabola
//
//
    Form.prototype.drawparabola = function (a, xo, yo, x1, x2, n, closed, filled) {
        var i;
        ctx.beginPath();
        var x, y;
        var dx, dy;
        for (i = 0; i <= n; i++) {
            x = x1 + i * (x2 - x1) / n;
            y = a * x * x;
            dx = x + xo + this.xg;
            dy = y + yo + this.yg;
            if (i === 0)
                ctx.moveTo(dx, dy);
            else
                ctx.lineTo(dx, dy);

        }
        ctx.stroke();

    }
    ///no origin //////////////
    Form.prototype.drawarc = function (xo, yo, r, st, en, anticlock, closed, filled) {
        drawarc(ctx, xo + this.xg, yo + this.yg, r, st, en, anticlock, closed, filled)
    }

    ///  ok
    Form.prototype.drawcircle = function (xo, yo, r, filled) {
        drawarc(ctx, xo + this.xg, yo + this.yg, r, 0, twopi, false, false, filled)
    }
    /// no origin 
    Form.prototype.drawbezier = function (x0, y0, x1, y1, x2, y2, x, y, filled, closed) {
        var filled = filled || 0;
        var closed = closed || false;
        ctx.beginPath();
        ctx.moveTo(x0 + this.xg, y0 + this.yg);
        ctx.bezierCurveTo(x1 + this.xg, y1 + this.yg, x2 + this.xg, y2 + this.yg, x + this.xg, y + this.yg);
        if (closed)
            ctx.endPath();
        if (filled === 0 || filled === 2)
            ctx.stroke();
        if (filled === 1 || filled === 2)
            ctx.fill();

    }
    Form.prototype.drawrectform = function (f, filled) {

        drawrect(ctx, f.xg, f.yg, f.width, f.height, filled);
    }

    /// no origin 
    Form.prototype.drawtextform = function (f, text, size, centerleft) {

        drawtext(ctx, text, f.width / 2 + f.xg, f.height / 2 + f.yg, size, centerleft);
    }
    /// no origin 
    Form.prototype.lineargrad = function (x1, y1, x2, y2) {

        return this.ctx.createLinearGradient(this.xg + x1, this.yg + y1, this.xg + x2, this.yg + y2);
    }
    Form.prototype.radialgrad = function (x1, y1, r1, x2, y2, r2) {

        return this.ctx.createRadialGradient(this.xg + x1, this.yg + y1, r1, this.xg + x2, this.yg + y2, r2);
    }
    Form.prototype.drawrect = function (x1, y1, w, h, filled) {

        drawrect(ctx, x1 + this.xg, y1 + this.yg, w, h, filled);
    }
    Form.prototype.styles = function (ls, fs) {
        styles(ctx, ls, fs);
    }

    Form.prototype.lineargradient = function (x1, y1, x2, y2) {
        var grd = ctx.createLinearGradient(x1 + this.xg, y1 + this.yg, x2 + this.xg, y2 + this.yg);
        return grd;
    }

    Form.prototype.drawcylinder = function (x1, y1, w, h, filled) {
        ctx.beginPath();
        var dx = w / 3;
        var dy = w / 6;
        var xi = x1 + this.xg;
        var yi = y1 + this.yg
        ctx.moveTo(xi, yi);
        ctx.bezierCurveTo(xi, yi - dy, xi + w, yi - dy, xi + w, yi);
        ctx.lineTo(xi + w, yi + h);
        ctx.bezierCurveTo(xi + w, yi + h + dy, xi, yi + h + dy, xi, yi + h);
        ctx.closePath();
        if (filled)
            ctx.fill();
        ctx.stroke();
    }
    Form.prototype.drawcylinderfront = function (x1, y1, w, h, filled) {
        ctx.beginPath();
        var dx = w / 3;
        var dy = w / 6;
        var xi = x1 + this.xg;
        var yi = y1 + this.yg
        ctx.moveTo(xi, yi);
        ctx.bezierCurveTo(xi, yi + dy, xi + w, yi + dy, xi + w, yi);
        ctx.lineTo(xi + w, yi + h);
        ctx.bezierCurveTo(xi + w, yi + h + dy, xi, yi + h + dy, xi, yi + h);
        ctx.closePath();
        if (filled)
            ctx.fill();
        ctx.stroke();
    }
    Form.prototype.drawcylindertop = function (x1, y1, w, h, filled) {
        ctx.beginPath();
        var dx = w / 3;
        var dy = w / 6;
        var xi = x1 + this.xg;
        var yi = y1 + this.yg
        ctx.moveTo(xi, yi);
        ctx.bezierCurveTo(xi, yi - dy, xi + w, yi - dy, xi + w, yi);
        //ctx.lineTo(xi+w,yi+h);
        ctx.bezierCurveTo(xi + w, yi + dy, xi, yi + dy, xi, yi);
        ctx.closePath();
        if (filled)
            ctx.fill();
        ctx.stroke();
    }

    Form.prototype.drawcylinderbottom = function (x1, y1, w, h, filled) {

        ctx.beginPath();
        var dx = w / 3;
        var dy = w / 6;
        var xi = x1 + this.xg;
        var yi = y1 + this.yg
        ctx.moveTo(xi + w, yi + h);
        ctx.bezierCurveTo(xi + w, yi + h - dy, xi, yi + h - dy, xi, yi + h);
        if (filled)
            ctx.fill();
        ctx.stroke();

    }
    /// no origin 
    Form.prototype.drawtext = function (text, x, y, size, centerleft) {

        drawtext(ctx, text, x + this.xg, y + this.yg, size, centerleft);
    }
    // no origin 

    Form.prototype.drawpolygon = function (p, filled, closed, percent, st, len) {
        var i;
        var np = []
        for (i = 0; i < p.length / 2; i++) {
            np.push(p[2 * i] + this.xg);
            np.push(p[2 * i + 1] + this.yg);
        }
        drawpolygon(ctx, np, filled, closed, percent, st, len)
    }
    Form.prototype.drawgraph = function (p, x0, y0, scx, scy) {
        var i;
        var x0 = x0 || 0;
        var y0 = y0 || 0;
        var scx = scx || 1;
        var scy = scy || 1;
        for (i = 0; i < p.length; i++) {
            this.drawline(i * scx + x0, y0 - p[i] * scy + 2, i * scx + x0, y0 - p[i] * scy)
        }

    }
    Form.prototype.drawcurve = function (x, y, filled, closed, percent) {
        var i;
        percent = percent || 1
        ctx.beginPath();
        for (i = 0; i < x.length * percent; i++) {
            if (i === 0)
                ctx.moveTo(x[i] + this.xg, y[i] + this.yg);
            if (i > 0)
                ctx.lineTo(x[i] + this.xg, y[i] + this.yg);
        }
        if (closed)
            ctx.closePath();
        if (filled > 0)
            ctx.fill();
        if (filled === 0 || filled === 2)
            ctx.stroke();


    }
    // no origin //   because form can be moved so xg yg 

    Form.prototype.dash = function (ar) {
        this.ctx.setLineDash(ar);
    }
    Form.prototype.drawline = function (x1, y1, x2, y2, t) {
        this.lastt = t || 1
        ctx.beginPath();
        var xa = x1 + this.xg;
        var ya = this.yg + y1;
        var xb = x2 + this.xg;
        var yb = this.yg + y2;
        ctx.moveTo(xa, ya);
        this.lastx = xa + (xb - xa) * this.lastt;
        this.lasty = ya + (yb - ya) * this.lastt;
        ctx.lineTo(this.lastx, this.lasty);
        ctx.stroke();

    }
    Form.prototype.drawlinecv = function (x1, y1, x2, y2, vel, t) {
        var sol = Math.sqrt(x1 * x1 + y1 * y1);

        if (sol < 0.01) {
            t = 1;
        } else
            t = vel * t / sol;
        if (t > 1)
            t = 1;
        this.drawline(x1, y1, x2, y2, t);

    }
    /// no origin 
    Form.prototype.drawball = function (xo, yo, r, linestyle) {

        var cx = xo + this.xg;
        var cy = yo + this.yg;
        var grd = ctx.createRadialGradient(cx, cy, r / 10, cx, cy, r * 1.5);
        if (!linestyle)
            grd.addColorStop(0, "white");
        else
            grd.addColorStop(0, linestyle);
        grd.addColorStop(1, "black");

        ctx.fillStyle = grd;

        drawcirclefilled(ctx, cx, cy, r, 0, twopi, false);

    }

    /// draw arrow no origin 
    Form.prototype.drawarrow = function (x, y, len, th, arh, d, filled) {
        if (len < 0) {
            len = abs(len);
            th += Math.PI;
        }
        drawarrow(ctx, x + this.xg, y + this.yg, len, th, arh, d, filled)
    }
    Form.prototype.drawarrowc = function (x1, y1, x2, y2, arh, d, filled) {
        drawarrow(ctx, x1 + this.xg, y1 + this.yg, Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)), Math.atan2((y2 - y1), x2 - x1), arh, d, filled)
    }

    // x,y center len half len
    Form.prototype.drawdistance = function (x, y, len, th, arh, d, filled) {
        drawdistance(ctx, x + this.xg, y + this.yg, len, th, arh, d, filled)
    }

    Form.prototype.pause = function (b) {
        this.stopped = false;
        if (b)
            this.stopped = true;
    };
    //  Form.prototype.settime = function (atime) {
    //      this.t = atime;
    //  };
    Form.prototype.setvalues = function (amin, amax, avalue) {
        this.min = amin;
        this.max = amax;
        this.value = avalue;
        this.setscrollpos(amin, amax, avalue);
    };
    Form.prototype.setscrollpos = function (amin, amax, avalue) {
        this.min = amin;
        this.max = amax;
        this.value = avalue;
        if (this.kind !== SCROLLBAR)
            return;
        var ishor = false;
        var but = this.childs[1];
        var dis = 100;
        //this.y=(this.value-this.min)*dis/(this.max-this.min);
        if (this.width > this.height)
            ishor = true;
        if (ishor) {
            //alert (this.de)
            but.y = this.height - this.de - this.de / 2;
            dis = this.width - but.width;
            but.x = (this.value - this.min) * dis / (this.max - this.min);
            //but.width = (this.value - this.min) * dis / (this.max - this.min);
            //but.x =0; 
        } else {
            but.x = this.width - this.de - this.de / 2;
            dis = this.height - but.height;
            but.y = (this.value - this.min) * dis / (this.max - this.min);
            //but.height = (this.value - this.min) * dis / (this.max - this.min);
            //but.y = 0; 
        }
    };
    Form.prototype.fixscrollbar = function (sb) {
        if (sb.kind !== SCROLLBAR)
            return;
        var ishor = false; //is vertical
        var dis = 0;
        var d1 = 0;
        var d2 = 0;

        if (sb.width > sb.height)
            ishor = true;

        if (ishor) {

            dis = (sb.clickx - sb.de / 2) / (sb.width - sb.de);

        } else {
            dis = (sb.clicky - sb.de / 2) / (sb.height - sb.de);
        }

        if (dis < 0)
            dis = 0;
        if (dis > 1)
            dis = 1;
        sb.value = sb.min + dis * (sb.max - sb.min);
        ///if (sb.astep===0) sb.value=toround(sb.value);
        if (sb.astep)
            sb.value = step(sb.value, sb.astep)
        sb.setvalues(sb.min, sb.max, sb.value);
        sb.onvaluechange();
        sm.onvaluechange(sb);

    };
    Form.prototype.addsprite = function (id, title, x, y, w, h, imageres) {
        var nw = new Sprite(id, title, x, y, w, h, imageres);



        this.addchild(nw);
        return nw;
    };
    Form.prototype.addapp = function (id, title) {
        var sb = new App(id, title);
        sb.kind = APP;
        this.addchild(sb);
        return sb;
    };
    Form.prototype.addclockwin = function (id, title, x, y) {
        var sb = new Clockwin(0, "clockwin", x, y);
        sb.kind = APP;
        this.addchild(sb);
        return sb;
    };
    Form.prototype.addform3d = function (id, title, x, y, w, h) {
        var nf = new Form3d(id, title, x, y, w, h);
        nf.kind = "3d";
        this.addchild(nf);
        return nf;
    };
    Form.prototype.addscrollbar = function (id, title, x, y, width, height, imageres) {
        var sb = new Form(id, "", x, y, width, height, imageres);
        sb.de = sb.height / 2; // new attr 
        sb.rede = sb.height / 8;
        sb.kind = SCROLLBAR;
        sb.valuedraw = true;
        sb.valuename = title;
        sb.setvaluepos(12, -32);
        sb.cursor = "pointer";
        sb.drawbackground = false;
        sb.drawoutline = false;
        /// hor
        var sbrect = sb.addform(0, "", sb.de / 2, (height - sb.rede) / 2, width - sb.de, sb.rede, imageres);
        //var sbrect = sb.addform(0, "", 0, 0  , width, height  , imageres);
        sbrect.pickable = false;
        sbrect.drawoutline = true;
        sbrect.backcolor = rgb(133, 133, 133);
        this.addchild(sb);
        /////add a test win
        var ishor = false;
        if (sb.width > sb.height)
            ishor = true; ///
        //var sbwi = sb.width/3;
        // var sbhi = sb.width/3;
        if (ishor) {
            sb.de = sb.height / 2;
            //   sbwi = sb.height/3;
            //   sbhi = sb.height/3;// * 0.33;
        }
        if (!ishor) {
            sb.de = sb.width / 2;
            sb.rede = sb.width / 8;
            sbrect.x = (width - sb.rede) / 2;
            sbrect.y = sb.de / 2;
            sbrect.width = sb.rede;
            sbrect.height = height - sb.de;
        }
        var but = new Form(id, title, 0, 0, sb.de, sb.de, imageres);
        but.title = "";
        sb.addchild(but);
        but.corner = sb.de / 6;

        but.pickable = false;
        but.draggable = true;
        but.backcolor = colorbutton; //rgb(128, 128, 178);
        sb.backcolor = colorwin; //rgb(200, 200, 200);
        sb.setscrollpos(sb.min, sb.max, sb.value);
        but.drawoutline = true;
        // but.drawbackground = false;
        return sb;
    };

    Form.prototype.adddrag = function (id, title, x, y, width, height, imageres) {
        var nw = new Drag(id, title, x, y, width, height, imageres);
        this.addchild(nw);
        return nw;
    };
    Form.prototype.addmultistate = function (id, title, x, y, width, height, imageres) {
        var nw = new Multistate(id, title, x, y, width, height, imageres);
        this.addchild(nw);
        nw.backcolor = rgb(255, 255, 255);
        nw.drawbackground = false;
        nw.drawoutline = false;
        nw.cursor = "pointer";
        return nw;
    };



    Form.prototype.addlabel = function (id, title, x, y, width, height, imageres) {
        var nw = new Form(id, title, x, y, width, height, imageres);
        nw.kind = LABEL;
        nw.pickable = false;
        this.addchild(nw);
        nw.backcolor = "white";////
        return nw;
    };
    Form.prototype.getimageres = function (type) {
        if (type === "about")
            return iconabout;
        if (type === "help")
            return iconhelp;
        if (type === "close")
            return iconclose;
        if (type === "clock1")
            return clock1;
        if (type === "clock2")
            return clock2;
        return undefined;
    };
    Form.prototype.addform = function (id, title, x, y, width, height, imageres) {
        var nw = new Form(id, title, x, y, width, height, imageres);
        this.addchild(nw);
        nw.backcolor = colorwin;
        return nw;
    };
    Form.prototype.addshape = function (id, title, x, y, width, height, imageres) {
        var nw = new Form(id, title, x, y, width, height, imageres);
        this.addchild(nw);
        nw.backcolor = colorwin;
        nw.backout(false);
        return nw;
    };
    Form.prototype.addclosebutton = function (imageres) {
        var nw = this.addbutton(0, "x", this.width - 32, 0, 32, 32, imageres);
        var scope = this;
        nw.onclick = function () {
            scope.visible = false;
        }
        return nw;
    };
    Form.prototype.addbutton = function (id, title, x, y, width, height, imageres) {
        var nw = new Form(id, title, x, y, width, height, imageres);
        nw.kind = BUTTON;
        nw.cursor = "pointer";
        nw.backcolor = colorbutton; // rgb(155, 155, 155);
        nw.drawbackground = true;
        nw.drawoutline = true;
        this.addchild(nw);
        //this.textcentered=true;
        return nw;
    };
    Form.prototype.addbuttoncommand = function (command, plist, id, title, x, y, width, height, imageres) {
        var nw = this.addbutton(id, title, x, y, width, height, imageres);
        nw.kind = BUTTON;
        nw.backcolor = colorbutton; //rgb(155, 155, 155);
        nw.drawbackground = false;
        nw.command = command;
        nw.commandlist = [];
        for (var i = 0; i < plist.length; i++) {
            nw.commandlist.push(plist[i]);
        }
        //this.addchild(nw);
        return nw;
    };
    Form.prototype.addpushbutton = function (id, title, x, y, width, height, imageres) {

        var nw = this.addbutton(id, title, x, y, width, height, imageres);
        nw.kind = PUSHBUTTON;
        //this.addchild(nw);
        return nw;
    };

    function hidedown() {
        var i;
        ///alert (hidelist.length);
        for (i = 0; i < hidelist.length; i++) {
            var frm = hidelist[i];
            var cnd = (!hidelist[i].contains(mousex, mousey));
            //cnd=frm!==pressedobject;
            if (cnd) {
                hidelist[i].visible = false;

            }

        }
        hidelist = [];
    }
    Form.prototype.has = function (ob) {
        var i;
        if (this === ob)
            return true;
        for (i = 0; i < this.childs.length; i++) {
            return  has(childs[i]);
        }
        return false;
    }
    /// drop down
    Form.prototype.adddropdown = function (id, title, x, y, width, height, imageres) {

        var nw = new Dropdown(id, title, x, y, width, height);
        this.addchild(nw);
        nw.kind = 'dropdown';
        return nw;


    };
    function Dropdown(id, title, x, y, width, height) {


        Form.call(this, id, title, x, y, width, height);

        this.butn = this.addbutton(id, title, 0, 0, width, height);
        this.butn.textcentered = false;
        var dd = this.butn.addlabel("ldd", "", this.butn.width - 48, 0, 48, 48, icondropdown);
        dd.drawbackground = false;
        this.list = this.addlist("lliisstt", "", 0, 0, width, 655.1);

        this.list.visible = false;
        var vlist = this.list;
        vlist.drawbackground = true;
        vlist.backcolor = "yellow";
        vlist.drawoutline = true;
        this.butn.onclick = function () {
            vlist.visible = true;
            hidelist.push(vlist);/// 

        }





    }

/// caution after constructor 
    Dropdown.prototype = Object.create(Form.prototype);
    Dropdown.prototype.constructor = Dropdown;

    Dropdown.prototype.getselindex = function () {

        return this.list.selindex;


    }

    Dropdown.prototype.setselindex = function (n) {

        this.list.selectitem(n);
        this.butn.title = this.list.childs[n].title;

    }

    Dropdown.prototype.additems = function (ar) {
        var i;

        for (i = 0; i < ar.length; i++) {
            var li = this.list.addlistitem("li", ar[i], 0, i * this.height, this.width, this.height, undefined);
            li.onclick = function () {
                li.parent.visible = false;

            }
        }
        this.list.height = ar.length * this.height;

        this.list.selectitem(0);

    }


    ////////   addchild with proper image list mlist check combo
    Form.prototype.addlist = function (id, title, x, y, width, height, imageres) {
        var nw = new Form(id, title, x, y, width, height, imageres);
        nw.kind = LIST;
        nw.multiselect = false;
        this.addchild(nw);
        nw.backcolor = rgb(0, 250, 250);
        return nw;
    };
    Form.prototype.addmlist = function (id, title, x, y, width, height, imageres) {
        var nw = new Form(id, title, x, y, width, height, imageres);
        nw.kind = LIST;
        nw.multiselect = true;
        this.addchild(nw);
        nw.backcolor = rgb(0, 250, 250);
        return nw;
    };
    Form.prototype.addcheck = function (id, title, x, y, width, height, imageres) {
        var nw = new Form(id, title, x, y, width, height, imageres);
        nw.kind = LIST;
        nw.subkind = CHECK;
        nw.multiselect = true;
        this.addchild(nw);
        nw.backcolor = colorcheck;
        nw.drawoutline = true;
        return nw;
    };
    Form.prototype.addradio = function (id, title, x, y, width, height, imageres) {
        var nw = new Form(id, title, x, y, width, height, imageres);
        nw.kind = LIST;
        nw.subkind = RADIO;
        nw.multiselect = false;
        this.addchild(nw);
        nw.backcolor = colorcheck;
        nw.drawoutline = true;
        return nw;
    };
    Form.prototype.addlistitem = function (id, title, x, y, width, height, imageres) {
        var nw = new Form(id, title, x, y, width, height, imageres);
        nw.kind = LISTITEM;
        this.addchild(nw);
        nw.cursor = "pointer";
        nw.texth = this.texth;
        //
        return nw;
    };

    /// sets selindex if list ob is selecteditem
    Form.prototype.setselindex = function (ob) {
        this.selindex = -1;
        if (this.kind !== LIST)
            return;


        for (var i = 0; i < this.childs.length; i++) {
            if (ob === this.childs[i]) {
                this.selindex = i;
            }
        }

    };
    Form.prototype.getselindex = function () {
        return this.selindex;

    };
    ///// pressed list item object so only this check on list 
    Form.prototype.listpressed = function (ob) {
        if (!this.multiselect) {
            for (var i = 0; i < this.childs.length; i++) {
                this.childs[i].checked = (ob === this.childs[i]);
            }
        }
    };
    /// recalc position 
    Form.prototype.setchilds = function (ax, ay, dx, dy, nw, nh) {
        var si;
        for (si = 0; si < this.childs.length; si++) {
            this.childs[si].x = ax + si * dx;
            this.childs[si].y = ay + si * dy;
            if (nw)
                this.childs[si].width = nw;
            if (nh)
                this.childs[si].height = nh;

        }
    };
    Form.prototype.setchildsarray = function (rows, cols, dx, dy) {
        var c, r;
        var i;
        for (r = 0; r < rows; r++) {

            for (c = 0; c < cols; c++) {
                i = cols * r + c;
                if (i < this.childs.length) {
                    this.childs[i].x = c * dx;
                    this.childs[i].y = r * dy;
                }

            }

        }
    };

    Form.prototype.selectitem = function (n) {
        this.selecteditem = undefined;
        if (n < 0 || n >= this.childs.length) {


            return;
        }
        this.selecteditem = this.childs[n];
        this.childs[n].checked = true;
        this.setselindex(this.selecteditem);
        if (this.multiselect)
            return;/// 
        var i;
        for (i = 0; i < this.childs.length; i++) {
            this.childs[i].checked = (n === i);

        }

    };
    Form.prototype.unselectitem = function (n) {
        this.selecteditem = undefined;

        if (n < 0 || n > this.childs.length)
            return;
        this.childs[n].checked = false;
    };
    Form.prototype.checklist = function (n) {
        if (n < 0 || n > this.childs.length)
            return false;
        if (this.kind !== LIST)
            return false;
        if (!this.multiselect)
            return this.selecteditem === this.childs[n];
        return this.childs[n].checked;
    };
    Form.prototype.checkeditem = function (n) {
        if (n < 0 || n > this.childs.length)
            return false;
        if (this.kind !== LIST)
            return false;
        return this.childs[n].checked;
    };
    Form.prototype.setkind = function (kind) {
        this.kind = kind;
    };
    Form.prototype.setsubkind = function (akind) {
        this.subkind = akind;
    };

    Form.prototype.inside = function (x, y) {
        var v = this.getparentpos();

        if (x < v.x)
            return false;
        if (y < v.y)
            return false;
        if (x > v.x + this.width)
            return false;
        if (y > v.y + this.height)
            return false;
        return true;

    }

    Form.prototype.mouseoverforms = function (alist) {
        var v = this.getmouseposglobal();
        var i;
        for (i = 0; i < alist.length; i++) {
            if (alist[i].inside(v.x, v.y))
                return alist[i];
        }

        return undefined;
    }

    Form.prototype.contains = function (ax, ay) {


        /// hit areas;
        if (!this.pickable)
            return false;


        var v = this.getparentpos();
        if (ax < v.x + this.hitdx)
            return false;
        if (ay < v.y + this.hitdy)
            return false;
        if (ax > this.width + this.hitdw + v.x + this.hitdx)
            return false;
        if (ay > this.height + this.hitdh + v.y + this.hitdy)
            return false;


        /////
        //// ok now we have hit win 
        // 
        this.clickx = ax - (v.x + this.hitdx);
        this.clicky = ay - (v.y + this.hitdy);
        ///********
        if (this.picktype === 1)
            return true;
        if (this.picktype === 2) {
            var cx = v.x + this.hitdx + (this.hitdw + this.width) / 2;
            var cy = v.y + this.hitdy + (this.hitdh + this.height) / 2;
            var rx = (this.hitdw + this.width) / 2;
            var ry = (this.hitdh + this.height) / 2;

            //return ((cx-ax)*(cx-ax)+(cy-ay)*(cy-ay)<this.width/2*this.width/2);
            return Math.pow((cx - ax) / rx, 2) + Math.pow((cy - ay) / ry, 2) <= 1;
        }




        return false;
    };
    Form.prototype.addtext = function () {
        var st = "";
        for (var i = 0; i < arguments.length; i++) {
            st += arguments[i] + " ";
            //this.texts.push(arguments[i]);
            ///// this.msg("hello from log"); works !!!!!!!!
        }
        this.texts.push(st);
    };
    Form.prototype.addchild = function () {
        for (var i = 0; i < arguments.length; i++) {
            this.childs.push(arguments[i]);
            arguments[i].parent = this;
        }
    };
    Form.prototype.getparentpos = function () {
        var parx = this.x;
        var pary = this.y;
        var v = this.parent;
        while (v) {
            parx += v.x;
            pary += v.y;
            v = v.parent;
        }
        /// ok update 
        this.xg = parx;
        this.yg = pary;
        return {
            x: parx,
            y: pary
        };
    };
    Form.prototype.devtolog = function (ax, ay) {
        //  -this.xorig+mousex,this.yorig-mousey	
        return {
            x: ax - this.xorig,
            y: -ay + this.yorig
        };
    };
    Form.prototype.logtodev = function (ax, ay) {
        return {
            x: ax + this.xorig,
            y: -ay + this.yorig
        };
    };
    Form.prototype.checkmouse = function (x, y) {
        ////// fills clicks[] for win
        // maybe for all forms not to overlap
        if (!this.visible)
            return;

        if (this.contains(x, y)) {
            clicks.push(this);

        }
        for (var i = 0; i < this.childs.length; i++) {
            this.childs[i].checkmouse(x, y);
        }
    };
    Form.prototype.home = function () {
        this.x = this.x0;
        this.y = this.y0;
    };
    Form.prototype.onvaluechange = function (ob) {
        return (ob !== undefined);
        /// do whatever on scroll bars
    };
    Form.prototype.onwheel = function (e) {
        /// do whatever 
    }; //// end onmdt
    Form.prototype.onmousedown = function () {
        /// do whatever 
    }; //// end onmdt
    Form.prototype.onmousemove = function () {
        /// do whatever 
    }; //// end onm mv
    Form.prototype.onmouseup = function () {};
    Form.prototype.onclick = function () {
        /// do whatever 
    };

    Form.prototype.onchildclicked = function (ch) {
        /// do whatever child ch clicked
    };
    Form.prototype.onenter = function () {

    }; //// end onmdt
    Form.prototype.onleave = function () {

    }; //// end onmdt
    Form.prototype.ondrop = function (dro, ovo) {
        /// do whatever  droppedobject dropped over  oveobject2
    };
    Form.prototype.ondragstart = function (dro) {
        /// do whatever  droppedobject dropped over  oveobject2
    };
    Form.prototype.onmessage = function (type, param) {
        // override this and read msg
        /// do whatever  droppedobject dropped over  oveobject2
    };
    Form.prototype.onevent = function (e, type) {
        /////  handle childs event first 
        ///// useless until now 
        if (type === MOUSEDOWN) {
        }
        var i = 0;
        // for (i=this.childs.length-1;i>-1;i--){
        //    this.childs[i].onevent(e,type);
        //}   
        for (i = 0; i < this.childs.length; i++) {
            this.childs[i].onevent(e, type);
        }
        ///// now its time to handle which mousedown
    }; //// end windo onevent
    ////
    Form.prototype.setpos = function () {

        var v = this.getparentpos();
        this.xg = v.x + this.pressed;
        this.yg = v.y + this.pressed;

    };
    Form.prototype.setanimtime = function (t) {

        var i;

        for (i = 0; i < this.anims.length; i++) {

            this.anims[i].t = t;
            //this.anims[i].update(0);

        }

    };

    Form.prototype.settime = function () {
        this.dt = timedelta * this.timescale * (!this.stopped);
        this.t += this.dt;
        // if (this.t < 0)
        //    this.t = 0;

    }


    Form.prototype.setpost = function () {
        this.setpos();
        this.settime();
        this.update();
        var i;

        for (i = 0; i < this.animators.length; i++) {

            this.animators[i].update(this.dt);

        }
        for (i = 0; i < this.tasks.length; i++) {
            this.tasks[i].update();
        }
    };
    Form.prototype.setpicktype = function (apt) {
        // 1 rect  2// ellipse   3 polygon 
        this.picktype = apt;


    }
    Form.prototype.below = function (aform, d) {
        aform.setpos();
        this.x = aform.xg;
        this.y = aform.yg + d + aform.height;

    }
/////////////------------------------------------------------------------------------////////////////////////////////////////////////////////
    Form.prototype.draw = function (ctx) {

        if (this.transformable) {
            ctx.save();
            this.transform();
        }

        this.setpost(); /// position x y and time
        if (!this.visible)
            return;

      if (this.alpha<1) ctx.globalAlpha = this.alpha;
        ctx.globalCompositeOperation = this.composition;
        if (this.cliptype > 0)
            this.clip();
        var selcolorink = this.textcolor;
        ctx.lineWidth = this.lw;
        ctx.linestyle = "black"
        ctx.strokeStyle = "white";
        if (this.kind === LABEL) {

        }
        ctx.fillStyle = this.backcolor;
        ///var drawbackground = true;
        /// if list dont draw background
        if (this.kind === LISTITEM) {
            this.drawbackground = false;
            if (this.parent.subkind === CHECK) {
                this.imageres = check1;
            }
            if (this.parent.subkind === RADIO) {
                this.imageres = radio1;
            }
            ///// if non multistate 
            if (this.parent.multiselect && this.checked) {
                this.drawbackground = true;
                selcolorink = "white";
                ctx.fillStyle = "blue"; ///rgb(123,123,123);
                if (this.parent.subkind === CHECK) {
                    this.imageres = check2;
                }
                if (this.parent.subkind === RADIO) {
                    this.imageres = radio2;
                }
            }
            if (!this.parent.multiselect && this === this.parent.selecteditem) {
                this.drawbackground = true;
                selcolorink = "white";
                ctx.fillStyle = "blue"; ///rgb(123,123,123);
                if (this.parent.subkind === CHECK) {
                    this.imageres = check2;
                }
                if (this.parent.subkind === RADIO) {
                    this.imageres = radio2;
                }
            }
            if (this.parent.subkind === CHECK || this.parent.subkind === RADIO) {
                this.drawbackground = false;
                selcolorink = this.textcolor;
            }
        } /// end is listitem 

        if (this.shadow) {
            ctx.fillStyle = this.shadowcolor;
            ctx.fillRect(this.xg + this.shadowdx, this.yg + this.shadowdy, this.width, this.height);
            ctx.fillStyle = this.backcolor;
        }
        if (this.drawbackground) {
            if (this.corner <= 0) {
                ctx.fillRect(this.xg, this.yg, this.width, this.height);
            } else {
                drawroundrect(ctx, this.xg, this.yg, this.width, this.height, this.corner, 1);
            }


        }


        ctx.fillStyle = selcolorink;

        ctx.font = this.texth + "px Helvetica";
        ctx.textAlign = "left";
        if (this.textcentered && !this.wrap)
            ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        var ofsx = 10 * (!this.textcentered) + this.xg + this.width / 2 * this.textcentered;
        var ofsy = this.yg + this.height / 2;
        /// to scale image
        var imx, imy;

        if (this.kind === LISTITEM) {
            //imx = this.xg + (this.width - this.imageres.imw) / 2;
            //imy = this.yg + (this.height - this.imageres.imh) / 2;
            ctx.textBaseline = "middle";
            ofsx = 32 + this.xg;// + this.height;    ###
            var ofsy = this.yg + this.height / 2;
            ctx.textAlign = "start";

        }
        if (this.wrap) {
            ctx.textBaseline = "top";
            wraptext(ctx, this.title, this.xg + this.texth / 5, this.yg + this.texth * 0.5, this.width, this.texth + this.texth / 5)
        } else
            ctx.fillText(this.title, ofsx, ofsy);
        ctx.textAlign = "start";
        //ctx.textBaseline = "top";
        //if (this.valuedraw) ctx.fillText(this.valuename + "=" + todecimal(this.value, this.valuedigits) + " " + this.valueunit, this.xg + this.valuex, this.height / 2 + this.yg + this.valuey)
        this.drawtexts(ctx);
        /// draw image
        if (this.imageres) {
            imx = this.xg + (this.width - this.imageres.imw) / 2;
            imy = this.yg + (this.height - this.imageres.imh) / 2;
            if (this.kind === LISTITEM) {
                imx = this.xg + (this.height - this.imageres.imw) / 2;
                imy = this.yg + (this.height - this.imageres.imh) / 2;
                ctx.drawImage(this.imageres.image, imx, imy);
            } else {
                if (!this.stretch)
                    this.drawimage(this.imageres, this.width, this.height, true)
                else
                    this.fillimage( );
            }
            ;
            //his.drawimage()
        }

        if (this.drawoutline) {
            ctx.strokeStyle = this.linecolor;
            //ctx.lineWidth = 0;
            if (this.corner <= 0) {
                ctx.beginPath();
                ctx.rect(this.xg, this.yg, this.width, this.height);
                ctx.stroke();
            } else {
                drawroundrect(ctx, this.xg, this.yg, this.width, this.height, this.corner, 0);
            }
        }
        //////   after draw  user
        // this.drawhitareas(ctx);
        this.userdraw(ctx);
        ///// draw childs
        this.drawchilds(ctx);
        if (this.tooltip) {
            this.tooltip.visible = (this === overobject);
        }
        if (this.tooltip && this.tooltip.visible) {
            this.drawrect(-1, -1, this.width + 2, this.height + 2, 0);
        }
        ctx.font = this.texth + "px Helvetica";
        if (this.valuedraw) {
            ctx.font = this.texth + "px Helvetica";
            ctx.fillText(this.valuename + "=" + todecimal(this.value, this.valuedigits) + " " + this.valueunit, this.xg + this.valuex, this.height / 2 + this.yg + this.valuey)
        }
        ctx.globalCompositeOperation = "source-over";

        if (this.cliptype > 1)
            ctx.restore();


        if (this.transformable) {
            ctx.restore();
        }
if (this.alpha<1) ctx.globalAlpha = 1;

    }; /// end draw definition
    // 
    // 
    Form.prototype.userdraw = function (ctx) {
        //override this to draw after form 
    }



    Form.prototype.drawchilds = function (ctx) {
        for (var i = 0; i < this.childs.length; i++) {
            this.childs[i].draw(ctx);
        }
    }
    Form.prototype.drawtexts = function (ctx) {
        var i = 0;
        // draw texts
        for (i = 0; i < this.texts.length; i++) {
            ctx.fillText(this.texts[i], 8 + this.xg, (i + 1) * this.texth + this.yg);
        }
    }

    Form.prototype.addparticleform = function (x, y, w, h) {
        var nf = new ParticleForm(0, "", x, y, w, h);
        this.addchild(nf);
        return nf;
    }

///// end form definition;//
//
//
//
//
//
////// drag value
    function Drag(id, title, x, y, width, height, imageres) {


        Form.call(this, id, title, x, y, width, height, imageres);
        this.frm = this.addform(0, "", 0, 0, width, height);
        this.frm.draggable = true;
        this.frm.backout(false);
        var frm = this.frm;
        this.scope = this;
        this.value0 = this.value;


        frm.onmouseup = function () {
            // frm.value=length(0,frm.x,0,frm.y);

            frm.x = 0;
            frm.y = 0;
            this.parent.value0 = this.parent.value;
        }

    }



    Drag.prototype = Object.create(Form.prototype);
    Drag.prototype.constructor = Drag;

    Drag.prototype.draw = function (ctx) {
        Form.prototype.draw.call(this, ctx);  /// any way if must draw childs etc
        var si = 1;
        if (this.frm.x < 0 || this.frm.y > 0)
            si = -1
        this.value = this.value0 + si * step(length(0, this.frm.x, 0, this.frm.y) / 10, this.astep);

        this.drawtext(todecimal(this.value, this.valuedigits), 0, 12, 10, true);

    };

//// particle form

    function ParticleForm(id, title, x, y, w, h) {


        Form.call(this, id, title, x, y, w, h);

        this.ps = jsoncopy(ParticleSystem);

        //psInit(this.ps);
        this.ps.x1 = 0;
        this.ps.y1 = 0;
        this.ps.x2 = w;
        this.ps.y2 = 0;

        this.alpha=0.2;
        this.stopped = false;
    }

/// caution after constructor 
    ParticleForm.prototype = Object.create(Form.prototype);
    ParticleForm.prototype.constructor = ParticleForm;

    ParticleForm.prototype.step = function () {
        /// override eg Step(ps,dt)
    }

    ParticleForm.prototype.draw = function (ctx) {
        Form.prototype.draw.call(this, ctx);  /// any way if must draw childs etc
        if (!this.visible)
            return;
        this.step();
        if (this.alpha<1){
            ctx.globalAlpha = this.alpha;
        }
        psDraw(this.ps, this);
if (this.alpha<1){
            ctx.globalAlpha = 1;
        }


    };

/// end part form




    function Sprite(id, title, x, y, w, h, imageres) {


        Form.call(this, id, title, x, y, w, h, imageres);
        this.kind = "sprite";
        this.spriteres = imageres;
        this.imageres = 0;
        this.pickable = true;
        /*
         this.tx = x;
         this.ty = y;
         this.scx = 1;
         this.scy = 1;
         this.rot = 0;
         this.pivx = 0;
         this.pivy = 0;
         
         */
        this.backout(false, false)
    }

/// caution after constructor 
    Sprite.prototype = Object.create(Form.prototype);
    Sprite.prototype.constructor = Sprite;



    Sprite.prototype.draw = function (ctx) {

        Form.prototype.draw.call(this, ctx);
        this.parent.drawimagetr(this.spriteres, this.tx, this.ty, this.rot, this.scx, this.scy, this.pivx, this.pivy);
    };
    Sprite.prototype.pivot = function (x, y) {

        this.pivx = x;
        this.pivy = y;
    };


    function Form3d(id, title, x, y, width, height) {
        Form.call(this, id, title, x, y, width, height);
        this.hitlist = [];
        this.mixers = [];
        this.kind = "3d";
        this.rho = 10;
        this.theta = 0;//3*Math.PI/2;
        this.phi = 0;//torad(60);

        //this.renderer=renderer;
        this.scene;
        this.camera;
        this.light;
        this.mouse3d = {
            x: -1,
            y: -1
        };
        // start 3d def
        this.camera = new THREE.PerspectiveCamera(33, window.innerWidth / window.innerHeight, 0.01, 40);
        this.camera.position.set(0, 7, 7);
        this.camera.lookAt(0, 0, 0);
        this.scene = new THREE.Scene();
        this.mixer = undefined; // new THREE.AnimationMixer( this.scene );
        this.scene.background = new THREE.Color(0x000000);
        /////scene.fog = new THREE.Fog( 0xa0a0a0, 200, 10000 );
        this.grid = new THREE.GridHelper(10, 10, 0xff00ff, 0xff0000);
        this.scene.add(this.grid);
        raycaster = new THREE.Raycaster();
        var mat = new THREE.MeshLambertMaterial({
            color: 0xffff00
        });
        //var box3 = box(1,1,1,mat);
        //this.scene.add(box3);
        //this.hitlist.push(box3);
        //var light = new THREE.PointLight( 0xff0000, 1, 100 );
        //light.position.set( 2, 3, 5  );
        //this.scene.add( light );
        this.p0 = this.scene.position.clone(); //this.scene.position.clone();
        this.r0 = this.scene.rotation.clone();
        this.sc0 = this.scene.scale.clone();
        // end 3d def
        this.controls = new THREE.OrbitControls(this.camera);
        var controls = this.controls;
        //controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
        controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
        controls.dampingFactor = 0.25;
        controls.screenSpacePanning = false;
        controls.minDistance = 0.1;
        controls.maxDistance = 50;
        //controls.maxPolarAngle =  Math.PI  ;


        controls.enablePan = false;
        controls.enabled = false;
    }
    Form3d.prototype = Object.create(Form.prototype);
    Form3d.prototype.constructor = Form3d;
    Form3d.prototype.onwheel = function (e) {
        this.wheeldelta = -0.1 * sign(e.deltaY);
        edeltay = e.deltaY;
        //var nsc=this.sc0.x+((mousey-mousey0)/1280*wheel/100);
        //var nsc=this.sc0.x+e.deltaY/1000;
        //var nsc=this.sc0.x+this.wheeldelta ;
        var nsc = this.scene.scale.x + this.wheeldelta;
        if (nsc < 0.1) {
            nsc = 0.1;
            this.wheeldelta = -this.sc0.x + 0.1;
        }
        //  this.scene.scale.x = nsc;
        //  this.scene.scale.y = nsc;
        //   this.scene.scale.z = nsc;

        this.rho -= this.wheeldelta * 2;
        if (this.rho < 1)
            this.rho = 1;
    }; //

    Form3d.prototype.setscale = function (nsc) {

        this.scene.scale.x = nsc;
        this.scene.scale.y = nsc;
        this.scene.scale.z = nsc;
        this.sc0.copy(this.scene.scale);
    }; //

    Form3d.prototype.draw = function (ctx) {
        //Form.prototype.draw.call(this, ctx);  /// any way if must draw childs etc
        //or 
        if (!this.visible) {
            return;
        }
        this.texts = [];

        this.setpost();
        if (control3d && mousemove && pressedobject === this) {
            // drag view 

            // this.scene.rotation.y = this.r0.y + ( (mousex - mousex0) / 314);
            //  this.scene.rotation.x = this.r0.x + ((mousey - mousey0) / 314);
            //this.scene.position.x = this.p0.x + ((mousex - mousex0) / 150);
            //this.scene.position.y = this.p0.y - ((mousey - mousey0) / 150);
            this.scene.rotation.z += mousedx / 340
            //this.theta-=mousedx/340;//(mousex - mousex0) / 314
            this.phi += mousedy / 160;//(mousex - mousex0) / 314
            if (this.phi > Math.PI / 2)
                this.phi = Math.PI / 2 - 0.0001;
            if (this.phi < -Math.PI / 2)
                this.phi = -Math.PI / 2 + 0.0001;
        }


        /// set camera pos ;
        //
        //
        // var x=this.rho*cos(this.phi)*cos(this.theta);
        // var y=this.rho*cos(this.phi)*sin(this.theta);
        //var z=this.rho*sin(this.phi);
        var z = this.rho * cos(this.phi) * cos(this.theta);
        var x = this.rho * cos(this.phi) * sin(this.theta);
        var y = this.rho * sin(this.phi);


//canvas3d.width=canvas.width;
//canvas3d.height=canvas.height;

        this.camera.position.set(x, y, z);
        this.camera.lookAt(0, 0, 0);
        // *** not set mobile resize failure //renderer.setPixelRatio(window.devicePixelRatio);
        this.camera.aspect = this.width / this.height;
        this.camera.updateProjectionMatrix();
        //renderw=this.width;
        //renderh=this.height;
        this.mouse3d.x = ((mousex - this.xg) / this.width) * 2 - 1;
        this.mouse3d.y = -((mousey - this.yg) / this.height) * 2 + 1;
        renderer.setViewport(0, 0, this.width, this.height);
         
        //renderer.setSize(logw, logh);
         renderer.setSize(canvas.width, canvas.height);
        //renderer.setSize(this.width, this.height);
         
        renderer.setPixelRatio(window.devicePixelRatio);
        //renderer.setSize(this.width, this.height);//
        //animate3d(this.dt, this.scene, this.camera, this.mouse3d, this.hitlist, this.mixer, this.mixers);
        animate3d(this);
        ctx.drawImage(canvas3d, this.xg, this.yg, this.width, this.height);
        ///old was ..,xg ,yg ,width ,height
        this.drawchilds(ctx);
        this.drawtexts(ctx);
        this.userdraw(ctx);
        this.drawtext(canvas.width+ " "+ canvas.height,100,100)
    };   

    function App(id, title) {
        Form.call(this, id, title, 0, 0, 1024, 768);
    }
    App.prototype = Object.create(Form.prototype);
    App.prototype.constructor = App;
    App.prototype.create = function () {}
    App.prototype.init = function () {}
    App.prototype.update = function () {}
    App.prototype.render = function () {}

    function Multistate(id, title, x, y, width, height, imageres) {
        Form.call(this, id, title, x, y, width, height, imageres);
        this.kind = MULTISTATE;
    }
    Multistate.prototype = Object.create(Form.prototype);
    Multistate.prototype.constructor = Multistate;
    Multistate.prototype.onclick = function () {
        // if (overobject!==this) return;
        this.state += 1;

        if (this.state > this.childs.length - 1)
            this.state = 0;
    };
    Multistate.prototype.draw = function (ctx) {
        var v = this.getparentpos();
        this.xg = v.x + 1 * (this === pressedobject);
        this.yg = v.y + 1 * (this === pressedobject);
        //ctx.fillStyle = this.backcolor;
        //ctx.fillRect(this.xg, this.yg, this.width, this.height);
        ctx.fillStyle = this.textcolor;
        ctx.fillStyle = rgb(0, 0, 0);
        ctx.font = this.texth + "px Helvetica";
        //ctx.textAlign = "center";
        //ctx.textBaseline = "top";
        var str = this.title;
        var imres;
        var img;
        var wi0 = 0;
        var ch = this.childs;
        if (ch) {
            str = ch[this.state].title;
            imres = ch[this.state].imageres;
            if (imres)
                img = imres.image;
            if (img)
                wi0 = img.width;
        }
        var ofsx = this.xg + wi0; // + ch[this.state].width / 2 + 40 * (imres);
        var ofsy = this.yg;
        ctx.fillText(str, ofsx, ofsy);
        //ctx.textAlign = "start";
        if (imres) {
            ctx.drawImage(imres.image, this.xg, this.yg);
        }
    };
    Multistate.prototype.addstate = function (id, title, imageres) {
        var nw = new Form(id, title, 1, 1, 32, 32, imageres);
        nw.kind = BUTTON;
        nw.drawbackground = false;
        nw.drawoutline = false;
        nw.pickable = false;
        this.childs.push(nw);
        this.states = this.childs.length;
        return nw;
    };


    //------------------------------------------------------------------
    function Clockwin(id, title, x, y, width, height, imageres) {
        Form.call(this, id, "", x, y, 48 * 6, 48, imageres);

        this.stept = 0.1;
        this.backcolor = rgb(243, 223, 223);
        this.drawbackground = false;
        this.drawoutline = false;
        //this.draggable=true;
        var d0 = 0;
        this.ms = this.addmultistate(0, "", 0, d0, 48, 48);
        this.ms.addstate(1, "", clock1);
        this.ms.addstate(2, "", clock2);
        var par = this.parent;
        var mu = this.ms;
        this.ms.onclick = function () {

            var par = this.parent;


            Multistate.prototype.onclick.call(this);
            if (mu.state === 0)
                par.stopped = true;
            if (mu.state === 1)
                par.stopped = false;

            this.parent.onmessage("clock", mu.state);
        };
        var msl = this;
        this.rst = this.addbutton(0, "", 48, d0, 48, 48, clock3);
        this.rst.drawbackground = false;
        this.rst.drawoutline = false;
        this.rst.onclick = function () {
            this.parent.t = 0;

            this.parent.onmessage("reset");
        };
        this.ff1 = this.addbutton(0, "", 2 * 48, d0, 48, 48, clock4);
        this.ff1.drawbackground = false;
        this.ff1.drawoutline = false;
        this.ff1.onmouseup = function () {
            msl.clockstop();

        };
        this.ff1.onmousedown = function () {
            msl.clockstart();
            this.parent.onmessage("right");
        };
        this.ff2 = this.addbutton(0, "", 3 * 48, d0, 48, 48, clock5);
        this.ff2.drawbackground = false;
        this.ff2.drawoutline = false;
        this.ff2.onmouseup = function () {
            msl.clockstop(this);
            this.parent.timescale = Math.abs(this.parent.timescale);
        };
        this.ff2.onmousedown = function () {
            this.parent.timescale = -Math.abs(this.parent.timescale);
            msl.clockstart(this);
            this.parent.onmessage("left");

        };
        this.ff3 = this.addbutton(0, "", 4 * 48, d0, 48, 48, clock6);
        this.ff3.drawbackground = false;
        this.ff3.drawoutline = false;
        this.ff3.onmouseup = function () {
            this.parent.t += this.parent.stept * this.parent.timescale;
            this.parent.onmessage("next");
        };
        this.ff3.onmousedown = function () {
            msl.clockstop(this);

        };
        this.ff4 = this.addbutton(0, "", 5 * 48, d0, 48, 48, clock7);
        this.ff4.drawbackground = false;
        this.ff4.drawoutline = false;
        this.ff4.onmouseup = function () {

            this.parent.t -= this.parent.stept * this.parent.timescale;
            //  if (this.parent.t < 0)
            //      this.parent.t = 0.0;

            this.parent.onmessage("previous");
        };
        this.ff4.onmousedown = function () {
            msl.clockstop(this);
        };
    }
    Clockwin.prototype = Object.create(Form.prototype);
    Clockwin.prototype.constructor = Clockwin;
    Clockwin.prototype.draw = function (ctx) {
        // this.drawbackground = true;
        ctx.lineWidth = this.lw;
        //ctx.lineStyle=rgb(0,0,0);
        var v = this.getparentpos();
        //drawroundrect(ctx, v.x, v.y, this.width, this.height, 4, 0, "black", this.backcolor);
        Form.prototype.draw.call(this, ctx);
        this.value = this.t;
    };
    Clockwin.prototype.reset = function () {
        this.stopped = true;
        this.ms.state = 0;
        this.t = 0;
    }
    Clockwin.prototype.clockstop = function () {
        this.stopped = true;
        this.ms.state = 0;
    }

    Clockwin.prototype.clockstart = function () {
        this.stopped = false;
        this.ms.state = 1;
    }

    /// class         ---------------------------- S c e n e     -----------------------------
    function Scene() {
        Form.call(this, "idscene", "title", 0, 0, 1024, 768);
        ////  collection of stuff only with parent===0;
    } // end scene def
    Scene.prototype = Object.create(Form.prototype);
    Scene.prototype.constructor = Scene;
    Scene.prototype.draw = function (ctx) {
        var i = 0;
        for (i = 0; i < this.childs.length; i++) {
            this.childs[i].draw(ctx);
        }
        if (draggedobject) {
            /// todo stop timer             
            if (draggedobject.dropable)
                draggedobject.draw(ctx);
        }
    };
    Scene.prototype.getclicks = function () {
        var i = 0;
        for (i = 0; i < this.childs.length; i++) {
            this.childs[i].checkmouse(mousex, mousey);
        }
        for (i = 0; i < sm.childs.length; i++) {
            sm.childs[i].checkmouse(mousex, mousey);
        }
    };
    Scene.prototype.onevent = function (e, type) {
        var i = 0;
        var ob = undefined;
        overobject = undefined;
        var v = undefined;
        var oldoverobject = undefined;
        //draggedobject=undefined;
        clickedobject = undefined;
        clicks = [];
        this.getclicks();
        ob = getlastchild();
        overover = ob;
        overobject2 = getpreviouschild();
        if (type === MOUSEWHEEL && overover) {
            overover.onwheel(e);
        }
        if (type === MOUSEDOWN) {

            pressedobject = undefined;
            if (ob !== undefined) {

                control3d = false;
                if (ob.kind === "3d") {
                    ob.p0.copy(ob.scene.position);
                    ob.r0.copy(ob.scene.rotation);
                    ob.sc0.copy(ob.scene.scale);
                    control3d = true;
                }
                if (ob.kind === LISTITEM) {

                    ob.pressed = 1;
                }
                ob.onmousedown();
                if (ob.kind === BUTTON || ob.kind === PUSHBUTTON)
                    ob.pressed = 1; //modify dx for buttons
                if (ob.kind === SCROLLBAR) {

                    ob.fixscrollbar(ob);
                }
                pressedobject = ob; //// ok 
                overobject = ob;
                if (ob.draggable)
                    draggedobject = ob;
                dragx = ob.x;
                dragy = ob.y;
                sm.ondragstart(ob);
                ob.ondragstart(ob);
                if (ob.parent)
                    ob.parent.ondragstart(ob);

                ////////  if is list toggle  
            } ///// having clicked
            //---

            hidedown(); /// *** 

        } //////// end mouse down
        if (type === MOUSEMOVE) {
            oldoverobject = overobject;
            overobject = ob;
            if (ob) {
                if (oldoverobject !== overobject) {
                    ob.onenter();
                    if (oldoverobject)
                        oldoverobject.onleave();
                }


                changecursor(ob.cursor);
            } else
                changecursor("default");
            if (pressedobject) {
                pressedobject.onmousemove();
                // not only sb 
                //    if (pressedobject.kind === SCROLLBAR) {
                v = pressedobject.getparentpos();
                pressedobject.clickx = mousex - v.x;
                pressedobject.clicky = mousey - v.y;
                pressedobject.fixscrollbar(pressedobject);
                ///  }
            }
            if (overobject) {
                overobject.onmousemove();
            }



            if (draggedobject !== undefined && mousest === 2) {
                ///// update drag position
                draggedobject.x = dragx + mousex - mousex0;
                draggedobject.y = dragy + mousey - mousey0;
                /// are we over another object ?
                if (draggedobject.limited) {
                    draggedobject.dolimit()
                }
            }
        } ////end mouse move 
        if (type === MOUSEUP) {
            sm.onmouseup();
            control3d = false;
            overobject = ob;
            if (pressedobject) {
                pressedobject.onmouseup();
                if (pressedobject.kind === "3d")
                    control3d = true;

            }

            if (ob === pressedobject)
                clickedobject = ob;
            if (clickedobject) {

                if (ob.kind === LISTITEM) {

                    ob.checked = !ob.checked;
                    ob.parent.selecteditem = ob; ////in any case 
                    ob.parent.listpressed(ob);
                    ob.pressed = 1;
                    ob.parent.setselindex(ob);

                    ob.parent.onclick(); ////// list item click notify parent
                    /// handle auto dropdown list;
                    if (ob.parent.parent.kind === "dropdown") {

                        //ob.parent.visible = false;
                        ob.parent.parent.childs[0].title = ob.title;

                        ob.parent.parent.onclick();
                    }

                }
                clickedobject.onclick(); //// 
                if (clickedobject.parent) {
                    clickedobject.parent.onchildclicked(clickedobject)
                }

                switch (clickedobject.command) {
                    case 0:
                        break;
                    case SCFIRST:
                        sm.gotoscene(0);
                        break;
                    case SCNEXT:
                        sm.gonext();
                        break;
                    case SCPREVIOUS:
                        sm.goprevious();
                        break;
                    case SCANY:
                        sm.gotoscene(clickedobject.commandlist[0]);
                        break;
                    case "any":
                        sm.gotoscene(clickedobject.commandlist[0]);
                        break;
                    case FSON:
                        fullscreenon();
                        break;
                    case FSOFF:
                        fullscreenoff();
                        break;
                } /// end switch
            } /// end clicked 
            /// if mousest=3 dragged dropped 
            //////// handle drop
            if (draggedobject && overobject2) {
                sm.ondrop(draggedobject, overobject2);
                draggedobject.ondrop(draggedobject, overobject2);
                overobject2.ondrop(draggedobject, overobject2);
                if (overobject2.parent) {
                    overobject2.parent.ondrop(draggedobject, overobject2)
                }
            }
            ;

            draggedobject = undefined;
        } /// end mouseup
        //////useless  
        for (i = this.childs.length - 1; i > -1; i--) {
            this.childs[i].onevent(e, type);
        }
        for (i = sm.childs.length - 1; i > -1; i--) {
            sm.childs[i].onevent(e, type);
        }
    };
    Scene.prototype.userevent = function (e, type) {
        ///    override if have special message
        //// do nothing user defines his event 
        //all scene events handled by childs now user

        // if (type === MOUSEUP) {
        //        unpress(pressedobject);
        //      pressedobject = 0;
        //   }
    };
    /// class         ---------------------------- S c e n e  M a n a g e r    -----------------------------   
    function SceneManager() {
        fpst0 = 0; //Date.now();
        ///var that=this;

        Form.call(this, "idSM", "title", 0, 0, logw, logh);
        this.messages = [];
        //this.addbuttoncommand(SCFIRST, [], 0, " menu", 0, 0, 128, 64, iconhome);
        this.name = "SceneManager";
        this.scenes = []; ////  collection of scenes;
        this.current = 0; //first scene
        this.currentscene = 0; /// noscene
        this.images = [];
        this.dwin;

        check1 = this.createimage("images/check1.png");
        check2 = this.createimage("images/check2.png");
        radio1 = this.createimage("images/radio1.png");
        radio2 = this.createimage("images/radio2.png");
        iconhome = this.createimage("images/iconhome.png");

        iconinfo = this.createimage("images/iconinfo.png");

        clock1 = this.createimage("images/clock1.png");
        clock2 = this.createimage("images/clock2.png");
        clock3 = this.createimage("images/clock3.png");
        clock4 = this.createimage("images/clock4.png");
        clock5 = this.createimage("images/clock5.png");
        clock6 = this.createimage("images/clock6.png");
        clock7 = this.createimage("images/clock7.png");


        iconabout = this.createimage("images/aboutbtn.png");
        iconhelp = this.createimage("images/helpbtn.png");
        iconclose = this.createimage("images/closebtn.png");
        icondropdown = this.createimage("images/dropdown.png");
    } // end scene Manager def
    SceneManager.prototype = Object.create(Form.prototype);
    SceneManager.prototype.constructor = SceneManager;
    SceneManager.prototype.adddebug = function () {
        this.dwin = this.addform(0, "", 0, 0, 256 + 1000 * (debug === false), 512);
        this.dwin.drawbackground = false;
        //this.dwin.textcolor = "grey";
        this.dwin.draggable = true;
        this.dwin.drawoutline = true;
    }

    SceneManager.prototype.setscene = function () {
        this.currentscene = this.scenes[this.current]; //// always have scene
        ///this.onresize();
    };
    SceneManager.prototype.createscene = function () {
        gok = true;
        var ns = new Scene();
        this.scenes.push(ns);
        this.setscene();
        return ns;
    };
    SceneManager.prototype.addscene = function () {
        var ns = new Scene();
        this.scenes.push(ns);
        //this.childs.push(awin);
        //this.setscene();
        return ns;
    };
    SceneManager.prototype.adddialog = function (w, h, imres, scenetogo) {
        var ns = new Scene();
        this.scenes.push(ns);
        var nf = ns.addform(0, "", 0, 0, w, h, imres);

        var cb = nf.addbutton(0, "", w - 48, 4, 48, 48, iconclose);
        cb.onclick = function () {
            sm.gotoscene(scenetogo);
        }
        return ns;
    };
    SceneManager.prototype.createimage = function (fn) {
        var ns = new ImageResource(fn);
        this.images.push(ns);
        return ns;
    };
    SceneManager.prototype.scenexists = function (n) {
        var le = this.scenes.length;
        if (le < 1)
            return false;
        return (n > -1 && n < le);
    };
    SceneManager.prototype.gotoscene = function (n) {
        this.current = 0;
        if (this.scenes.length < 1) {
            alert("NO SCENE NO APP");
            return;
        }
        if (n > -1 && n < this.scenes.length) {
            this.current = n;
        }
        //this.currentscene = this.scenes[this.current]; //// always have scene
        this.setscene();
    };
    SceneManager.prototype.gonext = function () {
        this.current++;
        if (this.current >= this.scenes.length) {
            this.current = 0;
        }
        //this.currentscene = this.scenes[this.current]; //// always have scene
        this.setscene();
    };
    SceneManager.prototype.goprevious = function () {
        this.current--;
        if (this.current < 0) {
            this.current = this.scenes.length - 1;
        }
        this.setscene();
        //this.currentscene = this.scenes[this.current]; //// always have scene
    };
    SceneManager.prototype.draw = function (ctx) {
        // this.messages=[]; 
        this.dwin.visible = debug;
        frames++;
        fpst = time1; //Date.now();
        if (fpst - fpst0 > 1) {
            fps = frames;
            fpst0 = fpst;
            frames = 0;

        }
        // ctx2.fillStyle = rgb(0,0,255);// this.backcolor;
        //ctx2.fillRect(0, 0, canvaswidth, canvasheight);
        ctx.fillStyle = this.backcolor;
        //if (this.drawbackground) ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.save();
        viewtr.reset();
        //gsc=2.5;
        viewtr.translate(0, 0);
        viewtr.scale(gsc, gsc);
        settransform(ctx, viewtr);
        // set canvas transform
        //canvas.style.transform="scale('+gsc+','+gsc+')";
        //setelementpos(canvas,0,0);
        if (this.scenes.length > 0) {
            this.currentscene.draw(ctx);
            // ctx.fillText(info, 0, 4);     
        }
        var i = 0;
        for (i = this.childs.length - 1; i > -1; i--) {
            this.childs[i].draw(ctx);
        }

        if (debug) {

            this.dwin.texts = [];
            this.dwin.addtext("fps", fps);
            this.dwin.addtext("mousest", mousest);
            this.dwin.addtext("over", obtitle(overobject));
            var ovst = "overect";
            if (overobject) {
                ovst = concat(toint(overobject.x), toint(overobject.y), toint(overobject.width), toint(overobject.height))
            }
            this.dwin.addtext("overect", ovst);

            this.dwin.addtext("over 2", obtitle(overobject2));

            this.dwin.addtext("pressed", obtitle(pressedobject));
            this.dwin.addtext("dragged", obtitle(draggedobject));
            this.dwin.addtext("mouse x,y", toint(mousex), ",", toint(mousey));
            this.dwin.addtext("mouse dx,dy", toint(mousex - mousex0), ",", toint(mousey - mousey0));
            this.dwin.addtext("w pix ratio", window.devicePixelRatio);
            this.dwin.addtext("canvas", canvas.width, canvas.height);


            this.dwin.addtext("wiw wih ", window.innerWidth, window.innerHeight);


            this.dwin.addtext("outer ", window.outerWidth, window.outerHeight);


            this.dwin.addtext("screen", window.screen.width, window.screen.height);


            this.dwin.addtext("avail", window.screen.availWidth, window.screen.availHeight);
            for (i = 0; i < debugs.length; i++) {
                this.dwin.addtext(debugs[i]);
            }
            this.dwin.addtext("edeltay", edeltay);

            //this.dwin.draw(ctx);
            debugs = [];

        }/// end debug
        ctx.restore();
    };
    SceneManager.prototype.onevent = function (e, type) {
        // hope all info in global vars

        // this.currentscene.userevent(e, type); 
        //   if (type === MOUSEUP) {
        //     unpress(pressedobject);
        //        pressedobject = 0;
        //   } 

        this.currentscene.onevent(e, type);
        /// already all childs notified but if 
        ///************* caution 
        this.currentscene.userevent(e, type);
        if (type === MOUSEUP) {
            unpress(pressedobject);
            pressedobject = 0;
        }




        //

    };
   Form.prototype.addfs = function (x, y, width, height) {
        var tb = this.addbutton(0,"",x, y, width, height);
        this.addchild(tb);
        tb.backout(false,true);
        tb.linecolor=rgb(205,205,205);
        tb.onclick=function(){
            fullscreen();
            onresize();
        }
        
        
        return tb;


    };

    Form.prototype.addtoolbar = function (id, title, x, y, width, height, cols, rows, im1, im2, imw, imh) {
        var tb = new Toolbar(id, title, x, y, width, height, cols, rows, im1, im2, imw, imh);
        this.addchild(tb);
        return tb;


    };

    function Toolbar(id, title, x, y, width, height, cols, rows, im1, im2) {


        Form.call(this, id, title, x, y, width, height, im1);
        this.imw = width / cols;
        this.imh = height / rows;
        this.mask = this.addform(0, "", 0, 0, this.imw, this.imh, im2);
        this.drawbackground = false;
        this.mask.pickable = false;
        this.mask.drawbackground = false;
        this.cols = cols;
        this.rows = rows;

        this.im1 = im1;
        this.im2 = im2;
        this.col = 0;
        this.row = 0;
    }

/// caution after constructor 
    Toolbar.prototype = Object.create(Form.prototype);
    Toolbar.prototype.constructor = Toolbar;

    Toolbar.prototype.drawmask = function (ctx) {
        ///override this to your own draw
        // make mask invisible



    };

    Toolbar.prototype.draw = function (ctx) {

        Form.prototype.draw.call(this, ctx);  /// any way if must draw childs etc
        //or  
        // compute x,y    
        // var x=this.xg+this.col*this.imw;
        //var y=this.yg+this.row*this.imh;

        this.mask.x = this.col * this.imw;
        this.mask.y = this.row * this.imh;

        this.drawmask(ctx);



    };




    Toolbar.prototype.onmousedown = function () {
        this.col = toint(this.clickx / this.imw);
        this.row = toint(this.clicky / this.imh);
        /// check 	 
    };
    Toolbar.prototype.onmousemove = function () {

    };
    Toolbar.prototype.onmouseup = function () {};
    Toolbar.prototype.onclick = function () {
        //this.col=toint(this.clickx/this.imw);
        // this.row=toint(this.clicky/this.imh);
        /// check 

    };

    function fullscreenon(element) {
    fullscreen();
        onresize();
    }

    function fullscreenoff() {
    fullscreen();

        onresize();
    }

    ////----------------------------------end drawing functions -------------------
    ///------------------------------------------    app start 

    ///----------------------------------------------------------------------------    
    ///--------------------------------init 3d
    function init3d() {
        if (!Detector.webgl)
            Detector.addGetWebGLMessage();
        ///initmaterials();
        canvas3d = getelement("canvas3d");
        //canvas3d.width = logw;
        //canvas3d.height = logh;
        renderer = new THREE.WebGLRenderer({
            canvas: canvas3d,
            antialias: true
        });
       // renderer.setSize(logw, logh);
        //renderer.setSize(canvas3d.width, canvas3d.height);

        renderer.shadowMap.enabled = true;
    }

    function animate3d(frm) {
        var dt = frm.dt;
        var ascene = frm.scene;
        var acamera = frm.camera;
        var amouse = frm.mouse3d;
        var ahitlist = frm.hitlist;
        var amixer = frm.mixer;
        var amixers = frm.mixers;
        raycaster.setFromCamera(amouse, acamera);
        var intersects = raycaster.intersectObjects(ahitlist);

        if (intersects.length > 0) {

            if (INTERSECTED !== intersects[0].object) {
                if (INTERSECTED)
                    INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
                INTERSECTED = intersects[0].object;
                INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
                INTERSECTED.material.emissive.setHex(0x555555);
            }
        } else {
            if (INTERSECTED)
                INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
            INTERSECTED = null;
        }
        renderer.render(ascene, acamera);
        //stats.update();
        if (frm.controls)
            frm.controls.update;

        if (amixer)
            amixer.update(dt);
    }

    function render3d() {}
    var w = window;
    var requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
    //////////////----------create sm    -----------------------------
    var sm = new SceneManager();

    function getmanager() {
        return sm;
    }

    function main() {

        time1 = Date.now() / 1000;
        mousedx = mousex - pmousex;
        mousedy = mousey - pmousey;
        timedelta = (time1 - time0);//*(sm.stopped===false);// * timescale;
        time = time + (timedelta);
        if (timedelta > interval) {
            //time0 = time1;
            time0 = time1 - (timedelta % interval)
            sm.draw(ctx); //////  render();
            sm.messages = [];
        }
        pmousex = mousex;
        pmousey = mousey;
        // Request to do this again ASAP
        requestAnimationFrame(main);
    }


    function start() {
        time0 = Date.now() / 1000;
        time = 0;
        initialize();
        if (can3d)
            init3d();
        onresize();
          main();
    }

    return {
        start: start,
        getmanager: getmanager,
        renderer: renderer,
        Form: Form,
        Form3d: Form3d,
        Clockwin: Clockwin,
        Multistate: Multistate,
        Toolbar: Toolbar
    };
}; /// end frame work
// notes renderer set pixelratio  renderer.setPixelRatio(window.devicePixelRatio);e