Exemple #1
0
        static WebGLTexture loadTexture(WebGLRenderingContext gl, string url, Action callback)
        {
            //gl.enable(gl.TEXTURE_2D);

            var texture = gl.createTexture();
            var image   = new IHTMLImage();

            Console.WriteLine("loading: " + url);
            image.src = url;

            image.InvokeOnComplete(
                delegate
            {
                Console.WriteLine("loaded: " + url);

                gl.bindTexture(gl.TEXTURE_2D, texture);
                gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, (int)gl.LINEAR);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, (int)gl.LINEAR);
                gl.bindTexture(gl.TEXTURE_2D, null);

                callback();
            }
                );

            return(texture);
        }
Exemple #2
0
        public UltraApplication(IHTMLElement e)
        {
            var Title = new IHTMLDiv
            {
            };

            new Browsers
            {
            }.Container.AttachTo(Title);

            new HTML.Images.FromBase64.twitter_small().AttachToDocument();
            new HTML.Images.FromBase64._troll__by_GirlFlash().AttachToDocument();

            var TitleLogo = new IHTMLImage("assets/ScriptCoreLib/jsc.png");
            var TitleText = new IHTMLSpan("UltraApplication");

            TitleText.style.fontFamily    = ScriptCoreLib.JavaScript.DOM.IStyle.FontFamilyEnum.Verdana;
            TitleText.style.paddingLeft   = "2em";
            TitleText.style.fontSize      = "xx-large";
            TitleLogo.style.verticalAlign = "middle";


            Title.appendChild(TitleLogo);
            Title.appendChild(TitleText);

            Title.style.height = "128px";

            Title.AttachToDocument();
            Title.FadeIn(2500, 1000,
                         delegate
            {
                1500.AtDelay(ContinueBuildingApplication);
            }
                         );
        }
            public EnemyUnit(EnemyInfo i)
            {
                Info    = i;
                Control = (IHTMLImage)Info.Image.Clone();

                Visible = false;
            }
Exemple #4
0
        private static void CreateRotor2(double _angle, IHTMLElement _container, IHTMLImage img, Timer timer)
        {
            var a = img;



            //a.style.width = "400px";
            //a.style.height = "300px";



            var angle = _angle;

            ApplyRotation(a, angle, 2);

            timer.Tick +=
                delegate
            {
                angle -= 0.25 * 8;
                ApplyRotation(a, angle, 2);


                a.style.SetLocation((a.clientWidth - a.offsetWidth) / 2, (a.clientHeight - a.offsetHeight) / 2);
            };


            a.AttachTo(_container);
        }
Exemple #5
0
        private static void Spawn(double Rotation)
        {
            var z = new IHTMLDiv().AttachToDocument();
            var r = new IHTMLDiv().AttachTo(z);

            z.style.position = IStyle.PositionEnum.relative;
            var i = new IHTMLImage(Assets.Path + "/Preview.png").AttachTo(r);

            var b = new IHTMLButton().AttachTo(r);

            b.innerText = "hello world";
            b.style.SetLocation(20, 20);
            z.style.SetLocation(100, 100);


            var costheta = Math.Cos(Rotation);
            var sintheta = Math.Sin(Rotation);

            var M11 = costheta;
            var M12 = -sintheta;
            var M21 = sintheta;
            var M22 = costheta;


            z.style.SetMatrixTransform(
                M11, M21,
                M12, M22,

                0, 0
                );
        }
		public UltraApplication(IHTMLElement e)
		{
			var Title = new IHTMLDiv
				{
					innerHTML = @"
<img border='0' src='http://www.w3schools.com/images/compatible_ie.gif' width='31' height='30' alt='Internet Explorer' title='Internet Explorer' />
<img border='0' src='http://www.w3schools.com/images/compatible_firefox.gif' width='31' height='30' alt='Firefox' title='Firefox' />
<img border='0' src='http://www.w3schools.com/images/compatible_opera.gif' width='28' height='30' alt='Opera' title='Opera' />
<img border='0' src='http://www.w3schools.com/images/compatible_chrome.gif' width='31' height='30' alt='Google Chrome' title='Google Chrome' />
<img border='0' src='http://www.w3schools.com/images/compatible_safari.gif' width='28' height='30' alt='Safari' title='Safari' />
"
				};


			var TitleLogo = new IHTMLImage("assets/ScriptCoreLib/jsc.png");
			var TitleText = new IHTMLSpan("UltraApplication");
			TitleText.style.fontFamily = ScriptCoreLib.JavaScript.DOM.IStyle.FontFamilyEnum.Verdana;
			TitleText.style.paddingLeft = "2em";
			TitleText.style.fontSize = "xx-large";
			TitleLogo.style.verticalAlign = "middle";


			Title.appendChild(TitleLogo);
			Title.appendChild(TitleText);

			Title.style.height = "128px";

			Title.AttachToDocument();
			Title.FadeIn(2500, 1000,
				delegate
				{
					1500.AtDelay(ContinueBuildingApplication);
				}
			);
		}
Exemple #7
0
    public static TaskAwaiter <IHTMLImage> GetAwaiter(this IHTMLImage i)
    {
        var y = new TaskCompletionSource <IHTMLImage>();

        i.InvokeOnComplete(y.SetResult);
        return(y.Task.GetAwaiter());
    }
            public ScoreBoard(ImageResources gfx)
            {
                Life1 = gfx.biggun.Clone();
                Life2 = gfx.biggun.Clone();
                Life3 = gfx.biggun.Clone();

                score_label.style.color = Color.White;
                lives_label.style.color = Color.White;

                score_value.style.color = Color.Green;

                var left = new IHTMLDiv(score_label, score_value);

                left.style.Float = IStyle.FloatEnum.left;

                lives_value.appendChild(
                    Life1,
                    Life2,
                    Life3
                    );

                score_value.style.paddingLeft = "1em";
                Life1.style.paddingLeft       = "1em";
                Life2.style.paddingLeft       = "1em";
                Life3.style.paddingLeft       = "1em";

                var right = new IHTMLDiv(lives_label, lives_value);

                right.style.Float = IStyle.FloatEnum.right;

                Control.style.fontSize = "22px";
                Control.appendChild(left, right);
            }
		private static void Spawn(double Rotation)
		{

			var z = new IHTMLDiv().AttachToDocument();
			var r = new IHTMLDiv().AttachTo(z);
			z.style.position = IStyle.PositionEnum.relative;
			var i = new IHTMLImage(Assets.Path + "/Preview.png").AttachTo(r);

			var b = new IHTMLButton().AttachTo(r);

			b.innerText = "hello world";
			b.style.SetLocation(20, 20);
			z.style.SetLocation(100, 100);


			var costheta = Math.Cos(Rotation);
			var sintheta = Math.Sin(Rotation);

			var M11 = costheta;
			var M12 = -sintheta;
			var M21 = sintheta;
			var M22 = costheta;


			z.style.SetMatrixTransform(
					M11, M21,
						M12, M22,

					0, 0
			);
		}
        public __PictureBox()
        {
            // http://stackoverflow.com/questions/18389224/how-to-style-html5-range-input-to-have-different-color-before-and-after-slider

            this.HTMLTarget = new IHTMLDiv
            {

            };



            this.InternalElement = new IHTMLImage
            {
            }.AttachTo(this.HTMLTarget);


            // keep only borders
            this.InternalElement.style.height = "100%";
            this.InternalElement.style.width = "100%";






            this.Size = new global::System.Drawing.Size(200, 200);
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // what about gif, svg, canvas and webgl?
            Native.document.icon = new fullbox();

            new IHTMLButton {
                "?"
            }.AttachToDocument().WhenClicked(
                button =>
            {
                var div = new IHTMLDiv {
                    "?"
                };

                // 7x20
                div.style.color  = "red";
                div.style.width  = "16px";
                div.style.height = "16px";

                IHTMLImage i = div;

                var c = new CanvasRenderingContext2D(16, 16);

                c.drawImage(i, 0, 0, 16, 16);


                Native.css.style.cursorImage = i;

                // Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
                // why wont this work?
                Native.document.icon = c.canvas.toDataURL();
            }
                );
        }
Exemple #12
0
        public IHTMLImage ToImage(string path)
        {
            IHTMLImage i = GetImagePath(path);

            i.alt = Description;

            return(i);
        }
Exemple #13
0
        public THREE_OBJAsset(IHTMLImage i, string uri)
        {
            new Action(
                async delegate
            {
                await i;

                var texture = new THREE.Texture(
                    //new HTML.Images.FromAssets.ash_uvgrid01()
                    //new HTML.Images.FromAssets.texture_palm()
                    i
                    );
                texture.needsUpdate = true;

                // model


                var loader = new THREE.OBJLoader();
                loader.load(
                    //'obj/male02/male02.obj',
                    //"assets/WebGLOBJExperiment/male02.obj",
                    //"assets/WebGLOBJExperiment/palm.obj",
                    uri,

                    new Action <THREE.Object3D>(
                        o =>
                {
                    o.traverse(
                        new Action <object>(
                            child =>
                    {
                        var m = child as THREE.Mesh;
                        if (m != null)
                        {
                            m.material.map = texture;

                            // http://stackoverflow.com/questions/10857233/in-three-js-alpha-channel-works-inconsistently
                            (m.material as dynamic).transparent = true;
                        }
                    }
                            )
                        );



                    this.Source.SetResult(o);
                }
                        )
                    //, null, null
                    );

                //
                //await s.Task;
            }
                )();
        }
Exemple #14
0
        public static GoogleThreeDWarehouseImage ToGoogleThreeDWarehouseImage(this IHTMLImage source)
        {
            var n = new GoogleThreeDWarehouseImage
            {
                Image = source
            };


            string mid = null;

            var u = new Uri(source.src);

            if (u.Host != "sketchup.google.com")
            {
                return(null);
            }

            if (u.AbsolutePath != "/3dwarehouse/download")
            {
                return(null);
            }

            foreach (var p in u.Query.Split('&'))
            {
                var kv = p.Split('=');
                if (kv.Length == 2)
                {
                    if (kv[0] == "mid")
                    {
                        mid = kv[1];
                    }
                }
            }

            if (mid == null)
            {
                return(null);
            }

            n.Token = mid;

            n.Frames = Enumerable.ToArray(
                from imagenum in Enumerable.Range(0, 36)
                select new IHTMLImage("http://sketchup.google.com/3dwarehouse/download?mid=" + mid + "&rtyp=swivel&setnum=0&imagenum=" + imagenum)
            {
                border = 0
            }
                );

            //n.Image.style.border = "4px solid red";



            return(n);
        }
Exemple #15
0
        public TreeNode Add(string Text, IHTMLImage Image)
        {
            var n = Add(Text);

            n.Element.OpenImage          = Image;
            n.Element.OpenImage.border   = 0;
            n.Element.ClosedImage        = (IHTMLImage)Image.cloneNode(true);
            n.Element.ClosedImage.border = 0;
            n.InternalUpdate();

            return(n);
        }
Exemple #16
0
 private void InternalPlaceholderOrButton(IHTMLImage x)
 {
     if (this.InternalChildren.Any())
     {
         x.style.display = IStyle.DisplayEnum.empty;
         this.Element.ButtonChildless.style.display = ScriptCoreLib.JavaScript.DOM.IStyle.DisplayEnum.none;
     }
     else
     {
         x.style.display = IStyle.DisplayEnum.none;
         this.Element.ButtonChildless.style.display = ScriptCoreLib.JavaScript.DOM.IStyle.DisplayEnum.inline_block;
     }
 }
        public static string toDataURL(this IHTMLImage img)
        {
            var context = new CanvasRenderingContext2D();

            context.canvas.width  = img.width;
            context.canvas.height = img.height;

            context.drawImage(img, 0, 0, img.width, img.height);

            var dataURL = context.canvas.toDataURL();

            return(dataURL);
        }
Exemple #18
0
        static IHTMLImage CloneImage(IHTMLImage xi)
        {
            var iii = new IHTMLImage(xi.src)
            {
                title = xi.title,
                alt   = xi.alt
            };


            iii.style.SetSize(xi);

            return(iii);
        }
        public static void HideNowButShowAtDelay(this IHTMLImage jsc)
        {
            jsc.style.visibility = IStyle.VisibilityEnum.hidden;

            jsc.InvokeOnComplete(
                delegate
            {
                500.AtDelay(
                    delegate
                {
                    jsc.style.visibility = IStyle.VisibilityEnum.visible;
                }
                    );
            }
                );
        }
		private void Start1()
		{

			//concept.AttachToDocument();

			var Title = new IHTMLDiv
			{

			};

			new Browsers
			{
			}.Container.AttachTo(Title);

			new HTML.Images.FromBase64.twitter_small().AttachToDocument();
			new HTML.Images.FromAssets.twitter_small().AttachToDocument();




			var TitleLogo = new IHTMLImage("assets/ScriptCoreLib/jsc.png");
			var TitleText = new IHTMLSpan("UltraApplication");
			TitleText.style.fontFamily = ScriptCoreLib.JavaScript.DOM.IStyle.FontFamilyEnum.Verdana;
			TitleText.style.paddingLeft = "2em";
			TitleText.style.fontSize = "xx-large";
			TitleLogo.style.verticalAlign = "middle";


			Title.appendChild(TitleLogo);
			Title.appendChild(TitleText);

			Title.style.height = "128px";

			Title.AttachToDocument();
			Title.FadeIn(2500, 1000,
				delegate
				{
					1500.AtDelay(
						delegate
						{
							ContinueBuildingApplication();
						}
					);
				}
			);
		}
        public TipRotator(TipDocument _Data)
        {
            this.Data = _Data;

            if (this.Data == null)
                this.Data = DefaultData;

            var div = new IHTMLDiv();

            var header = new IHTMLElement(IHTMLElement.HTMLElementEnum.h3, this.Data.Topic).AttachTo(div);

            var randomized = this.Data.Tips.Randomize();

            var current = randomized.First();

            var content = new IHTMLElement(IHTMLElement.HTMLElementEnum.p).AttachTo(div);

            var next = new IHTMLButton("Next Tip").AttachTo(div);

            var src = "assets/ClickOnce/Button_19.gif";

            
            var img = new IHTMLImage(this.Data.Location + src).AttachTo(next);

            img.style.verticalAlign = "middle";

            Action GoNext =
                delegate
                {
                    current = randomized.Next(i => i == current);

                    content.innerText = current.Content;
                    content.style.color = current.Color;
                };

            GoNext();

            next.onclick +=
                delegate
                {
                    GoNext();
                };

            div.AttachTo(Native.Document.body);
        }
        public static void SpawnEntrypointWithBrandning(this Type alias)
        {
            if (Native.window == null)
            {
                return;
            }

            Native.window.onload +=
                delegate
            {
                IHTMLImage i = "assets/ScriptCoreLib/jsc.png";

                i.style.position = IStyle.PositionEnum.absolute;
                i.style.right    = "1em";
                i.style.bottom   = "1em";
                i.AttachToDocument();
            };

            ScriptCoreLib.JavaScript.Native.Spawn(alias.Name, i => Activator.CreateInstance(alias));
        }
        public static void BeginPulseAnimation(this IHTMLImage jsc)
        {
            jsc.style.Opacity = 0;

            jsc.InvokeOnComplete(
                delegate
            {
                jsc.FadeIn(500, 1000,
                           delegate
                {
                    new Timer(
                        t =>
                    {
                        jsc.style.Opacity = (Math.Cos(t.Counter * 0.1) + 1.0) * 0.5;
                    }
                        , 1, 1000 / 15);
                }
                           );
            }
                );
        }
Exemple #24
0
        public __PictureBox()
        {
            // http://stackoverflow.com/questions/18389224/how-to-style-html5-range-input-to-have-different-color-before-and-after-slider

            this.HTMLTarget = new IHTMLDiv
            {
            };



            this.InternalElement = new IHTMLImage
            {
            }.AttachTo(this.HTMLTarget);


            // keep only borders
            this.InternalElement.style.height = "100%";
            this.InternalElement.style.width  = "100%";



            this.Size = new global::System.Drawing.Size(200, 200);
        }
Exemple #25
0
        public UltraApplication(IHTMLElement e)
        {
            var Title = new IHTMLDiv
            {
                innerHTML = @"
<img border='0' src='http://www.w3schools.com/images/compatible_ie.gif' width='31' height='30' alt='Internet Explorer' title='Internet Explorer' />
<img border='0' src='http://www.w3schools.com/images/compatible_firefox.gif' width='31' height='30' alt='Firefox' title='Firefox' />
<img border='0' src='http://www.w3schools.com/images/compatible_opera.gif' width='28' height='30' alt='Opera' title='Opera' />
<img border='0' src='http://www.w3schools.com/images/compatible_chrome.gif' width='31' height='30' alt='Google Chrome' title='Google Chrome' />
<img border='0' src='http://www.w3schools.com/images/compatible_safari.gif' width='28' height='30' alt='Safari' title='Safari' />
"
            };


            var TitleLogo = new IHTMLImage("assets/ScriptCoreLib/jsc.png");
            var TitleText = new IHTMLSpan("UltraApplication");

            TitleText.style.fontFamily    = ScriptCoreLib.JavaScript.DOM.IStyle.FontFamilyEnum.Verdana;
            TitleText.style.paddingLeft   = "2em";
            TitleText.style.fontSize      = "xx-large";
            TitleLogo.style.verticalAlign = "middle";


            Title.appendChild(TitleLogo);
            Title.appendChild(TitleText);

            Title.style.height = "128px";

            Title.AttachToDocument();
            Title.FadeIn(2500, 1000,
                         delegate
            {
                1500.AtDelay(ContinueBuildingApplication);
            }
                         );
        }
Exemple #26
0
        public void InitializeContent()
        {
            // Initialise WebGL

            // if canvas object makes use of toDataUrl then this arg is required!
            var gl = new WebGLRenderingContext(preserveDrawingBuffer: true, alpha: false);

            var canvas = gl.canvas;

            Native.document.body.style.overflow = IStyle.OverflowEnum.hidden;

            canvas.AttachToDocument();
            canvas.style.SetLocation(0, 0);
            canvas.style.backgroundColor = "black";

            var s = new RaySurface(this);

            this.onsurface(gl);



            #region Dispose
            var IsDisposed = false;

            Dispose = delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                IsDisposed = true;

                canvas.Orphanize();
            };
            #endregion

            #region AtResize
            Action AtResize = delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                canvas.width  = Native.window.Width;
                canvas.height = Native.window.Height;

                this.onresize(Native.window.Width, Native.window.Height);
            };

            AtResize();

            Native.window.onresize += delegate
            {
                AtResize();
            };
            #endregion

            Func <string> newicon = delegate
            {
                var icon = canvas.toDataURL("image/png");

                Native.document.getElementsByTagName("link").AsEnumerable().ToList().WithEach(
                    e =>
                {
                    var link = (IHTMLLink)e;

                    if (link.rel == "icon")
                    {
                        if (link.type == "image/png")
                        {
                            link.href = icon;
                        }
                        else
                        {
                            link.Orphanize();
                        }
                    }
                }
                    );

                return(icon);
            };


            Native.window.onframe += delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                this.onframe();
            };

            Native.document.body.onclick +=
                delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                newicon();
            };


            Native.document.body.ondblclick +=
                delegate
            {
                if (IsDisposed)
                {
                    return;
                }


                Native.document.body.requestFullscreen();
            };

            #region draggable

            // http://www.thecssninja.com/javascript/gmail-dragout
            // can we drag ourself into crx?
            @"Sphere Ray Trace".ToDocumentTitle();

            Native.window.requestAnimationFrame +=
                delegate
            {
                var icon = newicon();
                var img  = new IHTMLImage {
                    src = icon
                };

                //img.width = Native.Window.Width / 2;
                //img.height = Native.Window.Height / 2;

#if PackageAsApplication
                Native.Document.getElementsByTagName("script")
                .Select(k => (IHTMLScript)k)
                .FirstOrDefault(k => k.src.EndsWith("/view-source"))
                .With(
                    source =>
                {
                    #region PackageAsApplication
                    Action <IHTMLScript, XElement, Action <string> > PackageAsApplication =
                        (source0, xml, yield) =>
                    {
                        new IXMLHttpRequest(
                            ScriptCoreLib.Shared.HTTPMethodEnum.GET, source0.src,
                            (IXMLHttpRequest r) =>
                        {
                            // store hash
                            xml.Add(new XElement("link", new XAttribute("rel", "location"), new XAttribute("href", Native.Document.location.hash)));

                            #region script
                            xml.Add(
                                new XElement("script",
                                             "/* source */"
                                             )
                                );

                            var data = "";


                            Action later = delegate
                            {
                                data = data.Replace("/* source */", r.responseText);
                            };
                            #endregion


                            //Native.Document.getElementsByTagName("link").AsEnumerable().ToList().ForEach(

                            xml.Elements("link").ToList().ForEach(
                                (XElement link, Action next) =>
                            {
                                #region style
                                var rel = link.Attribute("rel");
                                if (rel.Value != "stylesheet")
                                {
                                    next();
                                    return;
                                }

                                var href = link.Attribute("href");

                                var placeholder = "/* " + href.Value + " */";

                                //page.DragHTM.innerText += " " + placeholder;


                                xml.Add(new XElement("style", placeholder));

                                new IXMLHttpRequest(ScriptCoreLib.Shared.HTTPMethodEnum.GET, href.Value,
                                                    rr =>
                                {
                                    later += delegate
                                    {
                                        data = data.Replace(placeholder, rr.responseText);
                                    };

                                    Console.WriteLine("link Remove");
                                    link.Remove();

                                    next();
                                }
                                                    );

                                #endregion
                            }
                                )(
                                delegate
                            {
                                data = xml.ToString();
                                Console.WriteLine("data: " + data);
                                later();

                                yield(data);
                            }
                                );
                        }
                            );
                    };
                    #endregion


                    PackageAsApplication(
                        source,
                        XElement.Parse(new DefaultPage.XMLSourceSource().Text),
                        data =>
                    {
                        var bytes  = Encoding.ASCII.GetBytes(data);
                        var data64 = System.Convert.ToBase64String(bytes);


                        Native.Document.body.title = "Drag me!";

                        Native.Document.body.ondragstart +=
                            e =>
                        {
                            //e.dataTransfer.setData("text/plain", "Sphere");

                            // http://codebits.glennjones.net/downloadurl/virtualdownloadurl.htm
                            //e.dataTransfer.setData("DownloadURL", "image/png:Sphere.png:" + icon);

                            e.dataTransfer.setData("DownloadURL", "application/octet-stream:Sphere.htm:data:application/octet-stream;base64," + data64);
                            e.dataTransfer.setData("text/html", data);
                            e.dataTransfer.setData("text/uri-list", Native.Document.location + "");
                            e.dataTransfer.setDragImage(img, img.width / 2, img.height / 2);
                        };
                    }
                        );
                }
                    );
#endif
            };


            #endregion
        }
        //public const string Alias = "Class1";
        //public const string DefaultData = "Class1Data";

        /// <summary>
        /// Creates a new control
        /// </summary>
        /// <param name="DataElement">The hidden data element</param>
        public Class1(IHTMLElement DataElement)
        {
            IStyleSheet.Default.AddRule("*", "cursor: url('assets/NatureBoy/cursor.cur'), auto;", 0);

            IStyleSheet.Default.AddRule("body",
                r =>
                {
                    r.style.backgroundColor = Color.Gray;
                    r.style.overflow = IStyle.OverflowEnum.hidden;
                    r.style.padding = "0px";
                }
            );

            IStyleSheet.Default.AddRule(".stage",
                r =>
                {
                    r.style.backgroundColor = Color.White;

                    r.style.position = IStyle.PositionEnum.absolute;
                    r.style.left = "0px";
                    r.style.top = "0px";
                    r.style.right = "0px";
                    r.style.bottom = "0px";
                    r.style.Opacity = 0.0;
                }
            );



            var bg = new IHTMLImage("assets/NatureBoy/back/IMG_0572.jpg");

            bg.style.position = IStyle.PositionEnum.absolute;
            bg.style.SetLocation(0, 0);
            bg.style.width = "100%";
            bg.AttachToDocument();



            var stage = new IHTMLDiv { className = "stage" };

            stage.AttachToDocument();


            var dude4 = new Dude { ZoomFunc = y => (y + 300) / (600) };

            dude4.TeleportTo(200, 200);
            dude4.Control.AttachToDocument();
            dude4.AutoRotate(1);

            var dude5 = new Dude { ZoomFunc = dude4.ZoomFunc };

            dude5.TeleportTo(600, 300);
            dude5.Control.AttachToDocument();
            dude5.AutoRotateToCursor(stage);

            var dude6 = new Dude { ZoomFunc = dude4.ZoomFunc };

            dude6.TeleportTo(300, 400);
            dude6.Control.AttachToDocument();

            var dude7 = new Dude { ZoomFunc = dude4.ZoomFunc };

            dude7.TeleportTo(200, 400);
            dude7.Control.AttachToDocument();

            var dude8 = new Dude { ZoomFunc = dude4.ZoomFunc };

            dude8.TeleportTo(250, 300);
            dude8.Control.AttachToDocument();

            var CurrentDude = default(Dude);

            Action<Dude> SelectDude = i =>
                                          {
                                              if (CurrentDude != null)
                                                  CurrentDude.IsSelected = false;

                                              CurrentDude = i;
                                              CurrentDude.IsSelected = true;
                                          };

            Action<Dude> BindSelectDude =
                i => i.Control.onclick += delegate { SelectDude(i); };

            BindSelectDude(dude6);
            BindSelectDude(dude7);
            BindSelectDude(dude8);


            stage.onclick +=
                delegate(IEvent ev)
                {
                    CurrentDude.WalkTo(ev.CursorPosition);

                    dude5.WalkTo(ev.CursorPosition);
                };

        }
        public __DataGridView()
        {
            //Console.WriteLine("enter DataGridView .ctor");

            Console.WriteLine("event: enter new DataGridView()");

            this.AutoGenerateColumns = true;


            // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201404/20140412
            // tested by?
            // X:\jsc.svn\examples\javascript\forms\test\TestWebBrowserOneWayDataBinding\TestWebBrowserOneWayDataBinding\ApplicationControl.Designer.cs
            //    this.dataGridView1.RowTemplate.Height = 24;
            this.RowTemplate = new DataGridViewRow();

            this.InternalElement = new IHTMLDiv
            {

                // do this ahead of time
                // when can we have a special type for a classname string?
                className = typeof(DataGridView).Name
            };

            // can jsc help us here and via [HTMLAttribute] redirect the data to html attribute?
            this.AllowUserToResizeColumnsAttribute = new XAttribute("AllowUserToResizeColumns", "").AttachTo(this.InternalElement);
            this.RowHeadersVisibleAttribute = new XAttribute("RowHeadersVisible", "true").AttachTo(this.InternalElement);


            // add the rule to current document.
            // what happens if we do popup?
            // wha about scoped style?
            this.css = this.InternalElement.css;

            // do we need this?
            this.InternalElement.style.overflow = DOM.IStyle.OverflowEnum.hidden;



            this.InternalColumns = new __DataGridViewColumnCollection();
            this.Columns = (DataGridViewColumnCollection)(object)this.InternalColumns;

            #region InternalRows
            this.InternalRows = new __DataGridViewRowCollection
            {
                InternalContext = this
            };
            this.Rows = (DataGridViewRowCollection)(object)this.InternalRows;

            this.InternalRows.InternalItems.Added +=
                (s, i) =>
                {
                    s.InternalContext = this;
                };
            #endregion


            #region SelectedCells
            this.InternalSelectedCells = new __DataGridViewSelectedCellCollection();
            this.SelectedCells = (DataGridViewSelectedCellCollection)(object)this.InternalSelectedCells;
            this.InternalSelectedCells.InternalItems.ListChanged +=
                (_s, _e) =>
                {
                    if (_e.ListChangedType == ListChangedType.ItemAdded)
                    {
                        var item = this.InternalSelectedCells.InternalItems[_e.NewIndex];

                        // when is this null?
                        //if (this.DefaultCellStyle == null)
                        //{
                        //    item.InternalContentContainer.style.backgroundColor = JSColor.System.Highlight;
                        //}
                        //else
                        //{
                        var SelectionBackColor = this.DefaultCellStyle.SelectionBackColor;
                        var SelectionForeColor = this.DefaultCellStyle.SelectionForeColor;

                        item.InternalTableColumn_div.style.backgroundColor = SelectionBackColor.ToString();
                        //}
                        //item.InternalContentContainer.style.color = JSColor.System.HighlightText;

                        // tested by
                        // X:\jsc.svn\core\ScriptCoreLib.Windows.Forms\ScriptCoreLib.Windows.Forms\JavaScript\BCLImplementation\System\Windows\Forms\DataGridView.cs
                        item.InternalTableColumn_div.style.color = SelectionForeColor.ToString();
                    }


                    if (SelectionChanged != null)
                        SelectionChanged(this, new EventArgs());
                };
            #endregion


            this.MultiSelect = true;



            this.InternalSetDefaultFont();

            this.InternalScrollContainerElement = new IHTMLDiv
            {
                // pstyle
                className = "InternalScrollContainerElement"
            }.AttachTo(this.InternalElement);




            //this.InternalScrollContainerElement.style.backgroundColor = JSColor.Gray;
            this.BackgroundColor = global::System.Drawing.SystemColors.AppWorkspace;

            this.InternalScrollContainerElement.style.overflow = DOM.IStyle.OverflowEnum.auto;

            // tested by
            // X:\jsc.svn\examples\javascript\css\CSSPrintMediaExperiment\CSSPrintMediaExperiment\Application.cs

            // for printer we do not want to see the scollbar
            // if we change the document we will loose the style?
            // this wont work
            //IStyleSheet.Default
            //    [CSSMediaTypes.print]
            //    [this.InternalScrollContainerElement].style.overflow =
            //        IStyle.OverflowEnum.hidden;


            new IStyle(this.InternalScrollContainerElement)
            {
                position = DOM.IStyle.PositionEnum.absolute,
                left = "0px",
                top = "0px",
                right = "0px",
                bottom = "0px"
            };


            var __ContentTableContainer = new IHTMLDiv { className = "__ContentTableContainer" }.AttachTo(InternalScrollContainerElement);

            // 116ms css.style { selectorText = table.__ContentTable[style-id="2"] > tbody > tr > td } 
            this.__ContentTable = new IHTMLTable
            {
                className = __ContentTable_className,
                cellPadding = 0,
                cellSpacing = 0
            }.AttachTo(__ContentTableContainer);

            // X:\jsc.svn\examples\javascript\css\CSSOdd\CSSOdd\Application.cs

            //this.__ContentTable_css = css.descendants[className];
            this.__ContentTable_css = css[this.__ContentTable];

            //css.adjacentSibling[]
            //css.siblings

            //92ms css.style { selectorText = div.DataGridView[style-id="2"] table.__DataGridViewContentTable > tbody > tr > td } view-source:34816

            // view-source:34816
            //92ms css.style { selectorText = table.__DataGridViewColumnsTable[style-id="3"] > tbody > tr > td } 

            // the hacky way:
            //this.__ContentTable_css = css[" table." + this.__ContentTable.className];

            this.__ContentTable_css_td = this.__ContentTable_css
                + IHTMLElement.HTMLElementEnum.tbody
                + IHTMLElement.HTMLElementEnum.tr
                + IHTMLElement.HTMLElementEnum.td;

            this.__ContentTable_css_alt_td = this.__ContentTable_css
                [IHTMLElement.HTMLElementEnum.tbody][IHTMLElement.HTMLElementEnum.tr].even[IHTMLElement.HTMLElementEnum.td];

            this.__ContentTable_css_odd_td = this.__ContentTable_css
                [IHTMLElement.HTMLElementEnum.tbody][IHTMLElement.HTMLElementEnum.tr].odd[IHTMLElement.HTMLElementEnum.td];


            __ContentTable.style.paddingTop = "22px";



            var __ColumnsTableContainer = new IHTMLDiv
            {
                className = "__ColumnsTableContainer"
            }.AttachTo(InternalScrollContainerElement);

            // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2013/201312/20131213-forms-css
            this.__ColumnsTable = new IHTMLTable
            {
                className = __ColumnsTable_className,

                cellPadding = 0,
                cellSpacing = 0
            }.AttachTo(
            __ColumnsTableContainer);

            this.__ColumnsTable_css = css[this.__ColumnsTable];

            this.__ColumnsTable_css_td =
                this.__ColumnsTable_css
                + IHTMLElement.HTMLElementEnum.tbody
                + IHTMLElement.HTMLElementEnum.tr
                + IHTMLElement.HTMLElementEnum.td;

            IHTMLTableRow __ColumnsTableRow = null;

            //__ColumnsTableContainer.style.SetLocation(0, 0);
            __ColumnsTableContainer.style.position = IStyle.PositionEnum.absolute;
            __ColumnsTableContainer.style.left = "0px";

            __ColumnsTableRow = __ColumnsTable.AddBody().AddRow();
            __ColumnsTableRow.style.height = "22px";


            var __RowsTableContainer = new IHTMLDiv
            {
                className = "__RowsTableContainer"
            }.AttachTo(InternalScrollContainerElement);

            //__RowsTableContainer.style.SetLocation(0, 0);
            __RowsTableContainer.style.position = IStyle.PositionEnum.absolute;
            __RowsTableContainer.style.top = "0px";


            this.__RowsTable = new IHTMLTable
            {
                className = __RowsTable_className,
                cellPadding = 0,
                cellSpacing = 0
            }.AttachTo(__RowsTableContainer);

            // should we make the monkier a bit lazier?
            this.__RowsTable_css = css[this.__RowsTable];

            // 139ms { __RowsTable_css = { selectorText = div.DataGridView[style-id="2"] > div:nth-of-type(1) > div:nth-of-type(3) > table:nth-of-type(1), selectorElement =  } } 
            //Console.WriteLine(new { this.__RowsTable_css });
            this.__RowsTable_css_td = this.__RowsTable_css
                + IHTMLElement.HTMLElementEnum.tbody
                + IHTMLElement.HTMLElementEnum.tr
                + IHTMLElement.HTMLElementEnum.td;

            this.__RowsTable_css_td.style.backgroundColor = "cyan";


            __RowsTable.style.paddingTop = "22px";
            this.__RowsTableBody = __RowsTable.AddBody();

            Console.WriteLine("new DataGridView() before Corner");

            #region Corner
            this.__Corner = new IHTMLDiv().AttachTo(InternalScrollContainerElement);


            __Corner.style.position = IStyle.PositionEnum.absolute;
            //__Corner.style.SetLocation(0, 0);
            __Corner.style.height = "22px";

            #endregion

            // too slow for onscroll
            //var css_fixed_left =
            //    __RowsTableContainer.css
            //    | __Corner.css;

            //var css_fixed_top =
            //   __ColumnsTableContainer.css
            //   | __Corner.css;

            #region onscroll
            Action onscroll = delegate
            {
                // perhaps we should only use .css for static styles?

                // how much faster are we if we skip .css ?
                __Corner.style.top = this.InternalScrollContainerElement.scrollTop + "px";
                __ColumnsTableContainer.style.top = this.InternalScrollContainerElement.scrollTop + "px";

                __Corner.style.left = this.InternalScrollContainerElement.scrollLeft + "px";
                __RowsTableContainer.style.left = this.InternalScrollContainerElement.scrollLeft + "px";


                //css_fixed_left.style.left = this.InternalScrollContainerElement.scrollLeft + "px";
                //css_fixed_top.style.top = this.InternalScrollContainerElement.scrollTop + "px";
            };
            #endregion

            this.__ContentTableBody = __ContentTable.AddBody();

            this.InternalNewRow = new __DataGridViewRow();
            this.InternalNewRow.InternalTableRow = __ContentTableBody.AddRow();
            this.InternalNewRow.InternalTableRow.style.height = "22px";


            this.InternalRows.InternalItems.Source.Add(InternalNewRow);

            // http://www.w3schools.com/cssref/sel_last-of-type.asp
            // dont we have lastOfType available yet?
            var InternalNewRow_content_css =
                // can we have LINQ style?  .Last()
                (__ContentTable_css + IHTMLElement.HTMLElementEnum.tbody).last[IHTMLElement.HTMLElementEnum.tr];

            var InternalNewRow_header_css = __RowsTable_css
                [IHTMLElement.HTMLElementEnum.tbody].last[IHTMLElement.HTMLElementEnum.tr];

            var InternalNewRow_css = InternalNewRow_content_css | InternalNewRow_header_css;

            // move to conditional css!
            this.AllowUserToAddRowsChanged +=
                delegate
                {
                    if (this.AllowUserToAddRows)
                        InternalNewRow_css.style.display = IStyle.DisplayEnum.empty;
                    else
                        InternalNewRow_css.style.display = IStyle.DisplayEnum.none;
                };


            this.DefaultCellStyle = new DataGridViewCellStyle
            {
                BackColor = global::System.Drawing.SystemColors.Window
            };

            this.ColumnHeadersDefaultCellStyle = new DataGridViewCellStyle
            {
                BackColor = global::System.Drawing.SystemColors.ButtonFace
            };

            this.RowHeadersDefaultCellStyle = new DataGridViewCellStyle
            {
                BackColor = global::System.Drawing.SystemColors.ButtonFace
            };


            Console.WriteLine("new DataGridView() before CreateVerticalResizer");


            #region CreateVerticalResizer --
            Func<IHTMLDiv> CreateVerticalResizer =
                () =>
                {
                    var r = new IHTMLDiv { className = "VerticalResizer" };

                    r.style.position = DOM.IStyle.PositionEnum.absolute;
                    r.style.height = "9px";
                    r.style.left = "0px";
                    r.style.width = "200px";
                    //HorizontalResizer.style.backgroundColor = JSColor.Red;
                    //r.style.cursor = DOM.IStyle.CursorEnum.move;

                    var l = new IHTMLDiv().AttachTo(r);

                    l.style.position = DOM.IStyle.PositionEnum.absolute;
                    l.style.top = "4px";
                    l.style.height = "1px";
                    l.style.left = "0px";
                    l.style.right = "0px";

                    //l.style.backgroundColor = this.InternalBackgroundColor.ToString();
                    ////l.style.backgroundColor = "yellow";

                    //InternalBackgroundColorChanged +=
                    //    delegate
                    //    {
                    //        l.style.backgroundColor = this.InternalBackgroundColor.ToString();
                    //    };


                    l.setAttribute("data-resizer", "resizer");

                    //this.InternalGridColorTargets.Add(
                    //     l.css
                    // );



                    this.ClientSizeChanged +=
                       delegate
                       {
                           r.style.width = "200x";
                           //r.Hide();

                           Native.window.requestAnimationFrame +=
                               //new ScriptCoreLib.JavaScript.Runtime.Timer(
                               delegate
                               {
                                   r.style.width = this.InternalScrollContainerElement.clientWidth + "px";
                                   //l.style.backgroundColor = "red";
                                   //r.Show();

                               }
                           ;
                           //).StartTimeout(200);
                       };


                    return r;
                };
            #endregion


            //css[(dynamic x) => x.AllowUserToResizeColumns == false][" .HorizontalResizer"].style.display = IStyle.DisplayEnum.none;
            //css[x => x.getAttribute("AllowUserToResizeColumns") == false][" .HorizontalResizer"].style.display = IStyle.DisplayEnum.none;

            var xAllowUserToResizeColumns_false = new XAttribute("AllowUserToResizeColumns", "false");

            css[xAllowUserToResizeColumns_false][" .HorizontalResizer"].style.display = IStyle.DisplayEnum.none;

            // should jsc go and detect where the attribute is attached to?
            //css[" .HorizontalResizer"][xAllowUserToResizeColumns_false].style.display = IStyle.DisplayEnum.none;

            // before CreateHorizontalResizer 

            var css_HorizontalResizer = css[" .HorizontalResizer"];

            new IStyle(css_HorizontalResizer)
            {
                position = DOM.IStyle.PositionEnum.absolute,
                width = "9px",
                height = "22px"
            };

            css_HorizontalResizer.hover.style.height = "100%";
            css_HorizontalResizer.active.style.height = "100%";
            css_HorizontalResizer.style.cursor = DOM.IStyle.CursorEnum.move;

            //var css_HorizontalResizerLine = css_HorizontalResizer[IHTMLElement.HTMLElementEnum.div];

            new IStyle(css_HorizontalResizer.after)
            {
                // just to show up, we need to set this?
                content = "''",

                position = DOM.IStyle.PositionEnum.absolute,
                left = "4px",
                width = "1px",
                top = "0px",
                bottom = "0px"
            };

            //_HorizontalResizer.css.active.first.style.color = "blue";
            //_HorizontalResizer.css.style.backgroundColor = "yellow";
            //_HorizontalResizer.css.active.style.backgroundColor = "cyan";

            // debug
            //_HorizontalResizer.css.first.style.backgroundColor = "cyan";

            // ?css.after.parent.hover...
            css_HorizontalResizer.hover.after.style.backgroundColor = "black";
            css_HorizontalResizer.active.after.style.backgroundColor = "blue";

            // save it so we can change the color
            this.InternalGridColor_css = css_HorizontalResizer.after;

            //var css = 



            //var ZeroVerticalResizer = CreateVerticalResizer().AttachTo(InternalElement);

            //ZeroVerticalResizer.style.SetLocation(0, 22 - 5);

            Console.WriteLine("new DataGridView() before ZeroHorizontalResizer");



            #region ZeroHorizontalResizer

            //var ZeroHorizontalResizer = CreateHorizontalResizer().AttachTo(InternalElement);
            var ZeroHorizontalResizer = new IHTMLDiv { className = "HorizontalResizer" }.AttachTo(InternalScrollContainerElement);

            var ZeroHorizontalResizerDrag = new DragHelper(ZeroHorizontalResizer)
            {
                // why cant I see it?
                Position = new Point(32, 0),
                Enabled = true
            };


            //Action UpdateToVerticalResizerScroll = delegate
            //{
            //    //ZeroVerticalResizer.style.SetLocation(
            //    //    this.InternalScrollContainerElement.scrollLeft,
            //    //    this.InternalScrollContainerElement.scrollTop + (22 - 5)
            //    //);
            //};



            #region UpdateToHorizontalResizerScroll
            Action UpdateToHorizontalResizerScroll = delegate
            {
                ZeroHorizontalResizer.style.SetLocation(
                        this.InternalScrollContainerElement.scrollLeft + ZeroHorizontalResizerDrag.Position.X - 1,
                        this.InternalScrollContainerElement.scrollTop
                    );
            };
            #endregion

            // what if the the value is changed in the inspector/
            // will our control survive the change? as we dont get any events for that.
            // almost. the Fill will not be recalculate just yet tho
            // tested by
            // X:\jsc.svn\examples\javascript\forms\Test\TestFlowDataGridPadding\TestFlowDataGridPadding\Application.cs
            css[new XAttribute("RowHeadersVisible", "false")][__ColumnsTable, __ContentTable].style.paddingLeft = "1px";
            var css_RowHeadersVisible_true = css[new XAttribute("RowHeadersVisible", "true")][__ColumnsTable, __ContentTable];

            #endregion

            Console.WriteLine("new DataGridView() before UpdateToHorizontalResizerDrag");


            #region UpdateToHorizontalResizerDrag
            Action UpdateToHorizontalResizerDrag = delegate
            {
                //var value = (ZeroHorizontalResizerDrag.Position.X + 4);
                var value = (ZeroHorizontalResizerDrag.Position.X + 4);

                // no we want it completly gone, not just at 4px
                if (this.RowHeadersVisible)
                {

                    __Corner.style.width = (value - 2) + "px";

                    __RowsTable.style.width = value + "px";
                    __RowsTable.style.minWidth = value + "px";

                    // has 2 borders
                }

                css_RowHeadersVisible_true.style.paddingLeft = value + "px";
            };

            #endregion

            // when this.RowHeadersVisible == false
            css[new XAttribute("RowHeadersVisible", "false")]
                [ZeroHorizontalResizer,
                __Corner,
                __RowsTable]
                .style.display = IStyle.DisplayEnum.none;

            UpdateToHorizontalResizerScroll();
            UpdateToHorizontalResizerDrag();

            InternalRowHeadersVisibleChanged +=
              delegate
              {
                  // tested by
                  // X:\jsc.svn\examples\javascript\Test\TestNoZeroColumnHeaderNoScrollbarDateDataGrid\TestNoZeroColumnHeaderNoScrollbarDateDataGrid\ApplicationControl.cs
                  UpdateToHorizontalResizerDrag();
                  UpdateToHorizontalResizerScroll();
              };


            #region ZeroHorizontalResizerDrag Drag
            ZeroHorizontalResizerDrag.DragStart +=
                delegate
                {
                    Native.Document.body.style.cursor = DOM.IStyle.CursorEnum.move;
                    //((IHTMLElement)ZeroHorizontalResizer.firstChild).style.backgroundColor = JSColor.Blue;
                };



            ZeroHorizontalResizerDrag.DragStop +=
                 delegate
                 {
                     Native.Document.body.style.cursor = DOM.IStyle.CursorEnum.auto;
                     //((IHTMLElement)ZeroHorizontalResizer.firstChild).style.backgroundColor = this.InternalBackgroundColor.ToString();
                     //((IHTMLElement)ZeroHorizontalResizer.firstChild).style.backgroundColor = "";
                     //((IHTMLElement)ZeroHorizontalResizer.firstChild).style.backgroundColor = "yellow";

                     UpdateToHorizontalResizerDrag();
                     InternalAutoSizeWhenFill();
                 };



            ZeroHorizontalResizerDrag.DragMove +=
                delegate
                {
                    UpdateToHorizontalResizerScroll();

                };
            #endregion



            Console.WriteLine("new DataGridView() before onscroll");

            onscroll();

            #region onscroll
            this.InternalScrollContainerElement.onscroll +=
               e =>
               {
                   // onscroll is high performance.
                   // using .css will slow us down 10x?

                   var s = Stopwatch.StartNew();

                   //UpdateToVerticalResizerScroll();
                   UpdateToHorizontalResizerScroll();


                   // 153209ms DataGridView onscroll { ElapsedMilliseconds = 13 }
                   // should jsc inline for performance?
                   onscroll();

                   // 35418ms DataGridView onscroll { ElapsedMilliseconds = 20 }
                   // 234208ms DataGridView onscroll { ElapsedMilliseconds = 120 } 
                   // 10468ms DataGridView onscroll { ElapsedMilliseconds = 27 } 

                   if (s.ElapsedMilliseconds > 10)
                       Console.WriteLine("DataGridView onscroll " + new { s.ElapsedMilliseconds });

               };
            #endregion

            Console.WriteLine("new DataGridView() after onscroll");

            __DataGridViewCell MouseCaptureCell = null;

            InternalScrollContainerElement.onmouseup +=
                delegate
                {
                    MouseCaptureCell = null;
                };


            // show data fast

            // API should do the casting here of the proxyies

            // this.Height = 22;
            // 

            // set the default for all
            // are the borders getting in our way?
            //__ContentTable_css_td.style.height = "22px";
            __ContentTable_css_td.style.height = "21px";
            __ContentTable_css_td.style.lineHeight = "21px";

            // this wont work for ff, ie
            //__ContentTable_css_td.style.position = IStyle.PositionEnum.relative;




            // IE, ff workaround. need a div to play relative
            var __ContentTable_css_td_relative = __ContentTable_css_td
                + IHTMLElement.HTMLElementEnum.div;

            new IStyle(__ContentTable_css_td_relative)
            {
                position = IStyle.PositionEnum.relative,
                width = "100%",
                height = "100%"
            };


            // ready to be made interactive
            //__ContentTable_css_td_relative["[data]"].empty.first.letter.style.color = "red";
            __ContentTable_css_td_relative["[data]"].empty.style.color = "red";
            // ah a place holder?
            // X:\jsc.svn\examples\javascript\forms\Test\TestLargeDataTable\TestLargeDataTable\ApplicationControl.cs
            __ContentTable_css_td_relative[":not([data])"].empty.style.backgroundColor = "yellow";


            var __ContentTable_css_td_empty_before = __ContentTable_css_td_relative.empty.before;

            __ContentTable_css_td_empty_before.contentXAttribute = new XAttribute("data", "");

            new IStyle(__ContentTable_css_td_empty_before)
            {

                paddingLeft = "4px",
                paddingRight = "4px",

                whiteSpace = IStyle.WhiteSpaceEnum.pre,
                overflow = IStyle.OverflowEnum.hidden,
                position = IStyle.PositionEnum.absolute,
                left = "0",
                top = "0",
                bottom = "0",
                right = "0",
            };





            // X:\jsc.svn\examples\javascript\CSS\Test\CSSNewIStyle\CSSNewIStyle\Application.cs

            // http://stackoverflow.com/questions/6601697/restore-webkits-css-outline-on-input-field

            new IStyle(
                __ContentTable_css_td + IHTMLElement.HTMLElementEnum.div + IHTMLElement.HTMLElementEnum.div)
            {
                outline = "none",

                whiteSpace = IStyle.WhiteSpaceEnum.pre,
                overflow = IStyle.OverflowEnum.hidden,
                position = IStyle.PositionEnum.absolute,
                left = "0",
                top = "0",
                bottom = "0",
                right = "0"
            };


            new IStyle(__ContentTable_css_td + IHTMLElement.HTMLElementEnum.div + IHTMLElement.HTMLElementEnum.div + IHTMLElement.HTMLElementEnum.span)
            {
                marginLeft = "4px",
                marginRight = "4px",
                lineHeight = "21px",
                whiteSpace = IStyle.WhiteSpaceEnum.pre
            };

            //Console.WriteLine("new DataGridView() before InitializeMissingCell");

            #region InitializeCell
            Action<__DataGridViewCell, __DataGridViewRow> InitializeMissingCell =
                (SourceCell, SourceRow) =>
                {
                    // https://connect.microsoft.com/IE/feedback/details/687834/getcomputedstyle-doesnt-implement-2nd-argument-pseudoelt#details

                    //Console.WriteLine("InitializeCell  " + new { SourceCell.ColumnIndex });

                    // is cell index equal to column index?
                    // what happens if we dont have enough columns?
                    // https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle

                    var SourceColumn = this.InternalColumns.InternalItems[SourceCell.ColumnIndex];

                    #region InternalTableColumn
                    SourceCell.InternalTableColumn = SourceRow.InternalTableRow.AddColumn();

                    SourceRow.InternalCells.InternalItemsX.Removed +=
                         (XRemovedCell, XRemovedCellIndex) =>
                         {
                             if (XRemovedCell == SourceCell)
                             {
                                 SourceCell.InternalTableColumn.Orphanize();
                             }
                         };
                    #endregion

                    // 951ms event: dataGridView1 set DataSource { ColumnIndex = 6, SourceRowIndex = 98, ElapsedMilliseconds = 667, a = 6.737373737373737 } 


                    // this wont work if we have multiple datagrids
                    // can we have a test for it?
                    // this div is needed for UI activities?
                    // like :before

                    var InternalTableColumn_relative = new IHTMLDiv
                    {
                    }.AttachTo(SourceCell.InternalTableColumn);

                    SourceCell.InternalTableColumn_div = new IHTMLDiv
                    {
                        tabIndex = (((SourceRow.Index + 1) << 16) + (SourceCell.ColumnIndex + 1))
                    }.AttachTo(InternalTableColumn_relative);

                    SourceCell.InternalTableColumn_div_span = new IHTMLSpan
                    {
                        // unformatted
                        //innerText = (string)SourceCell.Value
                    }.AttachTo(SourceCell.InternalTableColumn_div);

                    var SourceCellType = SourceCell.GetType();
                    //Console.WriteLine(new { SourceCellType });

                    // 25:204ms { SourceCellType = <Namespace>.DataGridViewTextBoxCell } 
                    // what about checkbox? tested by.?
                    #region __DataGridViewButtonCell
                    if (SourceColumn is __DataGridViewButtonColumn)
                    {
                        var InternalButton = new IHTMLButton().AttachTo(SourceCell.InternalTableColumn_div);


                        InternalButton.style.font = this.Font.ToCssString();

                        InternalButton.style.position = IStyle.PositionEnum.absolute;
                        InternalButton.style.left = "0px";
                        InternalButton.style.top = "0px";

                        InternalButton.style.width = "100%";
                        InternalButton.style.height = "100%";

                        SourceCell.InternalTableColumn_div_span.AttachTo(InternalButton);

                        InternalButton.onclick +=
                            delegate
                            {
                                if (this.CellContentClick != null)
                                    this.CellContentClick(this,
                                        new DataGridViewCellEventArgs(SourceCell.ColumnIndex, SourceRow.Index)
                                    );
                            };

                        return;
                    }
                    #endregion


                    #region __DataGridViewButtonCell
                    if (SourceColumn is __DataGridViewCheckBoxColumn)
                    {
                        // do we already also support DataSource DataTable typeof(bool)

                        var InternalButton = new IHTMLInput
                        {
                            type = Shared.HTMLInputTypeEnum.checkbox
                        }.AttachTo(SourceCell.InternalTableColumn_div);

                        SourceCell.InternalTableColumn_div.style.textAlign = IStyle.TextAlignEnum.center;
                        SourceCell.InternalTableColumn_div.style.padding = "2px";

                        //SourceCell.InternalTableColumn_div.style.verticalAlign = "middle";


                        //InternalButton.style.font = this.Font.ToCssString();

                        //InternalButton.style.position = IStyle.PositionEnum.absolute;
                        //InternalButton.style.left = "0px";
                        //InternalButton.style.top = "0px";

                        //InternalButton.style.width = "100%";
                        //InternalButton.style.height = "100%";

                        //InternalButton.style.margin = "auto";


                        SourceCell.InternalTableColumn_div_span.Orphanize();

                        InternalButton.onclick +=
                            delegate
                            {
                                if (this.CellContentClick != null)
                                    this.CellContentClick(this,
                                        new DataGridViewCellEventArgs(SourceCell.ColumnIndex, SourceRow.Index)
                                    );
                            };

                        return;
                    }
                    #endregion


                    // with 9 , 12, 15, 12, 6
                    // without 16, 32, 27,25, 30
#if FCELLEVENTS
                    #region AtInternalValueChanged
                    Action AtInternalValueChanged = delegate
                    {
                        InternalRaiseCellFormatting(SourceCell);

                        //var innerText = SourceCell.Value.ToString();
                        var innerText = SourceCell.FormattedValue.ToString();

                        //Console.WriteLine("AtInternalValueChanged " + new { innerText });
                        SourceCell.InternalTableColumn_div_span.innerText = innerText;

                        // ?
                        InternalRaiseCellValueChanged(SourceCell);

                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/04-monese/2014/201401/20140104-deploy
                        SourceCell.InternalTableColumn_div_span.title = SourceCell.InternalToolTipText;
                    };




                    AtInternalValueChanged();
                    SourceCell.InternalValueChanged += AtInternalValueChanged;
                    SourceCell.InternalToolTipTextChanged += AtInternalValueChanged;
                    #endregion

                    #region CellAtOffset
                    Func<int, int, __DataGridViewCell> CellAtOffset =
                        (x, y) =>
                        {
                            var value = default(__DataGridViewCell);

                            var Row = this.InternalRows.InternalItems.Source.ElementAtOrDefault(
                                SourceRow.Index + y
                            );

                            if (Row == null)
                                if (SourceRow.Index + y == this.InternalRows.Count)
                                    Row = InternalNewRow;

                            if (Row != null)
                            {
                                value = Row.InternalCells.InternalItems.ElementAtOrDefault(
                                    SourceCell.ColumnIndex + x
                                );
                            }

                            return value;
                        };
                    #endregion

                    bool ExitEditModeDone = true;

                    #region EnterEditMode
                    Action EnterEditMode =
                        delegate
                        {
                            if (this.ReadOnly)
                                return;

                            if (SourceCell.ReadOnly)
                                return;

                            if (SourceColumn.ReadOnly)
                                return;

                            if (!ExitEditModeDone)
                                return;


                            SourceCell.IsInEditMode = true;
                            ExitEditModeDone = false;

                            SourceCell.InternalTableColumn_div.Orphanize();

                            var EditElement = new IHTMLInput(Shared.HTMLInputTypeEnum.text);

                            EditElement.style.backgroundColor = "transparent";



                            EditElement.style.font = this.Font.ToCssString();


                            EditElement.style.borderWidth = "0";
                            EditElement.style.position = IStyle.PositionEnum.relative;
                            EditElement.style.left = "4px";
                            EditElement.style.top = "0";

                            EditElement.style.outline = "0";
                            EditElement.style.padding = "0";
                            EditElement.style.width = (SourceColumn.Width - 4) + "px";
                            EditElement.style.height = (SourceRow.Height - 1) + "px";

                            //EditElement.AttachTo(SourceCell.InternalTableColumn);
                            EditElement.AttachTo(InternalTableColumn_relative);

                            SourceCell.InternalStyle.InternalForeColorChanged +=
                                delegate
                                {
                                    EditElement.style.color = SourceCell.InternalStyle.InternalForeColor.ToString();
                                };

                            var OriginalValue = (string)SourceCell.Value;
                            EditElement.value = OriginalValue;


                            #region CheckChanges
                            Action CheckChanges = delegate
                            {
                                //if (((string)SourceCell.Value) != EditElement.value)
                                //{

                                var args = new __DataGridViewCellValidatingEventArgs(
                                    SourceCell.ColumnIndex,
                                     SourceRow.Index
                                )
                                {

                                    FormattedValue = EditElement.value
                                };

                                // tested by
                                // X:\jsc.svn\examples\javascript\forms\FormsDataGridViewDeleteRow\FormsDataGridViewDeleteRow\ApplicationControl.cs
                                if (this.CellValidating != null)
                                    this.CellValidating(this, (DataGridViewCellValidatingEventArgs)(object)args);

                                //Console.WriteLine("CellValidating " + new { args.Cancel });

                                if (args.Cancel)
                                {
                                    //Console.WriteLine("CellValidating Cancel " + new { OriginalValue });
                                    SourceCell.Value = OriginalValue;

                                    return;
                                }


                                SourceCell.Value = EditElement.value;

                                //}

                            };
                            #endregion

                            #region ExitEditMode
                            Action ExitEditMode = delegate
                            {
                                if (ExitEditModeDone) return;
                                ExitEditModeDone = true;
                                SourceCell.IsInEditMode = false;


                                EditElement.Orphanize();
                                SourceCell.InternalTableColumn_div.AttachTo(InternalTableColumn_relative);

                                //SourceCell.InternalStyle.InternalForeColorChanged +=
                                //    delegate
                                //    {
                                //        SourceCell.InternalContentContainer.style.color = SourceCell.InternalStyle.InternalForeColor.ToString();
                                //    };

                                //SourceCell.InternalContentContainer.style.backgroundColor = SourceCell.InternalStyle.InternalBackColor.ToString();


                                InternalRaiseCellEndEdit(SourceCell);

                                if (OriginalValue == (string)SourceCell.Value)
                                    return;

                                this.AutoResizeColumn(SourceCell.ColumnIndex);

                                //InternalRaiseCellFormatting(SourceCell);

                                Console.WriteLine("ExitEditMode AtInternalValueChanged");
                                AtInternalValueChanged();
                            };
                            #endregion



                            #region CellBeginEdit
                            EditElement.onfocus +=
                                delegate
                                {

                                    EditElement.select();
                                };
                            EditElement.focus();

                            InternalRaiseCellFormatting(SourceCell);

                            InternalRaiseCellBeginEdit(SourceCell);

                            #endregion


                            #region onblur
                            EditElement.onblur +=
                               delegate
                               {
                                   //Console.WriteLine("EditElement.onblur");

                                   if (CheckChanges != null)
                                       CheckChanges();

                                   if (ExitEditMode != null)
                                       ExitEditMode();


                               };
                            #endregion


                            var __selectionStart = -1;
                            var __selectionEnd = -1;
                            #region onkeyup
                            EditElement.onkeyup +=
                              _ev =>
                              {
                                  #region Focus
                                  Action<__DataGridViewCell> Focus =
                                      Cell =>
                                      {
                                          _ev.preventDefault();
                                          _ev.stopPropagation();

                                          if (Cell != null)
                                          {
                                              Cell.InternalTableColumn_div.focus();
                                          }
                                      };
                                  #endregion

                                  if (_ev.IsEscape)
                                  {
                                      CheckChanges = null;

                                      ExitEditMode();

                                      Focus(SourceCell);
                                      return;
                                  }

                                  if (_ev.KeyCode == (int)Keys.Up)
                                  {
                                      Focus(CellAtOffset(0, -1));
                                      return;
                                  }

                                  if (_ev.KeyCode == (int)Keys.Down)
                                  {
                                      Focus(CellAtOffset(0, 1));
                                      return;
                                  }

                                  if (_ev.KeyCode == (int)Keys.Right)
                                      if (EditElement.selectionStart == __selectionStart)
                                          if (EditElement.selectionEnd == __selectionEnd)
                                              if (__selectionEnd == __selectionStart)
                                                  if (__selectionStart == EditElement.value.Length)
                                                  {
                                                      Focus(CellAtOffset(1, 0));
                                                      return;
                                                  }

                                  if (_ev.KeyCode == (int)Keys.Left)
                                      if (EditElement.selectionStart == __selectionStart)
                                          if (EditElement.selectionEnd == __selectionEnd)
                                              if (__selectionEnd == __selectionStart)
                                                  if (__selectionStart == 0)
                                                  {
                                                      Focus(CellAtOffset(-1, 0));
                                                      return;
                                                  }

                                  __selectionEnd = EditElement.selectionEnd;
                                  __selectionStart = EditElement.selectionStart;
                              };
                            #endregion


                            #region onkeypress
                            EditElement.onkeypress +=
                                _ev =>
                                {

                                    if (_ev.IsReturn)
                                    {
                                        _ev.preventDefault();
                                        _ev.stopPropagation();

                                        if (CheckChanges != null)
                                            CheckChanges();

                                        ExitEditMode();
                                        SourceCell.InternalTableColumn_div.focus();

                                    }

                                };
                            #endregion



                        };
                    #endregion

                    #region InternalContentContainer ondblclick
                    SourceCell.InternalTableColumn_div.ondblclick +=
                        ev =>
                        {

                            ev.stopPropagation();
                            ev.preventDefault();

                            if (this.CellDoubleClick != null)
                                this.CellDoubleClick(
                                    this, new DataGridViewCellEventArgs(SourceColumn.Index, SourceRow.Index)
                                );

                            EnterEditMode();


                        };
                    #endregion

                    #region InternalContentContainer android has long taps

                    var TouchstartWatch = new Stopwatch();

                    SourceCell.InternalTableColumn_div.ontouchstart +=
                        delegate
                        {
                            Console.WriteLine("SourceCell.InternalContentContainer.ontouchstart");
                            TouchstartWatch.Restart();
                        };

                    SourceCell.InternalTableColumn_div.ontouchend +=
                        delegate
                        {
                            Console.WriteLine("SourceCell.InternalContentContainer.ontouchend");

                            if (TouchstartWatch.ElapsedMilliseconds > 300)
                            {
                                if (this.CellDoubleClick != null)
                                    this.CellDoubleClick(
                                        this, new DataGridViewCellEventArgs(SourceColumn.Index, SourceRow.Index)
                                    );

                                EnterEditMode();
                            }

                            // script: error JSC1000: No implementation found for this native method, please implement [System.Diagnostics.Stopwatch.Reset()]
                            //TouchstartWatch.Reset();

                            TouchstartWatch = new Stopwatch();
                        };
                    #endregion

                    #region InternalContentContainer onmousedown
                    SourceCell.InternalTableColumn_div.onmousedown +=
                        ev =>
                        {
                            MouseCaptureCell = SourceCell;

                            ev.preventDefault();

                            if (SourceCell.Selected)
                                EnterEditMode();
                            else
                                SourceCell.InternalTableColumn_div.focus();
                        };
                    #endregion

                    #region InternalContentContainer onmousemove
                    SourceCell.InternalTableColumn_div.onmousemove +=
                         ev =>
                         {
                             if (MouseCaptureCell == null) return;

                             if (!this.MultiSelect)
                             {
                                 MouseCaptureCell = SourceCell;
                                 ev.preventDefault();
                                 SourceCell.InternalTableColumn_div.focus();
                                 return;
                             }


                             if (ev.MouseButton == IEvent.MouseButtonEnum.Left)
                             {
                                 if (!this.InternalSelectedCells.Contains(SourceCell))
                                     this.InternalSelectedCells.Add(SourceCell);

                                 ev.preventDefault();
                             }
                         };
                    #endregion

                    #region InternalContentContainer onmouseup


                    SourceCell.InternalTableColumn_div.onmouseup +=
                        ev =>
                        {
                            if (MouseCaptureCell == null)
                                return;

                            MouseCaptureCell = null;

                            if (!ev.ctrlKey)
                                if (ev.MouseButton == IEvent.MouseButtonEnum.Left)
                                {
                                    ev.preventDefault();

                                    if (this.CellClick != null)
                                        this.CellClick(this, new DataGridViewCellEventArgs(SourceCell.ColumnIndex, SourceRow.Index));



                                    SourceCell.InternalTableColumn_div.focus();

                                }
                        };
                    #endregion

                    #region InternalContentContainer onkeydown
                    SourceCell.InternalTableColumn_div.onkeydown +=
                        ev =>
                        {

                            #region KeyNavigateTo
                            Func<Keys, int, int, bool> KeyNavigateTo =
                              (k, x, y) =>
                              {
                                  if (ev.KeyCode == (int)k)
                                  {
                                      // focus the cell on the right

                                      ev.preventDefault();
                                      ev.stopPropagation();

                                      var Cell = CellAtOffset(x, y);
                                      if (Cell != null)
                                      {
                                          Cell.InternalTableColumn_div.focus();
                                          return true;
                                      }



                                  }
                                  return false;
                              };
                            #endregion

                            #region FullRowSelect Delete
                            if (this.SelectionMode == DataGridViewSelectionMode.FullRowSelect)
                            {
                                if (ev.KeyCode == (int)Keys.Delete)
                                {
                                    if (SourceRow == InternalNewRow)
                                        return;

                                    if (!this.InternalAllowUserToDeleteRows)
                                        return;


                                    // tested by
                                    // X:\jsc.svn\examples\javascript\forms\FormsDataGridViewDeleteRow\FormsDataGridViewDeleteRow\ApplicationControl.cs


                                    // script: error JSC1000: No implementation found for this native method, please implement [System.Windows.Forms.DataGridViewRowCollection.Remove(System.Windows.Forms.DataGridViewRow)]

                                    var Cell = CellAtOffset(0, 1);


                                    if (this.InternalBeforeUserDeletedRow != null)
                                        this.InternalBeforeUserDeletedRow(
                                            this,
                                            new DataGridViewRowEventArgs(SourceRow)
                                        );

                                    this.Rows.Remove(SourceRow);

                                    if (this.UserDeletedRow != null)
                                        this.UserDeletedRow(
                                            this,
                                            new DataGridViewRowEventArgs(SourceRow)
                                        );


                                    if (Cell != null)
                                    {
                                        Cell.InternalTableColumn_div.focus();
                                    }



                                    return;
                                }
                            }
                            #endregion



                            if (KeyNavigateTo(Keys.Right, 1, 0)) return;
                            if (KeyNavigateTo(Keys.Left, -1, 0)) return;
                            if (KeyNavigateTo(Keys.Up, 0, -1)) return;
                            if (KeyNavigateTo(Keys.Down, 0, 1)) return;

                            if (ev.IsReturn)
                            {
                                ev.preventDefault();
                                ev.stopPropagation();

                                EnterEditMode();
                                return;
                            }

                            if (ev.KeyCode == (int)Keys.Space)
                            {
                                EnterEditMode();
                                return;
                            }

                            if (char.IsLetter((char)ev.KeyCode))
                            {
                                EnterEditMode();
                                return;
                            }

                            if (char.IsNumber((char)ev.KeyCode))
                            {
                                EnterEditMode();
                                return;
                            }



                        };
                    #endregion

                    #region InternalContentContainer onblur
                    SourceCell.InternalTableColumn_div.onblur +=
                        //SourceCell.InternalTableColumn.onblur +=
                        ev =>
                        {
                            SourceCell.InternalSetSelected(false);

                            if (!ev.ctrlKey)
                            {
                                // clear
                                while (this.InternalSelectedCells.Count > 0)
                                {
                                    var item = this.InternalSelectedCells.InternalItems[0];

                                    //item.InternalContentContainer.style.backgroundColor = item.InternalStyle.InternalBackColor.ToString();
                                    item.InternalTableColumn_div.style.backgroundColor = "";
                                    item.InternalTableColumn_div.style.color = item.InternalStyle.InternalForeColor.ToString();

                                    this.InternalSelectedCells.RemoveAt(0);
                                }

                            }

                            if (this.CellLeave != null)
                                this.CellLeave(this, new DataGridViewCellEventArgs(SourceCell.ColumnIndex, SourceRow.Index));

                        };
                    #endregion

                    #region InternalContentContainer onfocus
                    SourceCell.InternalTableColumn_div.onfocus +=
                        //SourceCell.InternalTableColumn.onfocus +=
                        ev =>
                        {
                            SourceCell.InternalSetSelected(true);

                            ev.preventDefault();
                            ev.stopPropagation();


                            if (this.CellEnter != null)
                                this.CellEnter(
                                    this,
                                    new DataGridViewCellEventArgs(SourceCell.ColumnIndex, SourceRow.Index)
                                );

                            {
                                var NewSelectedCell = SourceCell;

                                if (!this.InternalSelectedCells.Contains(NewSelectedCell))
                                    this.InternalSelectedCells.Add(NewSelectedCell);
                            }

                            if (this.SelectionMode == DataGridViewSelectionMode.FullRowSelect)
                            {
                                // tested by
                                // X:\jsc.svn\examples\javascript\forms\FormsDataGridRowSelect\FormsDataGridRowSelect\ApplicationControl.cs

                                foreach (var NewSelectedCell in SourceRow.InternalCells.InternalItems)
                                {

                                    if (!this.InternalSelectedCells.Contains(NewSelectedCell))
                                        this.InternalSelectedCells.Add(NewSelectedCell);
                                }

                            }

                        };
                    #endregion

                    InternalBindCellMouseEnter(SourceCell);

                    #region InternalContentContainer Font
                    SourceCell.InternalTableColumn_div.style.font = SourceCell.InternalStyle.Font.ToCssString();
                    SourceCell.InternalStyle.InternalFontChanged +=
                        delegate
                        {
                            if (SourceCell.Selected)
                                return;


                            SourceCell.InternalTableColumn_div.style.font = SourceCell.InternalStyle.Font.ToCssString();

                            if (SourceCell.InternalStyle.InternalFont.Underline)
                                SourceCell.InternalTableColumn_div.style.textDecoration = "underline";
                            else
                                SourceCell.InternalTableColumn_div.style.textDecoration = "";
                        };
                    #endregion

                    // need to move this to css
                    //#region InternalContentContainer InternalForeColorChanged
                    //SourceCell.InternalTableColumn_div.style.color = SourceCell.InternalStyle.InternalForeColor.ToString();
                    //SourceCell.InternalStyle.InternalForeColorChanged +=
                    //   delegate
                    //   {
                    //       if (SourceCell.Selected)
                    //           return;


                    //       SourceCell.InternalTableColumn_div.style.color = SourceCell.InternalStyle.InternalForeColor.ToString();
                    //   };
                    //#endregion

                    if (SourceCell.InternalStyle.Alignment == DataGridViewContentAlignment.MiddleRight)
                        SourceCell.InternalTableColumn_div.style.textAlign = IStyle.TextAlignEnum.right;
#endif

                };
            #endregion

            #region CreateMissingCells
            Action<__DataGridViewRow> CreateMissingCells =
                SourceRow =>
                {
                    //Console.WriteLine("CreateMissingCells  " + new
                    //{
                    //    SourceRow.Index,
                    //    CellsCount = SourceRow.InternalCells.InternalItems.Count,
                    //    ColumnsCount = this.InternalColumns.InternalItems.Count


                    //});

                    #region defaults
                    while (SourceRow.InternalCells.InternalItems.Count < this.InternalColumns.InternalItems.Count)
                    {
                        var ColumnIndex = SourceRow.InternalCells.Count;

                        //Console.WriteLine("CreateMissingCells  " + new { SourceRow.Index, ColumnIndex });

                        var __c = this.InternalColumns.InternalItems[ColumnIndex];

                        __DataGridViewCell SourceCell = null;


                        if (__c is __DataGridViewButtonColumn)
                        {
                            //Console.WriteLine("CreateMissingCells __DataGridViewButtonColumn " + new { SourceRow.Index, ColumnIndex });

                            SourceCell = new __DataGridViewButtonCell();
                        }
                        else if (__c is __DataGridViewCheckBoxColumn)
                        {
                            //Console.WriteLine("CreateMissingCells ? " + new { SourceRow.Index, ColumnIndex });

                            // X:\jsc.svn\examples\javascript\forms\Test\TestButtonColumn\TestButtonColumn\ApplicationControl.cs
                            SourceCell = new __DataGridViewCheckBoxCell();

                        }
                        else
                        {
                            //Console.WriteLine("CreateMissingCells ? " + new { SourceRow.Index, ColumnIndex });

                            SourceCell = new __DataGridViewTextBoxCell();
                        }

                        SourceRow.InternalCells.InternalItems.Add(SourceCell);


                    }
                    #endregion


                    //29:295ms CreateMissingCells  { Index = 0, CellsCount = 5, ColumnsCount = 1 }
                    //29:296ms what if SourceRow has more columns than the table? { i = 0 }
                    //29:298ms what if SourceRow has more columns than the table? { i = 1 }

                    for (int i = 0; i < SourceRow.InternalCells.InternalItems.Count; i++)
                    {
                        //Console.WriteLine("what if SourceRow has more columns than the table? " + new { i });

                        // X:\jsc.svn\examples\javascript\forms\FormsHistoricBindingSourcePosition\FormsHistoricBindingSourcePosition\ApplicationControl.cs
                        // SourceRow has more columns? bail? are we showing the correct columns?
                        if (i == this.Columns.Count)
                            break;

                        var SourceColumn = this.InternalColumns.InternalItems[i];
                        var SourceCell = SourceRow.InternalCells.InternalItems[i];

                        if (SourceCell.InternalTableColumn == null)
                        {
                            InitializeMissingCell(
                                SourceCell,
                                SourceRow
                            );
                        }

                        SourceColumn.InternalDefaultCellStyleChanged +=
                            delegate
                            {
                                if (SourceColumn.DefaultCellStyle != null)
                                {
                                    SourceCell.Style.ForeColor = SourceColumn.DefaultCellStyle.ForeColor;
                                    //SourceCell.Style.BackColor = SourceColumn.DefaultCellStyle.BackColor;
                                }
                            };

                        //((__DataGridViewCellStyle)SourceRow.DefaultCellStyle).InternalBackColorChanged +=
                        //    delegate
                        //    {
                        //        // when row style is changed, who overriddes who?
                        //        //SourceCell.Style.BackColor = SourceRow.DefaultCellStyle.BackColor;
                        //    };

                        if (SourceColumn.DefaultCellStyle != null)
                        {
                            SourceCell.Style.ForeColor = SourceColumn.DefaultCellStyle.ForeColor;
                            //SourceCell.Style.BackColor = SourceColumn.DefaultCellStyle.BackColor;
                        }


                    }


                };
            #endregion


            (__ColumnsTableRow.css + IHTMLElement.HTMLElementEnum.div).style.position = IStyle.PositionEnum.relative;

            Console.WriteLine("new DataGridView() before InternalColumns");

            #region InternalColumns
            this.InternalColumns.InternalItemsX.Removed +=
                (SourceColumn, NewIndex) =>
                {
                    foreach (var SourceRow in this.InternalRows.InternalItems.Source)
                    {
                        SourceRow.Cells.RemoveAt(NewIndex);
                    }

                    SourceColumn.InternalTableColumn.Orphanize();

                    SourceColumn.ColumnHorizontalResizer.Orphanize();
                };

            this.InternalColumns.InternalItemsX.Added +=
                (SourceColumn, NewIndex) =>
                {
                    // jsc why is this function slow?

                    //var SourceColumn = this.InternalColumns.InternalItems[_e.NewIndex];

                    var SourceColumnStopwatch = Stopwatch.StartNew();
                    // 1250ms { Name = dataGridView1 } InternalColumns Added { Index = 29, SourceColumnStopwatch = 41 } 

                    SourceColumn.InternalContext = this;

                    //Console.WriteLine(
                    //    new { this.Name }
                    //    + " InternalColumns Added " + new { SourceColumn.Index });


                    //if (c is __DataGridViewButtonColumn)
                    //    Console.WriteLine("InternalColumns __DataGridViewButtonColumn ItemAdded " + new { _e.NewIndex });
                    //else
                    //    Console.WriteLine("InternalColumns ? ItemAdded " + new { _e.NewIndex });


                    SourceColumn.InternalTableColumn = __ColumnsTableRow.AddColumn();

                    // move to .css
                    //SourceColumn.InternalTableColumn.style.position = IStyle.PositionEnum.relative;

                    if (this.InternalRows.Count > 0)
                        foreach (var SourceRow in this.InternalRows.InternalItems.Source)
                        {
                            CreateMissingCells(SourceRow);
                        }


                    #region c1contentcrel, move to css + :before?
                    var c1contentcrel = new IHTMLDiv { }.AttachTo(SourceColumn.InternalTableColumn);
                    c1contentcrel.style.position = IStyle.PositionEnum.relative;
                    c1contentcrel.style.left = "0";
                    c1contentcrel.style.top = "0";
                    c1contentcrel.style.right = "0";
                    c1contentcrel.style.height = "22px";

                    var c1contentc = new IHTMLDiv { }.AttachTo(c1contentcrel);
                    c1contentc.style.overflow = IStyle.OverflowEnum.hidden;
                    c1contentc.style.position = IStyle.PositionEnum.absolute;
                    c1contentc.style.left = "0";
                    c1contentc.style.top = "0";
                    c1contentc.style.right = "0";
                    c1contentc.style.height = "22px";


                    var c1content = new IHTMLSpan { innerText = SourceColumn.HeaderText }.AttachTo(c1contentc);
                    SourceColumn.InternalContent = c1content;
                    c1content.style.marginLeft = "4px";

                    // tested by
                    // X:\jsc.svn\examples\javascript\forms\TTFCurrencyExperment\TTFCurrencyExperment\ApplicationControl.cs

#if FHR
                    c1content.style.font = this.Font.ToCssString();

                    // ? we should use .css here
                    this.FontChanged +=
                        delegate
                        {
                            c1content.style.font = this.Font.ToCssString();
                        };
#endif

                    c1content.style.lineHeight = "22px";
                    #endregion


                    SourceColumn.InternalHeaderTextChanged +=
                        delegate
                        {
                            // would we be better off using :after:content attr()
                            c1content.innerText = SourceColumn.HeaderText;
                        };



                    // setting the size for the headers on top

                    //Console.WriteLine("before SourceColumnWidth_css");
                    var SourceColumnWidth_css = default(CSSStyleRuleMonkier);

                    if (SourceColumn.Index == -1)
                    {
                        // scoped style?

                        SourceColumnWidth_css =
                            this.__RowsTable_css;


                    }
                    else
                    {
                        SourceColumnWidth_css =
                                          this.__ColumnsTable_css_td[SourceColumn.Index] |
                                          this.__ColumnsTable_css_td[SourceColumn.Index][IHTMLElement.HTMLElementEnum.div] |
                                          this.__ContentTable_css_td[SourceColumn.Index] |
                                          this.__ContentTable_css_td[SourceColumn.Index][IHTMLElement.HTMLElementEnum.div];
                    }



                    #region AtInternalWidthChanged
                    Action AtInternalWidthChanged =
                        delegate
                        {
                            var SourceColumnWidthStopwatch = Stopwatch.StartNew();
                            var SourceColumnWidth = SourceColumn.Width;

                            // tested by
                            // X:\jsc.svn\examples\javascript\forms\Test\TestGrowingGrid\TestGrowingGrid\ApplicationControl.cs
                            // X:\jsc.svn\examples\javascript\forms\Test\TestFlowDataGridPadding\TestFlowDataGridPadding\Application.cs

                            // update the designer style
                            SourceColumnWidth_css.style.width = SourceColumnWidth + "px";
                            //// table wants to squeeshe the columns, prevent it


                            if (this.ColumnWidthChanged != null)
                                this.ColumnWidthChanged(this,
                                    new DataGridViewColumnEventArgs(SourceColumn)
                                   );

                            //  AtInternalWidthChanged { ElapsedMilliseconds = 0 } 
                            if (SourceColumnWidthStopwatch.ElapsedMilliseconds > 10)
                                Console.WriteLine("AtInternalWidthChanged " + new { SourceColumnWidthStopwatch.ElapsedMilliseconds });
                        };

                    SourceColumn.InternalWidthChanged += AtInternalWidthChanged;
                    AtInternalWidthChanged();
                    #endregion

                    // should jsc record the last current method before entering console writeline?
                    //Console.WriteLine(
                    //   new { this.Name }
                    //   + " InternalColumns Added step 2");
#if FHR
                    #region InternalVisibleChanged

                    //Console.WriteLine("before SourceColumnVisible__ColumnsTable_css");
                    var SourceColumnVisible__ColumnsTable_css = (__ColumnsTable_css
                     + IHTMLElement.HTMLElementEnum.tbody
                     + IHTMLElement.HTMLElementEnum.tr
                     + IHTMLElement.HTMLElementEnum.td)
                     [NewIndex];
                    //Console.WriteLine("after SourceColumnVisible__ColumnsTable_css");


                    //Console.WriteLine("before SourceColumnVisible__ContentTable_css");
                    var SourceColumnVisible__ContentTable_css = (
                        __ContentTable_css
                            + IHTMLElement.HTMLElementEnum.tbody
                          + IHTMLElement.HTMLElementEnum.tr
                         + IHTMLElement.HTMLElementEnum.td
                     )
                     [NewIndex];
                    //Console.WriteLine("after SourceColumnVisible__ContentTable_css");

                    // xattribute instead?
                    var SourceColumnVisible_css = SourceColumnVisible__ColumnsTable_css | SourceColumnVisible__ContentTable_css;

                    SourceColumn.InternalVisibleChanged +=
                        delegate
                        {
                            if (SourceColumn.Visible)
                                SourceColumnVisible_css.style.display = IStyle.DisplayEnum.empty;
                            else
                                SourceColumnVisible_css.style.display = IStyle.DisplayEnum.none;
                        };
                    #endregion

                    #region ColumnHorizontalResizer CreateHorizontalResizer
                    // should we delay this until resize is enabled?

                    //Console.WriteLine("before CreateHorizontalResizer");

                    SourceColumn.ColumnHorizontalResizer = new IHTMLDiv { className = "HorizontalResizer" };
                    // what about older rules?
                    // shall they stop existing once the new once is used?

                    //Console.WriteLine("before CreateHorizontalResizer onscroll");
                    //onscroll();

                    //Console.WriteLine("after CreateHorizontalResizer");

                    SourceColumn.ColumnHorizontalResizer.AttachTo(InternalElement);
                    //__ColumnsTableContainer.insertNextSibling(SourceColumn.ColumnHorizontalResizer);

                    var ColumnHorizontalResizerDrag = new DragHelper(SourceColumn.ColumnHorizontalResizer)
                    {
                        Enabled = true
                    };

                    SourceColumn.InternalHorizontalDrag = ColumnHorizontalResizerDrag;
                    #endregion


                    #region ColumnUpdateToHorizontalResizerScroll left
                    Action ColumnUpdateToHorizontalResizerScroll = delegate
                    {
                        var x = ColumnHorizontalResizerDrag.Position.X;

                        SourceColumn.ColumnHorizontalResizer.style.left = x + "px";
                    };
                    #endregion

                    #region ColumnUpdateToHorizontalResizerScroll
                    // do we need this?
                    //this.InternalRows.InternalItems.Added +=
                    //    delegate
                    //    {
                    //        this.HTMLTargetRef.requestAnimationFrame +=
                    //            delegate
                    //            {
                    //                ColumnUpdateToHorizontalResizerScroll();
                    //            };

                    //    };

                    this.InternalAtAfterVisibleChanged +=
                        delegate
                        {
                            this.HTMLTargetRef.requestAnimationFrame +=
                                delegate
                                {
                                    ColumnUpdateToHorizontalResizerScroll();
                                };

                        };
                    #endregion

                    #region CompensateFor ZeroHorizontalResizerDrag DragStop
                    Action<DragHelper> CompensateFor =
                        Target =>
                        {
                            var __X = 0;
                            Target.DragStart +=
                                delegate
                                {
                                    __X = Target.Position.X;
                                };

                            Target.DragStop +=
                                delegate
                                {
                                    ColumnHorizontalResizerDrag.Position.X +=
                                        Target.Position.X - __X;

                                    ColumnUpdateToHorizontalResizerScroll();
                                };
                        };

                    CompensateFor(ZeroHorizontalResizerDrag);
                    #endregion

                    #region Reposition
                    Action Reposition =
                        delegate
                        {
                            var RepositionStopwatch = Stopwatch.StartNew();


                            var x = ZeroHorizontalResizerDrag.Position.X - 1;

                            if (!this.RowHeadersVisible)
                            {
                                x = -4;
                            }

                            x -= this.InternalScrollContainerElement.scrollLeft;

                            for (int i = 0; i <= NewIndex; i++)
                            {
                                //x += this.InternalColumns.InternalItems[i].Width;

                                var CandidateColumn = this.InternalColumns.InternalItems[i];


                                // X:\jsc.svn\examples\javascript\forms\Test\TestDataGridPadding\TestDataGridPadding\ApplicationControl.cs
                                if (CandidateColumn.Visible)
                                    x += CandidateColumn.Width + 1;
                            }

                            ColumnHorizontalResizerDrag.Position = new Point(x, 0);

                            ColumnUpdateToHorizontalResizerScroll();

                            // what takes here half a sec?
                            // 1737ms event: Reposition { Index = 0, ElapsedMilliseconds = 447 } 

                            // report slow. 60 is the new slow
                            //if (RepositionStopwatch.ElapsedMilliseconds > 10)
                            if (RepositionStopwatch.ElapsedMilliseconds > 60)
                                Console.WriteLine("reposition " + new { SourceColumn.Index, RepositionStopwatch.ElapsedMilliseconds });
                        };

                    // are we adding columns in bulk? cant have reflow yet
                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201402/20140205
                    if (!InternalDataSourceBusy)
                        Reposition();


                    this.InternalScrollContainerElement.onscroll +=
                      e =>
                      {
                          Reposition();
                      };

                    // tested by
                    // X:\jsc.svn\examples\javascript\Test\TestNoZeroColumnHeaderNoScrollbarDateDataGrid\TestNoZeroColumnHeaderNoScrollbarDateDataGrid\ApplicationControl.cs
                    InternalRowHeadersVisibleChanged +=
                       delegate
                       {
                           Reposition();
                       };

                    for (int i = 0; i <= NewIndex; i++)
                    {
                        var item = this.InternalColumns.InternalItems[i];

                        item.InternalWidthChanged +=
                            delegate
                            {
                                if (InternalDataSourceBusy)
                                    return;

                                Reposition();

                            };
                    }
                    #endregion

                    #region ColumnHorizontalResizerDrag DragStart
                    var __DragStartX = 0;

                    ColumnHorizontalResizerDrag.DragStart +=
                        delegate
                        {

                            Native.Document.body.style.cursor = DOM.IStyle.CursorEnum.move;
                            //((IHTMLElement)SourceColumn.ColumnHorizontalResizer.firstChild).style.backgroundColor = JSColor.Blue;

                            __DragStartX = ColumnHorizontalResizerDrag.Position.X;
                        };

                    ColumnHorizontalResizerDrag.DragStop +=
                            delegate
                            {
                                //                                 { Width = 115, cwidth = 1045 } view-source:27892

                                // view-source:27892
                                //{ Width = 1045, cwidth = 1975 } 

                                Native.Document.body.style.cursor = DOM.IStyle.CursorEnum.auto;
                                //((IHTMLElement)SourceColumn.ColumnHorizontalResizer.firstChild).style.backgroundColor = this.InternalBackgroundColor.ToString();
                                //((IHTMLElement)SourceColumn.ColumnHorizontalResizer.firstChild).style.backgroundColor = "";
                                //((IHTMLElement)SourceColumn.ColumnHorizontalResizer.firstChild).style.backgroundColor = "yellow";
                                //SourceColumn.ColumnHorizontalResizer.style.backgroundColor = "red";

                                var ColumnHorizontalResizerDragNewValue = SourceColumn.Width + ColumnHorizontalResizerDrag.Position.X - __DragStartX;
                                Console.WriteLine(new { SourceColumn.Width, ColumnHorizontalResizerDragNewValue });

                                SourceColumn.Width = ColumnHorizontalResizerDragNewValue;
                                InternalAutoSizeWhenFill();
                            };


                    ColumnHorizontalResizerDrag.DragMove +=
                        delegate
                        {
                            ColumnUpdateToHorizontalResizerScroll();

                        };
                    #endregion


                    #region ColumnHorizontalResizer ondblclick AutoResizeColumn
                    SourceColumn.ColumnHorizontalResizer.onmousedown +=
                        e =>
                        {
                            if (e.MouseButton == IEvent.MouseButtonEnum.Middle)
                            {
                                e.preventDefault();
                                e.stopPropagation();

                                this.AutoResizeColumn(SourceColumn.Index, ObeyAutoSizeMode: false);
                                InternalAutoSizeWhenFill();

                            }
                        };

                    SourceColumn.ColumnHorizontalResizer.ondblclick +=
                        delegate
                        {
                            this.AutoResizeColumn(SourceColumn.Index, ObeyAutoSizeMode: false);
                            InternalAutoSizeWhenFill();
                        };
                    #endregion
#endif

                    bool InternalAutoResizeColumnBuzy = false;

                    #region InternalAutoResizeColumn

                    //Console.WriteLine("add InternalAutoResizeColumn");
                    this.InternalAutoResizeColumn +=
                        (SourceColumnIndex, ObeyAutoSizeMode) =>
                        {
                            //Console.WriteLine("at InternalAutoResizeColumn");

                            if (InternalAutoResizeColumnBuzy)
                                return;


                            if (SourceColumnIndex != SourceColumn.Index)
                                return;

                            var rows = this.InternalRows.InternalItems.Source;

                            var InternalAutoResizeColumnStopwatch = Stopwatch.StartNew();

                            // InternalAutoSize { Count = 33, cindex = -1 }
                            //Console.WriteLine(
                            //    new { this.Name }
                            //    + " InternalAutoResizeColumn "
                            //    + new
                            //    {
                            //        RowCount = rows.Count,
                            //        SourceColumnIndex,

                            //        // are we even supposed to do autoresize?
                            //        SourceColumn.AutoSizeMode
                            //    }
                            //);



                            #region Fill last column
                            if (this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill)
                            {
                                var FillColumn = InternalGetVisibleColumns().LastOrDefault();

                                if (FillColumn != null)
                                    if (SourceColumnIndex == FillColumn.Index)
                                    {
                                        //Console.WriteLine("InternalAutoResizeColumn " + new { FillColumn.Index, FillColumn.Name });

                                        //SourceColumn.le
                                        var SourceColumnLeft = InternalGetVisibleColumns()
                                            .Where(c => c.Index < FillColumn.Index)
                                            .Select(c => c.Width)
                                            .Sum();

                                        var ZeroRight = (ZeroHorizontalResizerDrag.Position.X + 4);


                                        // X:\jsc.svn\examples\javascript\forms\FormsHistoricBindingSourcePosition\FormsHistoricBindingSourcePosition\ApplicationControl.cs
                                        // tested by?
                                        if (!this.RowHeadersVisible)
                                        {
                                            // we are missing the left border!
                                            SourceColumnLeft = 0;
                                            ZeroRight = -4;
                                        }


                                        // { cindex = 0, w = 0, all = 1600, WidthByFill = 1600 } 

                                        var all = this.InternalScrollContainerElement.clientWidth;

                                        var WidthByFill = all - SourceColumnLeft - ZeroRight - 5;

                                        WidthByFill -= 1;

                                        //Console.WriteLine(
                                        //    " InternalAutoResizeColumn Fill "
                                        //    + new
                                        //    {
                                        //        SourceColumnIndex,
                                        //        SourceColumnLeft,
                                        //        value = ZeroRight,
                                        //        all,
                                        //        WidthByFill
                                        //    }

                                        //    );

                                        //{ cindex = 0, w = 0, value = 99, all = 753, WidthByFill = 654 } 

#if FHR
                                        __DragStartX = ColumnHorizontalResizerDrag.Position.X + (WidthByFill - SourceColumn.Width);
#endif

                                        InternalAutoResizeColumnBuzy = true;
                                        SourceColumn.Width = Math.Max(20, WidthByFill);
                                        InternalAutoResizeColumnBuzy = false;

                                        return;
                                    }
                            }
                            #endregion



                            if (SourceColumnIndex < 0)
                                return;

                            if (SourceColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.None)
                            {
                                if (ObeyAutoSizeMode)
                                    return;
                            }


                            //Console.WriteLine("before max");
                            #region SetColumnWidth

                            //1268ms before max view-source:35829
                            //1707ms after max 

                            // we should only look at currently visible rows?
                            var WidthByRowsInThisColumn = rows.Take(16).Max(
                                rr =>
                                {
                                    //1774ms at rr view-source:35829
                                    //2273ms at rr 

                                    //Console.WriteLine("enter rr");

                                    //                                    33736ms before max view-source:35829
                                    //33736ms enter rr view-source:35829
                                    //34202ms exit rr { value = 228 } 

                                    __DataGridViewCell cc = rr.Cells[SourceColumnIndex];

                                    //Console.WriteLine("got cc");

                                    //Console.WriteLine("InternalAutoSize " + new { rows.Count, cindex, cc.InternalContent.offsetWidth });

                                    //2717ms got cc view-source:35829
                                    //3165ms exit rr { value = 228 } 

                                    var s = Stopwatch.StartNew();

                                    // !!! accessing DOM is expensive!
                                    var value = cc.InternalTableColumn_div_span.offsetWidth;

                                    //2717ms got cc view-source:35829
                                    //3165ms exit rr { value = 228 } 

                                    if (s.ElapsedMilliseconds > 10)
                                        Console.WriteLine("got offsetWidth in " + new { s.ElapsedMilliseconds });

                                    return value;
                                }
                            );
                            //Console.WriteLine("after max");


                            WidthByRowsInThisColumn = Math.Max(WidthByRowsInThisColumn, this.InternalColumns.InternalItems[SourceColumnIndex].InternalContent.offsetWidth);
                            if (WidthByRowsInThisColumn == 0)
                            {
                                // no DOM?
                                //Console.WriteLine("InternalAutoSize skipped");
                                return;
                            }

                            // extra padding?
                            WidthByRowsInThisColumn += 8 + 24;

                            //Console.WriteLine("InternalAutoSize" + new { SourceColumn.Width, cwidth = WidthByRowsInThisColumn });

#if FHR
                            __DragStartX = ColumnHorizontalResizerDrag.Position.X + (WidthByRowsInThisColumn - SourceColumn.Width);
#endif

                            var NewWidth = Math.Max(20, WidthByRowsInThisColumn);



                            // 15248ms { Name = dataGridView2 }InternalAutoResizeColumn { RowCount = 2, SourceColumnIndex = 0, NewWidth = 154, ElapsedMilliseconds = 2 } 
                            // 14818ms { Name = dataGridView2 } InternalAutoResizeColumn { RowCount = 2, SourceColumnIndex = 2, NewWidth = 120, ElapsedMilliseconds = 1 } 

                            // 1745ms event: { Name = dataGridView1 } InternalAutoResizeColumn { RowCount = 9, SourceColumnIndex = 1, NewWidth = 260, ElapsedMilliseconds = 447 } 


                            // report only slow https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201404/20140413

                            if (InternalAutoResizeColumnStopwatch.ElapsedMilliseconds > 20)
                                Console.WriteLine(
                                    "event: " +
                                    new { this.Name }
                                    + " InternalAutoResizeColumn " + new
                                    {
                                        RowCount = rows.Count,
                                        SourceColumnIndex,
                                        NewWidth,
                                        InternalAutoResizeColumnStopwatch.ElapsedMilliseconds
                                    });

                            // why does this cost us 600ms?
                            SourceColumn.Width = NewWidth;
                            #endregion

                        };
                    #endregion





#if FHR
                    if (ColumnAdded != null)
                        ColumnAdded(this, new DataGridViewColumnEventArgs((DataGridViewColumn)(object)SourceColumn));
#endif

                    // 1135ms { Name = dataGridView1 } InternalColumns Added { Index = 29, SourceColumnStopwatch = 7 } 
                    // 888 ??
                    // 244382ms event: dataGridView2 set DataSource columns { SourceDataTableColumnCount = 7, ElapsedMilliseconds = 869 } 
                    // 2135ms { Name = dataGridView2 } InternalColumns Added { Index = 0, Name = , SourceColumnStopwatch = 123 } 

                    //120:5572ms { Name = dataGridView2 } InternalColumns Added { Index = 1, SourceColumnStopwatch = 8 } 

                    // 112:371747ms { Name = dataGridView1 } InternalColumns Added { Index = 1, SourceColumnStopwatch = 31 } 

                    if (SourceColumnStopwatch.ElapsedMilliseconds > 40)
                        Console.WriteLine(
                            new { this.Name }
                            + " InternalColumns Added " + new
                            {
                                SourceColumn.Index,
                                SourceColumnStopwatch = SourceColumnStopwatch.ElapsedMilliseconds
                            });

                };

            #endregion


            new IStyle(__RowsTable_css_td)
            {
                width = "100%",
                height = "21px",
                position = IStyle.PositionEnum.relative
            };






            #region DataGridNewRow
            {
                var DataGridNewRow = new IHTMLImage("assets/ScriptCoreLib.Windows.Forms/DataGridNewRow.png");
                var xDataGridViewCellIsInEditMode = new XAttribute("DataGridViewCellIsInEditMode", global::System.Convert.ToString(true));

                var __RowsTable_css_td_after = __RowsTable_css
                   [IHTMLElement.HTMLElementEnum.tbody]
                   .last[IHTMLElement.HTMLElementEnum.tr]
                    //[e => e.getAttribute("DataGridViewCellSelected") == true]
                   [IHTMLElement.HTMLElementEnum.td]
                   .after;

                __RowsTable_css_td_after.style.position = IStyle.PositionEnum.absolute;
                __RowsTable_css_td_after.style.left = "12px";
                __RowsTable_css_td_after.style.top = "0px";
                __RowsTable_css_td_after.style.right = "0";
                __RowsTable_css_td_after.style.height = "21px";
                __RowsTable_css_td_after.content = "";
                __RowsTable_css_td_after.style.backgroundPosition = "left center";
                DataGridNewRow.ToBackground(__RowsTable_css_td_after.style, false);
            }
            #endregion

            #region DataGridEditRow
            {
                var DataGridEditRow = new IHTMLImage("assets/ScriptCoreLib.Windows.Forms/DataGridEditRow.png");
                var xDataGridViewCellIsInEditMode = new XAttribute("DataGridViewCellIsInEditMode", global::System.Convert.ToString(true));

                var __RowsTable_css_td_after = __RowsTable_css
                   [IHTMLElement.HTMLElementEnum.tbody]
                   [IHTMLElement.HTMLElementEnum.tr]
                    //[e => e.getAttribute("DataGridViewCellSelected") == true]
                   [xDataGridViewCellIsInEditMode]
                   [IHTMLElement.HTMLElementEnum.td]
                   .after;

                __RowsTable_css_td_after.style.position = IStyle.PositionEnum.absolute;
                __RowsTable_css_td_after.style.left = "12px";
                __RowsTable_css_td_after.style.top = "0px";
                __RowsTable_css_td_after.style.right = "0";
                __RowsTable_css_td_after.style.height = "21px";
                __RowsTable_css_td_after.content = "";
                __RowsTable_css_td_after.style.backgroundPosition = "left center";
                DataGridEditRow.ToBackground(__RowsTable_css_td_after.style, false);
            }
            #endregion

            #region DataGridFocusRow
            {
                var xDataGridViewCellSelected = new XAttribute("DataGridViewCellSelected", global::System.Convert.ToString(true));
                var DataGridFocusRow = new IHTMLImage("assets/ScriptCoreLib.Windows.Forms/DataGridFocusRow.png");
                var __RowsTable_css_td_before = __RowsTable_css
                    [IHTMLElement.HTMLElementEnum.tbody]
                    [IHTMLElement.HTMLElementEnum.tr]
                    //[e => e.getAttribute("DataGridViewCellSelected") == true]
                    [xDataGridViewCellSelected]
                    [IHTMLElement.HTMLElementEnum.td]
                    .before;


                __RowsTable_css_td_before.style.position = IStyle.PositionEnum.absolute;
                __RowsTable_css_td_before.style.left = "4px";
                __RowsTable_css_td_before.style.top = "0px";
                __RowsTable_css_td_before.style.right = "0";
                __RowsTable_css_td_before.style.height = "21px";
                __RowsTable_css_td_before.content = "";
                __RowsTable_css_td_before.style.backgroundPosition = "left center";
                DataGridFocusRow.ToBackground(__RowsTable_css_td_before.style, false);
            }
            #endregion

            #region InitializeZeroColumnCell

            // we need to reduce this!
            Action<__DataGridViewRow> InitializeZeroColumnCell =
                SourceRow =>
                {
                    #region InternalTableColumn
                    var __tr = default(IHTMLTableRow);


                    if (InternalPrerenderZeroRows.Count > 0)
                    {
                        // datasource already prepped a row for us
                        __tr = InternalPrerenderZeroRows.Dequeue();
                        __tr.Clear();
                    }
                    else
                    {
                        __tr = new IHTMLTableRow { };

                        // Failed to execute 'insertBefore' on 'Node': The new child element is null. 
                        if (InternalNewRow != null)
                        {
                            __RowsTableBody.insertBefore(__tr, InternalNewRow.InternalZeroColumnTableRow);
                        }
                        else
                        {
                            __RowsTableBody.appendChild(__tr);
                        }
                    }

                    SourceRow.InternalZeroColumnTableRow = __tr;


                    //var __tr = __RowsTableBody.AddRow();
                    var InternalTableColumn = __tr.AddColumn();
                    #endregion

                    // X:\jsc.svn\examples\javascript\forms\FormsGridCellStyle\FormsGridCellStyle\Application.cs

                    InternalTableColumn.title = new { SourceRow.Index }.ToString();

                    //#region AtInternalHeightChanged
                    //Action AtInternalHeightChanged = delegate
                    //{
                    //    //c1.style.height = (SourceRow.InternalHeight - 1) + "px";
                    //    c1img.style.height = (SourceRow.InternalHeight - 1) + "px";
                    //    c2img.style.height = (SourceRow.InternalHeight - 1) + "px";

                    //    c1contentcrel.style.height = (SourceRow.InternalHeight - 1) + "px";
                    //    __tr.style.height = SourceRow.InternalHeight + "px";
                    //};

                    //AtInternalHeightChanged();
                    //SourceRow.InternalHeightChanged += AtInternalHeightChanged;
                    //#endregion
                };
            #endregion

            InitializeZeroColumnCell(InternalNewRow);

            Console.WriteLine("new DataGridView() after InitializeZeroColumnCell");


            #region InternalAutoResizeColumn
            var t = new global::System.Windows.Forms.Timer();
            t.Interval = 100;
            t.Tick +=
                delegate
                {
                    t.Stop();

                    InternalAutoResizeAll();
                };
            #endregion

            this.InternalRowHeadersVisibleChanged +=
                delegate
                {
                    InternalAutoSizeWhenFill();
                };

            #region ClientSizeChanged
            // whatif we are in autosize mode?
            this.ClientSizeChanged +=
                delegate
                {

                    InternalAutoSizeWhenFill();
                };
            #endregion

            Console.WriteLine("new DataGridView() before InternalRows.Added");


            #region InternalRows.Added

            this.InternalRows.InternalItems.Added +=
                  (SourceRow, CurrentRowIndex) =>
                  {
                      if (SourceRow == InternalNewRow)
                      {
                          // do we have a test for readding rows?

                          SourceRow.InternalTableRow.AttachTo(__ContentTableBody);
                          SourceRow.InternalZeroColumnTableRow.AttachTo(__RowsTableBody);

                      }

                      if (SourceRow.InternalTableRow != null)
                          return;

                      //Console.WriteLine("InternalRows Added");

                      if (InternalNewRow == null)
                      {
                          // when is this happening?
                          SourceRow.InternalTableRow = __ContentTableBody.AddRow();
                      }
                      else
                      {
                          // how much time are we spending per row?
                          // what about bulk entry?
                          // could we adapt a preexisting table?

                          // how much time do we spend on moving the new row thingy?




                          if (InternalPrerenderRows.Count > 0)
                          {
                              // datasource already prepped a row for us
                              SourceRow.InternalTableRow = InternalPrerenderRows.Dequeue();
                              SourceRow.InternalTableRow.Clear();
                          }
                          else
                          {
                              SourceRow.InternalTableRow = new IHTMLTableRow();


                              // Uncaught NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node. 
                              if (InternalNewRow.InternalTableRow.parentNode == null)
                              {
                                  // where is our new row?
                                  __ContentTableBody.appendChild(InternalNewRow.InternalTableRow);
                                  InternalNewRow.InternalZeroColumnTableRow.AttachTo(__RowsTableBody);
                              }


                              __ContentTableBody.insertBefore(
                                  // is it part of the rows still?
                                  SourceRow.InternalTableRow,
                                  InternalNewRow.InternalTableRow

                                );
                          }

                          //Console.WriteLine("InternalRows reposition InternalNewRow");

                          // make sure the RowIndex -1 is the last element
                          this.InternalRows.InternalItems.Source.Remove(InternalNewRow);
                          this.InternalRows.InternalItems.Source.Add(InternalNewRow);

                          //Console.WriteLine("InternalRows reposition InternalNewRow done");
                      }



                      // disabled for now, until we get a newer test
                      //#region AtInternalHeightChanged
                      //Action AtInternalHeightChanged = delegate
                      //{
                      //    SourceRow.InternalTableRow.style.height = SourceRow.InternalHeight + "px";
                      //};

                      //AtInternalHeightChanged();
                      //SourceRow.InternalHeightChanged += AtInternalHeightChanged;
                      //#endregion


                      CreateMissingCells(SourceRow);



                      if (!InternalSkipAutoSize)
                          if (!InternalDataSourceBusy)
                              if (this.AutoSizeColumnsMode != DataGridViewAutoSizeColumnsMode.None)
                              {
                                  //Console.WriteLine("a new row was added, auto resize?");
                                  t.Stop();
                                  t.Start();
                              }





                      InitializeZeroColumnCell(SourceRow);

                  };
            #endregion

            #region InternalRows Removed
            this.InternalRows.InternalItems.Removed +=
                (SourceRow, i) =>
                {
                    //Console.WriteLine("InternalRows Removed");

                    SourceRow.InternalTableRow.Orphanize();
                    SourceRow.InternalZeroColumnTableRow.Orphanize();

                    // raise any events
                };
            #endregion


            __DataGridViewRow PendingNewRow = null;

            #region UserAddedRow
            this.InternalRaiseCellBeginEdit =
                (SourceCell) =>
                {
                    //Console.WriteLine("InternalRaiseCellBeginEdit " + new { SourceCell.ColumnIndex, SourceCell.OwningRow.Index });

                    var SourceRow = SourceCell.InternalOwningRow;

                    if (SourceRow.IsNewRow)
                    {
                        var n = new __DataGridViewRow();
                        InternalNewRow = null;
                        PendingNewRow = SourceRow;

                        InternalSkipAutoSize = true;
                        this.InternalRows.InternalItems.Source.Add(n);
                        InternalSkipAutoSize = false;

                        InternalNewRow = n;

                        if (this.UserAddedRow != null)
                            this.UserAddedRow(this, new DataGridViewRowEventArgs((DataGridViewRow)(object)SourceRow));
                    }


                    if (this.CellBeginEdit != null)
                        this.CellBeginEdit(this,
                            new DataGridViewCellCancelEventArgs(SourceCell.ColumnIndex, SourceRow.Index)
                        );
                };
            #endregion

            #region CellEndEdit

            this.InternalRaiseCellValueChanged =
                (SourceCell) =>
                {
                    var SourceRow = SourceCell.InternalOwningRow;

                    if (SourceRow.IsNewRow)
                    {
                        // if there is now content on the new row then we need another new row downt we?
                        return;
                    }

                    //Console.WriteLine("InternalRaiseCellValueChanged " + new { SourceCell.ColumnIndex, SourceCell.OwningRow.Index });


                    if (PendingNewRow == SourceRow)
                        PendingNewRow = null;

                    if (this.CellValueChanged != null)
                        this.CellValueChanged(this,
                            new DataGridViewCellEventArgs(SourceCell.ColumnIndex, SourceCell.OwningRow.Index)
                        );
                };

            this.InternalRaiseCellEndEdit =
                (SourceCell) =>
                {
                    //Console.WriteLine("InternalRaiseCellEndEdit " + new { SourceCell.ColumnIndex, SourceCell.OwningRow.Index });

                    var SourceRow = SourceCell.InternalOwningRow;

                    #region  PendingNewRow
                    if (PendingNewRow == SourceRow)
                    {
                        var ColumnIndex = SourceCell.ColumnIndex;
                        var RowIndex = SourceRow.Index;

                        this.InternalRows.InternalItems.Source.Remove(SourceRow);

                        SourceRow.InternalTableRow.Orphanize();
                        SourceRow.InternalZeroColumnTableRow.Orphanize();

                        //if (this.UserDeletedRow != null)
                        //    this.UserDeletedRow(this, new DataGridViewRowEventArgs((DataGridViewRow)(object)SourceRow));

                        PendingNewRow = null;

                        this.InternalRows.InternalItems.Source[RowIndex].InternalCells.InternalItems[ColumnIndex].InternalTableColumn_div.focus();
                        //this[SourceCell.ColumnIndex, SourceRow.Index].Selected = true;
                    }
                    #endregion


                    if (this.CellEndEdit != null)
                        this.CellEndEdit(this,
                            new DataGridViewCellEventArgs(SourceCell.ColumnIndex, SourceRow.Index)
                        );
                };
            #endregion



            this.GridColor = global::System.Drawing.Color.FromArgb(0xa0, 0xa0, 0xa0);
            this.Height = 400;


            // 2901ms exit DataGridView .ctor { ElapsedMilliseconds = 923 } 
            // 25:584ms event: exit DataGridView .ctor { ElapsedMilliseconds = 525 } 
            Console.WriteLine("event: new DataGridView() " + new { DataGridViewConstructorStopwatch.ElapsedMilliseconds });
        }
 static void AttachImageToDocument(IHTMLImage img)
 {
     img.AttachToDocument();
 }
            // X:\jsc.svn\examples\glsl\future\GLSLShaderToyPip\GLSLShaderToyPip\Application.cs
            public EffectPass(
                AudioContext wa = null,
                gl gl = null,

                string precission = null,
                bool supportDerivatives = false,
                RefreshTexturThumbailDelegate callback = null,
                object obj = null,
                bool forceMuted = false,
                bool forcePaused = false,


                // createQuadVBO
                // ARRAY_BUFFER
                WebGLBuffer quadVBO = null,
                GainNode outputGainNode = null
                )
            {
                //new IHTMLPre { "enter EffectPass" }.AttachToDocument();


                // used by?
                var mFrame = 0;






                // http://math.hws.edu/eck/cs424/notes2013/19_GLSL.html
                // http://stackoverflow.com/questions/10079368/how-would-i-do-environment-reflection-in-webgl-without-using-a-library-like-thre
                this.MakeHeader_Image = delegate
                {
                    #region MakeHeader_Image
                    //new IHTMLPre { "enter MakeHeader_Image" }.AttachToDocument();


                    var header = precission;
                    var headerlength = 3;

                    if (supportDerivatives) { header += "#extension GL_OES_standard_derivatives : enable\n"; headerlength++; }

                    header += "uniform vec3      iResolution;\n" +
                              "uniform float     iGlobalTime;\n" +
                              "uniform float     iChannelTime[4];\n" +
                              "uniform vec4      iMouse;\n" +
                              "uniform vec4      iDate;\n" +
                              "uniform float     iSampleRate;\n" +
                              "uniform vec3      iChannelResolution[4];\n";

                    // not to be used by the hosted shader, but by our code in the middle on the gpu.
                    // gpu code injection. first take.
                    //"uniform float     fZoom;\n";

                    headerlength += 7;

                    for (var i = 0; i < mInputs.Length; i++)
                    {
                        var inp = mInputs[i];

                        // X:\jsc.svn\examples\javascript\chrome\apps\WebGL\ChromeShaderToyVRCardboardGrid\ChromeShaderToyVRCardboardGrid\Application.cs

                        //if (inp != null && inp.mInfo.mType == "cubemap")
                        if (inp is samplerCube)
                        {
                            new IHTMLPre { "add MakeHeader_Image samplerCube" }.AttachToDocument();

                            var tex = new WebGLTexture(gl);

                            // http://stackoverflow.com/questions/10079368/how-would-i-do-environment-reflection-in-webgl-without-using-a-library-like-thre
                            // view-source:https://www.shadertoy.com/js/effect.js

                            // um can there be only one samplerCube?
                            gl.activeTexture(gl.TEXTURE0);
                            //gl.enable(gl.TEXTURE_CUBE_MAP);
                            gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
                            //gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, (int)gl.CLAMP_TO_EDGE);
                            //gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, (int)gl.CLAMP_TO_EDGE);
                            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, (int)gl.LINEAR);
                            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, (int)gl.LINEAR);

                            //var cube0 = new IHTMLImage[] {
                            //        new HTML.Images.FromAssets.cube02_0(),
                            //        new HTML.Images.FromAssets.cube02_1(),
                            //        new HTML.Images.FromAssets.cube02_2(),
                            //        new HTML.Images.FromAssets.cube02_3(),
                            //        new HTML.Images.FromAssets.cube02_4(),
                            //        new HTML.Images.FromAssets.cube02_5()
                            //};

                            //public const uint TEXTURE_CUBE_MAP_POSITIVE_X = 34069;
                            //public const uint TEXTURE_CUBE_MAP_NEGATIVE_X = 34070;
                            //public const uint TEXTURE_CUBE_MAP_POSITIVE_Y = 34071;
                            //public const uint TEXTURE_CUBE_MAP_NEGATIVE_Y = 34072;
                            //public const uint TEXTURE_CUBE_MAP_POSITIVE_Z = 34073;
                            //public const uint TEXTURE_CUBE_MAP_NEGATIVE_Z = 34074;

                            //rawArrays: texture bound to texture unit 0 is not renderable.It maybe non - power - of - 2 and have incompatible texture filtering or is not 'texture complete'.


                            new IHTMLPre { "about to load TEXTURE_CUBE_MAP" }.AttachToDocument();

                            var cube0 = new IHTMLImage[] {
                                    new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_px(),
                                    new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_nx(),

                                    new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_py(),
                                    new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_ny(),


                                    new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_pz(),
                                    new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_nz()
                            };

                            cube0.WithEachIndex(
                                (pendingimg, index) =>
                                {
                                    pendingimg.InvokeOnComplete(
                                        img =>
                                        {
                                            gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
                                            //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
                                            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
                                            gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + (uint)index, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);

                                            new IHTMLPre { "add MakeHeader_Image samplerCube TEXTURE_CUBE_MAP_POSITIVE_X + " + new { index } }.AttachToDocument();

                                            if (index == 5)
                                            {
                                                new IHTMLPre { "add MakeHeader_Image samplerCube activeTexture  " }.AttachToDocument();

                                                //  samplerCube iChannel0; = 0 = TEXTURE0
                                            }

                                            // https://code.google.com/p/opengles-book-samples/source/browse/trunk/WebGL/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.html?r=5
                                            // http://stackoverflow.com/questions/31665132/gl-invalid-operation-caused-by-samplercube
                                            // http://forum.processing.org/two/discussion/7039/samplercube-and-ambient-reflection


                                        }
                                    );
                                }
                            );


                            header += "uniform samplerCube iChannel" + i + ";\n";
                        }
                        else
                        {
                            //new IHTMLPre { "add MakeHeader_Image sampler2D" }.AttachToDocument();
                            header += "uniform sampler2D iChannel" + i + ";\n";
                        }

                        // dont need it?
                        headerlength++;
                    }



                    // rror CreateShader {{ infoLog = ERROR: 0:250: 'assign' :  l-value required "gl_FragCoord" (can't modify gl_FragCoord)
                    //				ERROR: 0:251: 'assign' :  l - value required "gl_FragCoord"(can't modify gl_FragCoord)
                    //}}
                    // error CreateShader {{ infoLog = ERROR: 0:253: '=' :  cannot convert from 'FragCoord mediump 4-component vector of float' to 'highp 2-component vector of float'

                    var mImagePassFooter = @"
void main( void )
{
	vec4 color = gl_FragColor;


color.a = 1.0;

	mainImage( color, gl_FragCoord.xy );
					

	gl_FragColor = color;
}
";
                    #endregion


                    this.NewShader_Image = (fs) =>
                    {
                        #region NewShader_Image
                        //new IHTMLPre { "enter NewShader_Image" }.AttachToDocument();
                        var shaderCode = fs.ToString();

                        // is that it?
                        var vsSource = "attribute vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";

                        var fsSource = header + shaderCode + mImagePassFooter;

                        this.xCreateShader = CreateShader(gl, vsSource, fsSource, false);

                        #endregion

                        var vbo = new WebGLBuffer(gl);



                        #region calledby
                        //EffectPass.Paint_Image(effect.js:724)
                        //EffectPass.Paint(effect.js:1038)
                        //Effect.Paint(effect.js:1247)
                        //renderLoop2(pgWatch.js:404)
                        //ShaderToy.startRendering(pgWatch.js:420)
                        //watchInit(pgWatch.js:1386)
                        //onload(Xls3WS: 78)
                        #endregion
                        this.Paint_Image = (time, mouseOriX, mouseOriY, mousePosX, mousePosY, zoom) =>
                        {
                            var mProgram = xCreateShader.mProgram;


                            var xres = gl.canvas.width * zoom;
                            var yres = gl.canvas.height * zoom;

                            #region Paint_Image

                            //new IHTMLPre { "enter Paint_Image" }.AttachToDocument();

                            // this is enough to do pip to bottom left, no need to adjust vertex positions even?
                            gl.viewport(0, 0, (int)xres, (int)yres);

                            // useProgram: program not valid
                            gl.useProgram(mProgram);

                            // uniform4fv
                            var uniform4fv_mouse = new[] { mousePosX, mousePosY, mouseOriX, mouseOriY };

                            // X:\jsc.svn\examples\glsl\future\GLSLShaderToyPip\GLSLShaderToyPip\Application.cs
                            //gl.getUniformLocation(mProgram, "fZoom").With(fZoom => gl.uniform1f(fZoom, zoom));


                            var l2 = gl.getUniformLocation(mProgram, "iGlobalTime"); if (l2 != null) gl.uniform1f(l2, time);
                            var l3 = gl.getUniformLocation(mProgram, "iResolution"); if (l3 != null) gl.uniform3f(l3, xres, yres, 1.0f);
                            var l4 = gl.getUniformLocation(mProgram, "iMouse"); if (l4 != null) gl.uniform4fv(l4, uniform4fv_mouse);

                            // X:\jsc.svn\examples\javascript\chrome\apps\WebGL\synergy\SimpleDigitalClock\SimpleDigitalClock\Application.cs
                            // uniform vec4      iDate;                 // (year, month, day, time in seconds)
                            // http://bytes.com/topic/c-sharp/answers/258829-time-elapsed-since-midnight-c
                            var now = DateTime.Now;
                            //var sinceMidnight = now - DateTime.Today;
                            var sinceMidnight = now - now.Date;

                            var uniform4fv_dates = new float[] { now.Year, now.Month, now.Day, (float)sinceMidnight.TotalSeconds };
                            var l7 = gl.getUniformLocation(mProgram, "iDate"); if (l7 != null) gl.uniform4fv(l7, uniform4fv_dates);

                            //var l9 = gl.getUniformLocation(this.mProgram, "iSampleRate"); if (l9 != null) gl.uniform1f(l9, this.mSampleRate);

                            //var ich0 = gl.getUniformLocation(mProgram, "iChannel0"); if (ich0 != null) gl.uniform1i(ich0, 0);
                            //var ich1 = gl.getUniformLocation(mProgram, "iChannel1"); if (ich1 != null) gl.uniform1i(ich1, 1);
                            //var ich2 = gl.getUniformLocation(mProgram, "iChannel2"); if (ich2 != null) gl.uniform1i(ich2, 2);
                            //var ich3 = gl.getUniformLocation(mProgram, "iChannel3"); if (ich3 != null) gl.uniform1i(ich3, 3);


                            // what if there are other textures too?
                            // X:\jsc.svn\examples\javascript\chrome\apps\WebGL\ChromeWebGLFrameBuffer\ChromeWebGLFrameBuffer\Application.cs

                            //for (var i = 0; i < mInputs.Length; i++)
                            //{
                            //	var inp = mInputs[i];

                            //	gl.activeTexture((uint)(gl.TEXTURE0 + i));

                            //	if (inp == null)
                            //	{
                            //		gl.bindTexture(gl.TEXTURE_2D, null);
                            //	}
                            //}

                            var times = new[] { 0.0f, 0.0f, 0.0f, 0.0f };
                            var l5 = gl.getUniformLocation(mProgram, "iChannelTime");
                            if (l5 != null) gl.uniform1fv(l5, times);

                            var resos = new float[12] { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
                            var l8 = gl.getUniformLocation(mProgram, "iChannelResolution");
                            if (l8 != null) gl.uniform3fv(l8, resos);




                            // using ?
                            var vec2pos = (uint)gl.getAttribLocation(mProgram, "pos");
                            //gl.bindBuffer(gl.ARRAY_BUFFER, quadVBO);
                            gl.bindBuffer(gl.ARRAY_BUFFER, vbo);


                            #region vertices
                            float left = -1.0f;
                            // y reversed?
                            float bottom = -1.0f;
                            float right = 1.0f;
                            float top = 1.0f;

                            var fvertices =
                                new float[]
                                {
                                    // left top
                                    left, bottom,

                                    // right top
                                    //right, -1.0f,
                                    right, bottom,

                                    // left bottom
                                    left, top,

                                    // right top
                                    //right, -1.0f,
                                    right, bottom,

                                    // right bottom
                                    //right, 1.0f,
                                    right, top,

                                    // left bottom
                                    left,top
                                };

                            #endregion
                            gl.bufferData(gl.ARRAY_BUFFER, fvertices, gl.STATIC_DRAW);

                            gl.vertexAttribPointer(vec2pos, 2, gl.FLOAT, false, 0, 0);
                            gl.enableVertexAttribArray(vec2pos);


                            //var iChannel0 = gl.getUniformLocation(mProgram, "iChannel0");



                            // GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to render with no buffer attached to enabled attribute 1
                            gl.drawArrays(gl.TRIANGLES, 0, 6);


                            // first frame is now visible
                            gl.disableVertexAttribArray(vec2pos);
                            gl.bindBuffer(gl.ARRAY_BUFFER, null);
                            #endregion

                            mFrame++;

                        };
                    };
                };

            }
Exemple #31
0
 public static SpriteInfo Of(string v, IHTMLImage e)
 {
     return(new SpriteInfo {
         Value = v, ImageValue = e
     });
 }
Exemple #32
0
        void Spawn(DudeAnimationInfo LoadedCharacter, Scene.Document LoadedScene)
        {
            var ViewSize = new Size {
                Width = 640, Height = 480
            };

            var Container = new IHTMLDiv();

            Container.AttachToDocument();
            Container.style.SetSize(ViewSize.Width, ViewSize.Height + 22);
            Container.KeepInCenter();

            //Container.MakeCSSShaderCrumple();

            var Wallpaper = new IHTMLDiv().AttachTo(Container);

            Wallpaper.style.SetSize(ViewSize.Width, ViewSize.Height + 22);


            new power().ToBackground(Wallpaper.style);
            Wallpaper.style.position           = IStyle.PositionEnum.absolute;
            Wallpaper.style.backgroundRepeat   = "no-repeat";
            Wallpaper.style.backgroundPosition = "center center";



            var Margin     = 48;
            var MarginSafe = 72;



            var CurrentFrame = LoadedScene.Frames.Randomize().First();
            //var CurrentFrame = LoadedScene.Frames.Single(f => f.Name == "C");

            var Room = new IHTMLDiv();



            Room.style.border = "1px solid #00ff00";
            Room.style.SetSize(ViewSize.Width, ViewSize.Height);
            Room.style.position = IStyle.PositionEnum.absolute;
            Room.style.overflow = IStyle.OverflowEnum.hidden;

            Room.AttachTo(Container);
            Room.style.SetLocation(0, 22);

            //Room.AttachToDocument();
            //Room.KeepInCenter();



            var tween = Room.ToOpacityTween();

            Action HideRoom = () => tween.Value = 1;
            Action ShowRoom = () => tween.Value = 0;

            HideRoom();

            //var GroundOverlay2 = new IHTMLDiv();

            //GroundOverlay2.style.backgroundColor = Color.Blue;
            ////GroundOverlay.style.Opacity = 0;

            //GroundOverlay2.style.position = IStyle.PositionEnum.absolute;
            //GroundOverlay2.style.SetLocation(0, 0, ViewSize.Width, ViewSize.Height);
            //GroundOverlay2.AttachTo(Room);

            var LostInTime_Images = new ImpAdventures.HTML.Pages.LostInTimeImages().Images;

            var BackgroundImage = new IHTMLImage();

            LostInTime_Images.FirstOrDefault(
                k => k.src.SkipUntilLastIfAny("/") == CurrentFrame.Image.Source.SkipUntilLastIfAny("/")
                ).With(
                ImageSource =>
            {
                Console.WriteLine(ImageSource.src);
                BackgroundImage.src = ImageSource.src;
            }
                );

            BackgroundImage.style.SetLocation(0, 0, ViewSize.Width, ViewSize.Height);
            BackgroundImage.alt = "BackgroundImage";
            BackgroundImage.AttachTo(Room);

            //GroundOverlay2.style.backgroundImage = "url(" + CurrentFrame.Image.Source + ")";
            //BackgroundImage.InvokeOnComplete(
            //    delegate
            //    {
            //        //BackgroundImage.style.backgroundColor = Color.Red;
            //        //BackgroundImage.style.SetLocation(0,0, ViewSize.Width, ViewSize.Height);
            //        BackgroundImage.AttachTo(GroundOverlay2);
            //    }
            //);


            var GroundOverlay = new IHTMLDiv();

            GroundOverlay.style.backgroundColor = Color.Blue;
            GroundOverlay.style.Opacity         = 0;
            GroundOverlay.style.SetLocation(0, 0, ViewSize.Width, ViewSize.Height);
            GroundOverlay.AttachTo(Room);

            var Ground = new IHTMLDiv();

            Ground.style.SetLocation(0, 0, ViewSize.Width, ViewSize.Height);
            Ground.AttachTo(Room);



            var AnimateRoomChange = default(Action <Action>);

            #region TryToChangeRooms
            Func <TryToChangeRoomsArgs, bool> TryToChangeRooms =
                e =>
            {
                if (e == null)
                {
                    return(false);
                }

                if (e.NextRoomSelector == null)
                {
                    throw new ArgumentNullException("NextRoomSelector");
                }

                var next = LoadedScene.Frames.SingleOrDefault(e.NextRoomSelector);

                var r = next != null;

                if (r)
                {
                    AnimateRoomChange(
                        delegate
                    {
                        CurrentFrame = next;

                        Console.WriteLine("AnimateRoomChange");

                        LostInTime_Images.FirstOrDefault(
                            k => k.src.SkipUntilLastIfAny("/") == CurrentFrame.Image.Source.SkipUntilLastIfAny("/")
                            ).With(
                            ImageSource =>
                        {
                            Console.WriteLine(ImageSource.src);
                            BackgroundImage.src = ImageSource.src;
                        }
                            );

                        //GroundOverlay2.style.backgroundImage = "url(" + CurrentFrame.Image.Source + ")";
                        //BackgroundImage.src = CurrentFrame.Image.Source;

                        e.ReadyToTeleport();
                    }
                        );
                }


                return(r);
            };
            #endregion


            var dude = CreateDude(LoadedCharacter);

            dude.Control.AttachTo(Ground);

            #region Doors
            var Doors = new[]
            {
                new TryToChangeRoomsArgs
                {
                    Condition        = () => dude.CurrentLocation.X > ViewSize.Width - Margin,
                    NextRoomSelector = f => f.Name == CurrentFrame.Right,
                    ReadyToTeleport  = delegate
                    {
                        dude.TeleportTo(-MarginSafe, dude.CurrentLocation.Y);
                        dude.LookAt(new Point(MarginSafe, (int)dude.CurrentLocation.Y));
                    }
                },
                new TryToChangeRoomsArgs
                {
                    Condition        = () => dude.CurrentLocation.X < Margin,
                    NextRoomSelector = f => f.Name == CurrentFrame.Left,
                    ReadyToTeleport  = delegate
                    {
                        dude.TeleportTo(ViewSize.Width + MarginSafe, dude.CurrentLocation.Y);
                        dude.LookAt(new Point(ViewSize.Width - MarginSafe, (int)dude.CurrentLocation.Y));
                    }
                },
                new TryToChangeRoomsArgs
                {
                    Condition        = () => dude.CurrentLocation.Y < Margin,
                    NextRoomSelector = f => f.Name == CurrentFrame.Top,
                    ReadyToTeleport  = delegate
                    {
                        dude.TeleportTo(dude.CurrentLocation.X, ViewSize.Height + MarginSafe);
                        dude.LookAt(new Point((int)dude.CurrentLocation.X, ViewSize.Height - MarginSafe));
                    }
                },
                new TryToChangeRoomsArgs
                {
                    Condition        = () => dude.CurrentLocation.Y > ViewSize.Height - Margin,
                    NextRoomSelector = f => f.Name == CurrentFrame.Bottom,
                    ReadyToTeleport  = delegate
                    {
                        dude.TeleportTo(dude.CurrentLocation.X, -Margin);
                        dude.LookAt(new Point((int)dude.CurrentLocation.X, MarginSafe));
                    }
                }
            };
            #endregion

            Console.WriteLine(new { Doors = Doors.Length });

            Doors.WithEachIndex(
                (x, index) =>
            {
                Console.WriteLine(new { index, x });
                Console.WriteLine(new { index, x.Condition });
            }
                );


            var ChangeRoom = new ChangeRoom {
                autobuffer = true
            };
            var Talk = new Talk {
                autobuffer = true
            };
            var Argh_RChannel = new Argh_RChannel {
                autobuffer = true
            };
            var Argh_LChannel = new Argh_LChannel {
                autobuffer = true
            };
            var Argh_Disabled         = false;
            var Argh_VolumeMultiplier = 1.0;

            #region Argh_Stereo
            Action <double, double> Argh_Stereo =
                (volume, balance) =>
            {
                if (Argh_Disabled)
                {
                    return;
                }

                Argh_RChannel.AttachToDocument();
                Argh_LChannel.AttachToDocument();

                Argh_RChannel.volume = Argh_VolumeMultiplier * volume * balance;
                Argh_LChannel.volume = Argh_VolumeMultiplier * volume * (1 - balance);

                Argh_RChannel.play();
                Argh_LChannel.play();

                Argh_RChannel = new Argh_RChannel {
                    autobuffer = true
                };
                Argh_LChannel = new Argh_LChannel {
                    autobuffer = true
                };

                Argh_Disabled          = true;
                Argh_VolumeMultiplier /= 2;

                new Timer(t => Argh_Disabled         = false).StartTimeout(800);
                new Timer(t => Argh_VolumeMultiplier = 1).StartTimeout(5000);
            };
            #endregion

            #region PrintText
            Action <string, Action> PrintText =
                (text, done) =>
            {
                Talk.AttachToDocument();
                Talk.load();
                Talk.volume = Math.Min(1, dude.Zoom.DynamicZoom / 4);
                Talk.play();
                Talk = new Talk {
                    autobuffer = true
                };

                text.Length.Range().AsyncForEach(
                    i =>
                {
                    Wallpaper.innerText = text.Left(i + 1);

                    var c = text[i];

                    if (LoadedScene.SlowText.Contains("" + c))
                    {
                        return(100.Random());
                    }

                    return(50.Random());
                }, done
                    );
            };
            #endregion

            Action <string, Action> PrintRandomText =
                (text, done) => PrintText(text.Split(LoadedScene.TextDelimiter).Randomize().First(), done);



            dude.DoneWalking +=
                delegate
            {
                // compiler bug: cannot invoke Action<func, action> delegate ?

                System.Console.WriteLine("done walking in " + CurrentFrame.Name + " at " + dude.CurrentLocation);

                var xFirstOrDefault = Doors.FirstOrDefault(d => d.Condition());

                System.Console.WriteLine("done walking in " + new { xFirstOrDefault });

                // Doors null?
                if (TryToChangeRooms(xFirstOrDefault))
                {
                    return;
                }


                if (CurrentFrame.Items != null)
                {
                    var item = CurrentFrame.Items.Where(
                        i => new Point(i.X.ToInt32(), i.Y.ToInt32()).GetRange(dude.CurrentLocation) < i.R.ToInt32()
                        ).FirstOrDefault();

                    if (item != null)
                    {
                        dude.IsSelected = false;
                        dude.LookDown();

                        PrintRandomText(item.Text,
                                        delegate
                        {
                            dude.WalkingOnce +=
                                delegate
                            {
                                Wallpaper.innerText = "";
                            };

                            dude.IsSelected = true;
                        }
                                        );
                    }
                }
            };

            #region AnimateRoomChange
            AnimateRoomChange =
                ReadyToTeleport =>
            {
                var Step1 = default(System.Action);
                var Step2 = default(System.Action);
                var Step3 = default(Action);

                Step1 =
                    delegate
                {
                    tween.Done -= Step1;

                    ReadyToTeleport();

                    tween.Done += Step2;

                    ShowRoom();
                };

                Step2 =
                    delegate
                {
                    tween.Done -= Step2;

                    dude.DoneWalking += Step3;

                    dude.IsWalking = true;
                };

                Step3 =
                    delegate
                {
                    dude.DoneWalking -= Step3;

                    dude.IsSelected = true;
                };

                dude.IsSelected = false;

                tween.Done += Step1;
                // go left
                HideRoom();

                // http://stackoverflow.com/questions/3009888/autoplay-audio-files-on-an-ipad-with-html5
                ChangeRoom.AttachToDocument();
                ChangeRoom.load();
                ChangeRoom.volume = 0.2;
                ChangeRoom.play();
                ChangeRoom = new ChangeRoom();
            };
            #endregion

            var pointer_x = 0;
            var pointer_y = 0;

            #region onmousemove
            Container.onmousemove +=
                ev =>
            {
                if (Native.Document.pointerLockElement == Container)
                {
                    if (dude.IsSelected)
                    {
                        var volume  = Math.Min(1, dude.Zoom.DynamicZoom / 4);
                        var balance = dude.CurrentLocation.X / ViewSize.Width;

                        pointer_x += ev.movementX;
                        pointer_y += ev.movementY;

                        pointer_x = Math.Min(ViewSize.Width - 0, Math.Max(0, pointer_x));
                        pointer_y = Math.Min(ViewSize.Height - 0, Math.Max(0, pointer_y));

                        var OffsetPosition = new Point(pointer_x, pointer_y

                                                       );

                        Console.WriteLine(OffsetPosition);

                        Argh_Stereo(volume, balance);
                        dude.WalkTo(OffsetPosition);
                    }
                }
            };
            #endregion

            #region ontouchstart
            Container.ontouchstart +=
                ev =>
            {
                ev.PreventDefault();

                System.Console.WriteLine(ev.CursorPosition);

                if (dude.IsSelected)
                {
                    var volume  = Math.Min(1, dude.Zoom.DynamicZoom / 4);
                    var balance = dude.CurrentLocation.X / ViewSize.Width;

                    var ev_OffsetPosition = new Point(
                        ev.touches[0].clientX - Container.Bounds.Left,
                        ev.touches[0].clientY - Container.Bounds.Top
                        );

                    Argh_Stereo(volume, balance);
                    dude.WalkTo(ev_OffsetPosition);
                }
            };
            #endregion

            #region onclick
            Container.onclick +=
                ev =>
            {
                ev.PreventDefault();

                if (ev.MouseButton == IEvent.MouseButtonEnum.Middle)
                {
                    if (Native.Document.pointerLockElement == Container)
                    {
                        Native.Document.exitPointerLock();
                        return;
                    }

                    pointer_x = (int)dude.CurrentLocation.X;
                    pointer_y = (int)dude.CurrentLocation.Y;

                    //Container.requestFullscreen();
                    Container.requestPointerLock();
                    return;
                }

                if (ev.Element != Ground)
                {
                    return;
                }

                System.Console.WriteLine(ev.CursorPosition);

                if (dude.IsSelected)
                {
                    var volume  = Math.Min(1, dude.Zoom.DynamicZoom / 4);
                    var balance = dude.CurrentLocation.X / ViewSize.Width;

                    Argh_Stereo(volume, balance);
                    dude.WalkTo(ev.OffsetPosition);
                }
            };
            #endregion



            //GroundOverlay.onclick +=
            //    ev =>
            //    {
            //        if (ev.Element != GroundOverlay)
            //            return;

            //        System.Console.WriteLine(ev.CursorPosition);

            //        if (dude.IsSelected)
            //        {
            //            new Argh().play();

            //            dude.WalkTo(ev.OffsetPosition);
            //        }
            //    };


            dude.TeleportTo(ViewSize.Width / 2, (ViewSize.Height - MarginSafe) / 2);
            dude.LookDown();

            ShowRoom();

            dude.DoneWalkingOnce +=
                delegate
            {
                PrintRandomText(
                    LoadedScene.IntroText,
                    delegate
                {
                    dude.WalkingOnce +=
                        delegate
                    {
                        Wallpaper.innerText = "";
                    };

                    dude.IsSelected = true;
                }
                    );
            };

            dude.WalkToArc(MarginSafe, dude.Direction);
        }
Exemple #33
0
        private void Initialize(IDefault page = null)
        {
            #region += Launched chrome.app.window
            dynamic self               = Native.self;
            dynamic self_chrome        = self.chrome;
            object  self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    chrome.runtime.UpdateAvailable += delegate
                    {
                        new chrome.Notification(title: "UpdateAvailable");
                    };

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "ChromeUDPSendAsync");

                        var xappwindow = await chrome.app.window.create(
                            Native.document.location.pathname, options : null
                            );

                        //xappwindow.setAlwaysOnTop

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion


            int w = Native.window.Width;
            int h = Native.window.Height;



            var gl = new WebGLRenderingContext(preserveDrawingBuffer: true);

            var canvas = gl.canvas.AttachToDocument();
            canvas.style.backgroundColor        = JSColor.Black;
            Native.document.body.style.overflow = IStyle.OverflowEnum.hidden;
            canvas.style.SetLocation(0, 0);


            #region Dispose
            var IsDisposed = false;

            Dispose = delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                IsDisposed = true;

                canvas.Orphanize();
            };
            #endregion


            // http://cs.helsinki.fi/u/ilmarihe/metatunnel.html


            var p = gl.createProgram(
                new ChocoluxVertexShader(),
                new ChocoluxFragmentShader()
                );


            gl.bindAttribLocation(p, 0, "position");
            gl.linkProgram(p);

            gl.useProgram(p);

            var uniforms = p.Uniforms(gl);

            gl.viewport(0, 0, w, h);

            gl.enableVertexAttribArray(0);


            var verts = gl.createBuffer();

            gl.bindBuffer(gl.ARRAY_BUFFER, verts);
            gl.bufferData(gl.ARRAY_BUFFER,
                          new[] { -1f, -1f, -1f, 1f, 1f, -1f, 1f, 1f }
                          , gl.STATIC_DRAW);
            gl.vertexAttribPointer((uint)0, 2, gl.FLOAT, false, 0, 0);

            var indicies = gl.createBuffer();

            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicies);

            var q = new Uint16Array(0, 1, 2, 3);



            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, q, gl.STATIC_DRAW);

            var start = new IDate().getTime();

            Native.window.onframe += delegate
            {
                var timestamp = new IDate().getTime();
                var t         = (timestamp - start) / 1000.0f * 30f;


                uniforms.t = t * 100;
                //gl.uniform1f(gl.getUniformLocation(p, "t"), t * 100);
                gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_SHORT, 0);
                gl.flush();
            };



            #region AtResize
            Action AtResize = delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                canvas.width  = Native.window.Width;
                canvas.height = Native.window.Height;


                gl.viewport(0, 0, canvas.width, canvas.height);
            };

            AtResize();

            Native.window.onresize += delegate
            {
                AtResize();
            };
            #endregion


            #region requestFullscreen
            Native.Document.body.ondblclick +=
                delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                // http://tutorialzine.com/2012/02/enhance-your-website-fullscreen-api/

                Native.Document.body.requestFullscreen();
            };
            #endregion


            Func <string> newicon = delegate
            {
                var icon = canvas.toDataURL("image/png");

                Native.Document.getElementsByTagName("link").AsEnumerable().ToList().WithEach(
                    e =>
                {
                    var link = (IHTMLLink)e;

                    if (link.rel == "icon")
                    {
                        if (link.type == "image/png")
                        {
                            link.href = icon;
                        }
                        else
                        {
                            link.Orphanize();
                        }
                    }
                }
                    );

                return(icon);
            };

            Native.Document.body.onclick +=
                delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                newicon();
            };

#if PackageAsApplication
            @"Spiral".ToDocumentTitle();

            Native.Window.requestAnimationFrame +=
                delegate
            {
                var icon = newicon();
                var img  = new IHTMLImage {
                    src = icon
                };

                //img.width = Native.Window.Width / 2;
                //img.height = Native.Window.Height / 2;

                Native.Document.getElementsByTagName("script")
                .Select(k => (IHTMLScript)k)
                .FirstOrDefault(k => k.src.EndsWith("/view-source"))
                .With(
                    source =>
                {
                    #region PackageAsApplication
                    Action <IHTMLScript, XElement, Action <string> > PackageAsApplication =
                        (source0, xml, yield) =>
                    {
                        new IXMLHttpRequest(
                            ScriptCoreLib.Shared.HTTPMethodEnum.GET, source0.src,
                            (IXMLHttpRequest r) =>
                        {
                            // store hash
                            xml.Add(new XElement("link", new XAttribute("rel", "location"), new XAttribute("href", Native.Document.location.hash)));

                            #region script
                            xml.Add(
                                new XElement("script",
                                             "/* source */"
                                             )
                                );

                            var data = "";


                            Action later = delegate
                            {
                                data = data.Replace("/* source */", r.responseText);
                            };
                            #endregion


                            //Native.Document.getElementsByTagName("link").AsEnumerable().ToList().ForEach(

                            xml.Elements("link").ToList().ForEach(
                                (XElement link, Action next) =>
                            {
                                #region style
                                var rel = link.Attribute("rel");
                                if (rel.Value != "stylesheet")
                                {
                                    next();
                                    return;
                                }

                                var href = link.Attribute("href");

                                var placeholder = "/* " + href.Value + " */";

                                //page.DragHTM.innerText += " " + placeholder;


                                xml.Add(new XElement("style", placeholder));

                                new IXMLHttpRequest(ScriptCoreLib.Shared.HTTPMethodEnum.GET, href.Value,
                                                    rr =>
                                {
                                    later += delegate
                                    {
                                        data = data.Replace(placeholder, rr.responseText);
                                    };

                                    Console.WriteLine("link Remove");
                                    link.Remove();

                                    next();
                                }
                                                    );

                                #endregion
                            }
                                )(
                                delegate
                            {
                                data = xml.ToString();
                                Console.WriteLine("data: " + data);
                                later();

                                yield(data);
                            }
                                );
                        }
                            );
                    };
                    #endregion


                    PackageAsApplication(
                        source,
                        XElement.Parse(new XDefaultPage.XMLSourceSource().Text),
                        data =>
                    {
                        var bytes  = Encoding.ASCII.GetBytes(data);
                        var data64 = System.Convert.ToBase64String(bytes);


                        Native.Document.body.title = "Drag me!";

                        Native.Document.body.ondragstart +=
                            e =>
                        {
                            //e.dataTransfer.setData("text/plain", "Sphere");

                            // http://codebits.glennjones.net/downloadurl/virtualdownloadurl.htm
                            //e.dataTransfer.setData("DownloadURL", "image/png:Sphere.png:" + icon);

                            e.dataTransfer.setData("DownloadURL", "application/octet-stream:Chocolux.htm:data:application/octet-stream;base64," + data64);
                            e.dataTransfer.setData("text/html", data);
                            e.dataTransfer.setData("text/uri-list", Native.Document.location + "");
                            e.dataTransfer.setDragImage(img, img.width / 2, img.height / 2);
                        };
                    }
                        );
                }
                    );
            };
#endif
        }
        public Application(IApp page)
        {
            // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeTabsExperiment\ChromeTabsExperiment\Application.cs
            Console.WriteLine("enter ChromeHybridCapture Application");


            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;



            #region self_chrome_tabs extension
            object self_chrome_tabs = self_chrome.tabs;
            if (self_chrome_tabs != null)
            {
                // running as extension {{ FullName = <Namespace>.Application }}

                //Console.WriteLine("running as extension " + new { typeof(Application).FullName });
                //Console.WriteLine("running as extension " + new { typeof(Application).Assembly.FullName });

                // can we find and connect to app?
                Console.WriteLine("running as extension " + new { typeof(Application).Assembly.GetName().Name });

                //70ms chrome.management.getAll
                //2015-08-22 13:41:33.591 view-source:53670 98ms chrome.management.getAll {{ Length = 28 }}
                //2015-08-22 13:41:33.594 view-source:53670 101ms ExtensionInfo {{ id = aemlnmcokphbneegoefdckonejmknohh, name = ChromeHybridCapture }}
                //2015-08-22 13:41:33.597 view-source:53670 104ms ExtensionInfo {{ id = apdfllckaahabafndbhieahigkjlhalf, name = Google Drive }}
                //2015-08-22 13:41:33.599 view-source:53670 106ms ExtensionInfo {{ id = blpcfgokakmgnkcojhhkbfbldkacnbeo, name = YouTube }}
                //2015-08-22 13:41:33.602 view-source:53670 109ms ExtensionInfo {{ id = cgnjcccfcjhdnbfgjgllglbhfcgndmea, name = WebGLHZBlendCharacter }}
                //2015-08-22 13:41:33.604 view-source:53670 111ms ExtensionInfo {{ id = coobgpohoikkiipiblmjeljniedjpjpf, name = Google Search }}
                //2015-08-22 13:41:33.608 view-source:53670 114ms ExtensionInfo {{ id = fkgibadjpabiongmgoeomdbcefhabmah, name = ChromeCaptureToFile.Application.exe }}
                //2015-08-22 13:41:33.610 view-source:53670 117ms ExtensionInfo {{ id = ghbmnnjooekpmoecnnnilnnbdlolhkhi, name = Google Docs Offline }}
                //2015-08-22 13:41:33.612 view-source:53670 119ms ExtensionInfo {{ id = haebnnbpedcbhciplfhjjkbafijpncjl, name = TinEye Reverse Image Search }}
                //2015-08-22 13:41:33.614 view-source:53670 121ms ExtensionInfo {{ id = lchcahaldakdnjlkchkgncecgpcnabgo, name = Heat Zeeker }}
                //2015-08-22 13:41:33.616 view-source:53670 123ms ExtensionInfo {{ id = nhkcfbkpodjkallcfebgihcoglfaniep, name = freenode irc }}
                //2015-08-22 13:41:33.619 view-source:53670 126ms ExtensionInfo {{ id = ogmpedngmnolclkmlpcdgmfonlagkejp, name = Private Joe: Urban Warfare }}
                //2015-08-22 13:41:33.621 view-source:53670 128ms ExtensionInfo {{ id = pcklgpcdddecpmkiinpkhehanbijjepn, name = idea-remixer }}
                //2015-08-22 13:41:33.624 view-source:53670 131ms ExtensionInfo {{ id = pjkljhegncpnkpknbcohdijeoejaedia, name = Gmail }}
                //2015-08-22 13:41:33.626 view-source:53670 133ms ExtensionInfo {{ id = plgmlhohecdddhbmmkncjdmlhcmaachm, name = draw.io (Legacy) }}
                //2015-08-22 13:41:33.629 view-source:53670 136ms ExtensionInfo {{ id = aapbdbdomjkkjkaonfhkkikfgjllcleb, name = Google Translate }}
                //2015-08-22 13:41:33.631 view-source:53670 138ms ExtensionInfo {{ id = bcfddoencoiedfjgepnlhcpfikgaogdg, name = QR-Code Tag Extension }}
                //2015-08-22 13:41:33.633 view-source:53670 139ms ExtensionInfo {{ id = coblegoildgpecccijneplifmeghcgip, name = Web Cache }}
                //2015-08-22 13:41:33.635 view-source:53670 142ms ExtensionInfo {{ id = ganlifbpkcplnldliibcbegplfmcfigp, name = Collusion for Chrome }}
                //2015-08-22 13:41:33.638 view-source:53670 145ms ExtensionInfo {{ id = gighmmpiobklfepjocnamgkkbiglidom, name = AdBlock }}
                //2015-08-22 13:41:33.640 view-source:53670 147ms ExtensionInfo {{ id = iiabebggdceojiejhopnopmbkgandhha, name = Operation Heat Zeeker }}
                //2015-08-22 13:41:33.642 view-source:53670 149ms ExtensionInfo {{ id = jkgfnfnagdnjicmonpfhhdnkdjgjdamo, name = Avalon Spider Solitaire }}
                //2015-08-22 13:41:33.644 view-source:53670 151ms ExtensionInfo {{ id = kdifgkljkjhpflhalpkhehlldfakggdi, name = my.jsc-solutions.net }}
                //2015-08-22 13:41:33.646 view-source:53670 153ms ExtensionInfo {{ id = lmjegmlicamnimmfhcmpkclmigmmcbeh, name = Application Launcher for Drive (by Google) }}
                //2015-08-22 13:41:33.648 view-source:53670 155ms ExtensionInfo {{ id = mmfbcljfglbokpmkimbfghdkjmjhdgbg, name = Text }}
                //2015-08-22 13:41:33.650 view-source:53670 157ms ExtensionInfo {{ id = molncoemjfmpgdkbdlbjmhlcgniigdnf, name = Project Naptha }}
                //2015-08-22 13:41:33.652 view-source:53670 159ms ExtensionInfo {{ id = ogkcjmbhnfmlnielkjhedpcjomeaghda, name = WebGL Inspector }}
                //2015-08-22 13:41:33.653 view-source:53670 160ms ExtensionInfo {{ id = pkngagjebplcgimojegcakmnlggmcjlc, name = LBA Redux }}
                //2015-08-22 13:41:33.657 view-source:53670 164ms ExtensionInfo {{ id = ppmibgfeefcglejjlpeihfdimbkfbbnm, name = Change HTTP Request Header }}

                Action<string> __ChromeCaptureToFile_Application_sendMessage = delegate { };

                new { }.With(
                    async delegate
                    {
                        //  TypeError: chrome.management.getAll is not a function

                        Console.WriteLine("chrome.management.getAll");
                        var extensions = await chrome.management.getAll();

                        Console.WriteLine("chrome.management.getAll " + new { extensions.Length });
                        // https://developer.chrome.com/extensions/management#type-ExtensionInfo

                        //                        view - source:53670 69ms chrome.management.getAll
                        //2015 - 08 - 22 13:34:13.514 view - source:53670 89ms chrome.management.getAll { { Length = 28 } }
                        //                        2015 - 08 - 22 13:34:13.518 view - source:53670 93ms ExtensionInfo { { item = [object Object] } }

                        foreach (var item in extensions)
                        {
                            //Console.WriteLine("ExtensionInfo " + new { item });
                            //Console.WriteLine("ExtensionInfo " + new { item.id, item.name });

                            //2015-08-22 13:41:33.608 view-source:53670 114ms ExtensionInfo {{ id = fkgibadjpabiongmgoeomdbcefhabmah, name = ChromeCaptureToFile.Application.exe }}

                            // typeof(self) ?
                            if (item.name.StartsWith(typeof(Application).Assembly.GetName().Name))
                            {
                                var __item = item;

                                // we will also know when it reloads? we have to reconnect then?

                                __ChromeCaptureToFile_Application_sendMessage = message =>
                                {
                                    Console.WriteLine("extension chrome.runtime.sendMessage " + new { message, __item.id, __item.name });

                                    chrome.runtime.sendMessage(item.id, message, null);
                                };

                                chrome.runtime.sendMessage(item.id, "extension to app!", null);


                                // extension chrome.runtime.connect done {{ name = , sender = null }}
                                chrome.runtime.connect(item.id).With(
                                    port =>
                                    {
                                        //Console.WriteLine("extension chrome.runtime.connect done " + new { port.name, port.sender.id });
                                        //Console.WriteLine("extension chrome.runtime.connect done " + new { port.name, port.sender });
                                        Console.WriteLine("extension chrome.runtime.connect done");




                                        #region extension: HopToChromeApp.VirtualOnCompleted
                                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeapp
                                        HopToChromeApp.VirtualOnCompleted = async (that, continuation) =>
                                       {
                                           // state 0 ? or state -1 ?
                                           Console.WriteLine("extension HopToChromeApp VirtualOnCompleted enter ");

                                           TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableContinuation r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation);

                                           // 29035ms extension  port.onMessage {{ message = do HopToChromeExtension }}
                                           port.postMessage("do HopToChromeApp " + new { r.shadowstate.TypeName, r.shadowstate.state });


                                           // now send the jump instruction... will it make it?
                                           port.postMessage(r.shadowstate);
                                       };
                                        #endregion




                                        // is the app now able to send extension messages?

                                        port.onMessage.addListener(
                                            new Action<object>(
                                                (message) =>
                                                {
                                                    // 4847ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }}



                                                    // extension  port.onMessage {{ message = from app hello to extension }}
                                                    // extension  port.onMessage {{ message = [object Object] }}

                                                    // look app sent a message to extension

                                                    // 191ms extension  port.onMessage {{ message = from app hello to extension, is_string = false, equals_typeofstring = false }}

                                                    // 219ms extension  port.onMessage {{ message = from app hello to extension, expando_isstring = true, is_string = false, equals_typeofstring = false }}
                                                    //var expando_isstring = ScriptCoreLib.JavaScript.Runtime.Expando.Of(message).IsString;

                                                    // roslyn? wtf
                                                    //var is_string = message is string;
                                                    //var equals_typeofstring = message.GetType() == typeof(string);

                                                    //Console.WriteLine("extension  port.onMessage " + new { expando_isstring, is_string, equals_typeofstring });

                                                    // extension  port.onMessage {{ state = null, TypeName = null }}
                                                    if (message is string)
                                                    {
                                                        Console.WriteLine("extension  port.onMessage: " + message);

                                                        // Z:\jsc.svn\examples\javascript\async\Test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\ShadowIAsyncStateMachine.cs
                                                        return;
                                                    }


                                                    #region IAsyncStateMachine
                                                    // casting from anonymous object.
                                                    var xShadowIAsyncStateMachine = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)message;

                                                    // or constructor id?
                                                    Console.WriteLine("extension  port.onMessage " + new { xShadowIAsyncStateMachine.state, xShadowIAsyncStateMachine.TypeName });

                                                    // 12468ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }}, expando_isstring = true, is_string = false, equals_typeofstring = false }}
                                                    //2015-08-22 15:49:45.729 view-source:53670 12471ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }} }}
                                                    //2015-08-22 15:49:45.733 view-source:53670 12475ms extension  port.onMessage {{ message = [object Object], expando_isstring = false, is_string = false, equals_typeofstring = false }}
                                                    //2015-08-22 15:49:45.737 view-source:53670 12479ms extension  port.onMessage {{ state = 0, TypeName = <Namespace>.___ctor_b__4_9_d }}


                                                    #region xAsyncStateMachineType
                                                    var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
                                                        xAsyncStateMachineTypeCandidate =>
                                                        {
                                                            // safety check 1

                                                            //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

                                                            var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(xAsyncStateMachineTypeCandidate);
                                                            if (xisIAsyncStateMachine)
                                                            {
                                                                //Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

                                                                return xAsyncStateMachineTypeCandidate.FullName == xShadowIAsyncStateMachine.TypeName;
                                                            }

                                                            return false;
                                                        }
                                                    );
                                                    #endregion


                                                    var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
                                                    var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

                                                    var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

                                                    #region 1__state
                                                    xAsyncStateMachineType.GetFields(
                                                      System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
                                                      ).WithEach(
                                                       AsyncStateMachineSourceField =>
                                                       {

                                                           //Console.WriteLine(new { AsyncStateMachineSourceField });

                                                           if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
                                                           {
                                                               AsyncStateMachineSourceField.SetValue(
                                                                   NewStateMachineI,
                                                                   xShadowIAsyncStateMachine.state
                                                                );
                                                           }


                                                       }
                                                  );
                                                    #endregion

                                                    NewStateMachineI.MoveNext();
                                                    #endregion

                                                }
                                            )
                                        );



                                        //chrome.tabs.Created += async tab =>
                                        //{
                                        //    port.postMessage("chrome.tabs.Created " + new { tab });

                                        //};

                                        //chrome.tabs.Updated += async (tabId, x, tab) =>
                                        //{
                                        //    //  Updated {{ i = 0, x = null, tab = null }}

                                        //    port.postMessage("chrome.tabs.Updated  " + new { tabId, x, tab });


                                        //};
                                    }
                                );
                            }
                        }

                    }
                    );

                //chrome.tabs.Created += async tab =>
                //{
                //    Console.WriteLine("chrome.tabs.Created " + new { tab });

                //};

                //chrome.tabs.Updated += async (tabId, x, tab) =>
                //{
                //    //  Updated {{ i = 0, x = null, tab = null }}

                //    Console.WriteLine("chrome.tabs.Updated  " + new { tabId, x, tab });


                //};



                return;
            }
            #endregion


            #region self_chrome_socket app
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("appwindow chrome.app.window.create, is that you?");

                    MessagePort appwindow_to_app = null;

                    // called by? 619  app:HopToChromeAppWindow
                    #region  appwindow Native.window.onmessage
                    Native.window.onmessage += e =>
                    {
                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow

                        // appwindow Native.window.onmessage {{ data = app to appwindow! }}

                        var message = e.data;

                        //Console.WriteLine("appwindow Native.window.onmessage " + new { e.data });


                        // extension  port.onMessage {{ message = from app hello to extension }}
                        //var expando_isstring = ScriptCoreLib.JavaScript.Runtime.Expando.Of(message).IsString;

                        // look app sent a message to extension
                        //Console.WriteLine("app  port.onMessage " + new { message });

                        if (message is string)
                        {
                            Console.WriteLine("appwindow    Native.window.onmessage: " + message);
                            //Console.WriteLine("appwindow    Native.window.onmessage: " + new { e.ports });

                            if (e.ports != null)
                                foreach (var port in e.ports)
                                {
                                    Console.WriteLine("appwindow    Native.window.onmessage " + new { port });

                                    appwindow_to_app = port;
                                }

                            //e.po

                            return;
                        }

                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeapp




                        // casting from anonymous object.
                        var xShadowIAsyncStateMachine = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)message;

                        // or constructor id?
                        Console.WriteLine("appwindow     Native.window.onmessage " + new { xShadowIAsyncStateMachine.state, xShadowIAsyncStateMachine.TypeName });

                        // 12468ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }}, expando_isstring = true, is_string = false, equals_typeofstring = false }}
                        //2015-08-22 15:49:45.729 view-source:53670 12471ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }} }}
                        //2015-08-22 15:49:45.733 view-source:53670 12475ms extension  port.onMessage {{ message = [object Object], expando_isstring = false, is_string = false, equals_typeofstring = false }}
                        //2015-08-22 15:49:45.737 view-source:53670 12479ms extension  port.onMessage {{ state = 0, TypeName = <Namespace>.___ctor_b__4_9_d }}


                        #region xAsyncStateMachineType
                        var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
                            xAsyncStateMachineTypeCandidate =>
                            {
                                // safety check 1

                                //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

                                var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(xAsyncStateMachineTypeCandidate);
                                if (xisIAsyncStateMachine)
                                {
                                    //Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

                                    return xAsyncStateMachineTypeCandidate.FullName == xShadowIAsyncStateMachine.TypeName;
                                }

                                return false;
                            }
                        );
                        #endregion


                        var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
                        var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

                        var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

                        #region 1__state
                        xAsyncStateMachineType.GetFields(
                          System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
                          ).WithEach(
                           AsyncStateMachineSourceField =>
                           {

                               //Console.WriteLine(new { AsyncStateMachineSourceField });

                               if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
                               {
                                   AsyncStateMachineSourceField.SetValue(
                                       NewStateMachineI,
                                       xShadowIAsyncStateMachine.state
                                    );
                               }

                               // X:\jsc.svn\examples\javascript\async\Test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\CLRWebServiceInvoke.cs
                               // field names/ tokens need to be encrypted like typeinfo.

                               // some do manual restore
                               // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenIFrame\ChromeExtensionHopToTabThenIFrame\Application.cs
                               // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                               // or, are we supposed to initialize a string value here?

                               var xStringField = TestSwitchToServiceContextAsync.ArrayListExtensions.AsEnumerable(xShadowIAsyncStateMachine.StringFields).FirstOrDefault(
                                   f => DecoratedString(f.FieldName) == DecoratedString(AsyncStateMachineSourceField.Name)
                               );

                               if (xStringField != null)
                               {
                                   // once we are to go back to client. we need to reverse it?

                                   AsyncStateMachineSourceField.SetValue(
                                       NewStateMachineI,
                                       xStringField.value
                                    );
                                   // next xml?
                                   // before lets send our strings back with the new state!
                                   // what about exceptions?
                               }
                           }
                      );
                        #endregion

                        NewStateMachineI.MoveNext();

                    };
                    #endregion


                    #region appwindow:HopToChromeApp
                    HopToChromeApp.VirtualOnCompleted = async (that, continuation) =>
                    {
                        // do we have the port to send back our portal warp?

                        // state 0 ? or state -1 ?
                        Console.WriteLine("appwindow HopToChromeApp VirtualOnCompleted enter " + new { appwindow_to_app });

                        //// https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                        //// async dont like ref?
                        TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableContinuation r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation);
                        // 29035ms extension  port.onMessage {{ message = do HopToChromeExtension }}
                        appwindow_to_app.postMessage("do HopToChromeAppWindow " + new { r.shadowstate.TypeName, r.shadowstate.state });
                        // now send the jump instruction... will it make it?
                        appwindow_to_app.postMessage(r.shadowstate);
                    };
                    #endregion


                }
                else
                {
                    //Console.WriteLine("running as app");

                    // running as app {{ FullName = ChromeHybridCapture.Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null }}
                    //Console.WriteLine("running as app " + new { typeof(Application).Assembly.FullName });

                    // running as app {{ Name = ChromeHybridCapture.Application }}
                    Console.WriteLine("running as app " + new { typeof(Application).Assembly.GetName().Name } + " now reenable extension..");


                    #region app:appwindow_to_app
                    Action<object> appwindow_to_app = data =>
                    {
                        var xShadowIAsyncStateMachine = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)data;

                        Console.WriteLine("app appwindow_to_app " + new { xShadowIAsyncStateMachine.TypeName });

                        #region xAsyncStateMachineType
                        var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
                            xAsyncStateMachineTypeCandidate =>
                            {
                                // safety check 1

                                //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

                                var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(xAsyncStateMachineTypeCandidate);
                                if (xisIAsyncStateMachine)
                                {
                                    //Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

                                    return xAsyncStateMachineTypeCandidate.FullName == xShadowIAsyncStateMachine.TypeName;
                                }

                                return false;
                            }
                        );
                        #endregion

                        Console.WriteLine("app appwindow_to_app " + new { xAsyncStateMachineType });

                        var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
                        var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

                        var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

                        #region 1__state
                        xAsyncStateMachineType.GetFields(
                          System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
                          ).WithEach(
                           AsyncStateMachineSourceField =>
                           {

                               //Console.WriteLine(new { AsyncStateMachineSourceField });

                               if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
                               {
                                   AsyncStateMachineSourceField.SetValue(
                                       NewStateMachineI,
                                       xShadowIAsyncStateMachine.state
                                    );
                               }

                               // X:\jsc.svn\examples\javascript\async\Test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\CLRWebServiceInvoke.cs
                               // field names/ tokens need to be encrypted like typeinfo.

                               // some do manual restore
                               // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenIFrame\ChromeExtensionHopToTabThenIFrame\Application.cs
                               // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                               // or, are we supposed to initialize a string value here?

                               var xStringField = TestSwitchToServiceContextAsync.ArrayListExtensions.AsEnumerable(xShadowIAsyncStateMachine.StringFields).FirstOrDefault(
                                       f => DecoratedString(f.FieldName) == DecoratedString(AsyncStateMachineSourceField.Name)
                                   );

                               if (xStringField != null)
                               {
                                   // once we are to go back to client. we need to reverse it?

                                   AsyncStateMachineSourceField.SetValue(
                                           NewStateMachineI,
                                           xStringField.value
                                        );
                                   // next xml?
                                   // before lets send our strings back with the new state!
                                   // what about exceptions?
                               }
                           }
                      );
                        #endregion

                        NewStateMachineI.MoveNext();
                    };
                    #endregion


                    #region app:HopToChromeAppWindow
                    HopToChromeAppWindow.VirtualOnCompleted = async (that, continuation) =>
                    {
                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150824/webgliframebuffer

                        // state 0 ? or state -1 ?
                        Console.WriteLine("app HopToChromeAppWindow VirtualOnCompleted enter ");

                        #region outputWindow
                        if (that.window == null)
                        {
                            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow

                            if (outputWindow == null)
                            {
                                // https://developer.chrome.com/apps/app_window#type-CreateWindowOptions
                                outputWindow = await chrome.app.window.create(
                                                       Native.document.location.pathname,

                                                       // https://developer.chrome.com/apps/app_window#type-CreateWindowOptions
                                                       // this ctually works. but we wont see console on app log..
                                                       options: new { hidden = true, alwaysOnTop = true }
                                                );

                                ////xappwindow.setAlwaysOnTop

                                // or can we stay hidden?
                                //that.window.show();

                                await outputWindow.contentWindow.async.onload;
                            }
                            // reuse the window...
                            that.window = outputWindow;
                        }
                        #endregion


                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                        // async dont like ref?
                        TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableContinuation r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation);
                        // 29035ms extension  port.onMessage {{ message = do HopToChromeExtension }}



                        // Z:\jsc.svn\core\ScriptCoreLib\JavaScript\DOM\IWindow.postMessage.cs
                        // how do we use this thing?
                        var c = new MessageChannel();

                        c.port1.onmessage += e =>
                        {
                            Console.WriteLine("app HopToChromeAppWindow MessageChannel onmessage " + new { e.data });

                            appwindow_to_app(e.data);
                        };

                        c.port1.start();
                        c.port2.start();


                        //                    15ms appwindow    Native.window.onmessage: {{ ports = [object MessagePort] }}
                        //2015-08-22 20:50:18.019 view-source:53702 17ms appwindow    Native.window.onmessage: {{ port = [object MessagePort] }}
                        that.window.contentWindow.postMessage("do HopToChromeAppWindow " + new { r.shadowstate.TypeName, r.shadowstate.state }, transfer: c.port2);

                        // now send the jump instruction... will it make it?
                        that.window.contentWindow.postMessage(r.shadowstate);
                    };
                    #endregion





                    #region app:ConnectExternal
                    chrome.runtime.ConnectExternal += port =>
                    {
                        // app chrome.runtime.ConnectExternal {{ name = , id = jadmeogmbokffpkdfeiemjplohfgkidd }}

                        //Console.WriteLine("app chrome.runtime.ConnectExternal " + new { port.name, port.sender.id });
                        Console.WriteLine("app chrome.runtime.ConnectExternal " + new { port.sender.id } + " now click launch!");

                        new chrome.Notification(title: "ChromeHybridCapture", message: "service connected. click launch").Clicked += delegate
                        {
                            // https://developer.chrome.com/apps/app_runtime

                            // management_api
                        };

                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hybrid

                        // should we now be able to hop to our tab?
                        // what about if we are in an app window?

                        port.onMessage.addListener(
                            new Action<object>(
                                (message) =>
                                {
                                    // extension  port.onMessage {{ message = from app hello to extension }}
                                    var expando_isstring = ScriptCoreLib.JavaScript.Runtime.Expando.Of(message).IsString;

                                    // look app sent a message to extension
                                    //Console.WriteLine("app  port.onMessage " + new { message });

                                    if (expando_isstring)
                                    {
                                        Console.WriteLine("app  port.onMessage: " + message);
                                        return;
                                    }


                                    #region IAsyncStateMachine
                                    // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeapp
                                    // casting from anonymous object.
                                    var xShadowIAsyncStateMachine = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)message;

                                    // or constructor id?
                                    Console.WriteLine("app  port.onMessage " + new { xShadowIAsyncStateMachine.state, xShadowIAsyncStateMachine.TypeName });

                                    // 12468ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }}, expando_isstring = true, is_string = false, equals_typeofstring = false }}
                                    //2015-08-22 15:49:45.729 view-source:53670 12471ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }} }}
                                    //2015-08-22 15:49:45.733 view-source:53670 12475ms extension  port.onMessage {{ message = [object Object], expando_isstring = false, is_string = false, equals_typeofstring = false }}
                                    //2015-08-22 15:49:45.737 view-source:53670 12479ms extension  port.onMessage {{ state = 0, TypeName = <Namespace>.___ctor_b__4_9_d }}


                                    #region xAsyncStateMachineType
                                    var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
                                        xAsyncStateMachineTypeCandidate =>
                                        {
                                            // safety check 1

                                            //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

                                            var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(xAsyncStateMachineTypeCandidate);
                                            if (xisIAsyncStateMachine)
                                            {
                                                //Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

                                                return xAsyncStateMachineTypeCandidate.FullName == xShadowIAsyncStateMachine.TypeName;
                                            }

                                            return false;
                                        }
                                    );
                                    #endregion


                                    var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
                                    var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

                                    var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

                                    #region 1__state
                                    xAsyncStateMachineType.GetFields(
                                      System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
                                      ).WithEach(
                                       AsyncStateMachineSourceField =>
                                       {

                                           //Console.WriteLine(new { AsyncStateMachineSourceField });

                                           if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
                                           {
                                               AsyncStateMachineSourceField.SetValue(
                                                   NewStateMachineI,
                                                   xShadowIAsyncStateMachine.state
                                                );
                                           }


                                           // z:\jsc.svn\examples\javascript\async\Test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\CLRWebServiceInvoke.cs
                                           // field names/ tokens need to be encrypted like typeinfo.

                                           // some do manual restore
                                           // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenIFrame\ChromeExtensionHopToTabThenIFrame\Application.cs
                                           // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                                           // or, are we supposed to initialize a string value here?

                                           var xStringField = TestSwitchToServiceContextAsync.ArrayListExtensions.AsEnumerable(xShadowIAsyncStateMachine.StringFields).FirstOrDefault(
                                               f => DecoratedString(f.FieldName) == DecoratedString(AsyncStateMachineSourceField.Name)
                                           );

                                           if (xStringField != null)
                                           {
                                               // once we are to go back to client. we need to reverse it?

                                               AsyncStateMachineSourceField.SetValue(
                                                   NewStateMachineI,
                                                   xStringField.value
                                                );
                                               // next xml?
                                               // before lets send our strings back with the new state!
                                               // what about exceptions?
                                           }
                                       }
                                  );
                                    #endregion

                                    NewStateMachineI.MoveNext();
                                    #endregion
                                }
                            )
                        );



                        //port.postMessage(
                        //    new
                        //    {
                        //        text = "from app hello to extension"
                        //    }
                        //);

                        port.postMessage("from app hello to extension, click launch?");

                        // enable
                        //await default(HopToChromeExtension);

                        #region HopToChromeExtension
                        HopToChromeExtension.VirtualOnCompleted = async (that, continuation) =>
                        {
                            // state 0 ? or state -1 ?
                            Console.WriteLine("app HopToChromeExtension VirtualOnCompleted enter ");

                            // where is it defined?
                            // z:\jsc.svn\examples\javascript\async\Test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\ShadowIAsyncStateMachine.cs

                            // async dont like ref?
                            TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableContinuation r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation);

                            // 29035ms extension  port.onMessage {{ message = do HopToChromeExtension }}
                            port.postMessage("do HopToChromeExtension " + new { r.shadowstate.TypeName, r.shadowstate.state });


                            // now send the jump instruction... will it make it?
                            port.postMessage(r.shadowstate);


                            // how would we know to continue from current continuation?
                            // or are we fine to rebuild the scope if we jump back?
                        };
                        #endregion




                    };
                    #endregion

                    chrome.runtime.MessageExternal += (message, sender, sendResponse) =>
                    {
                        // was the extension able to pass us a message?

                        //Console.WriteLine("chrome.runtime.MessageExternal " + new { message, sender, sendResponse });
                        Console.WriteLine("app chrome.runtime.MessageExternal " + new { message });

                        // app chrome.runtime.MessageExternal {{ message = extension to app! }}

                        // remember the connection to enable hop to extension?
                    };

                    //Action AtLaunch = delegate { };

                    #region  Launched
                    // can the extension launch us too?
                    // either the user launches by a click or we launch from extension?
                    chrome.app.runtime.Launched += async delegate
                    {
                        // state 0 ? or state -1 ?

                        Console.WriteLine("app chrome.app.runtime.Launched before delay");

                        await Task.Delay(1);

                        nexttake:
                        //Console.WriteLine("nexttake " + new { index });
                        Console.WriteLine("nexttake");

                        // using IDisposable ?
                        await default(HopToChromeExtension);

                        #region HopToChromeExtension
                        // now this would be cool if it worked?
                        Console.WriteLine("app to extension chrome.app.runtime.Launched, only state was sent over?");

                        // can we do our thing and jump back with the capture now?

                        // lets create a tab for us to jump into..
                        //var tab = await chrome.tabs.create(new { url = "http://example.com" });

                        // https://developer.chrome.com/extensions/activeTab

                        // implict/auto context hop?
                        var tabsw = Stopwatch.StartNew();

                        // which window station?
                        var tabwindow = await chrome.windows.create(new { state = "fullscreen", url = "http://www.flightradar24.com/59.15,23.86/9" });
                        //var tabwindow = await chrome.windows.create(new { state = "fullscreen", url = "http://example.com" });

                        //var tab = await chrome.tabs.create(new { url = "http://www.flightradar24.com/59.05,24.14/8" });
                        // would we need to hop into the tab to inspec data?
                        Console.WriteLine("extension chrome.tabs.create done. about to capture... " + new { tabsw.ElapsedMilliseconds });


                        // how do we know a tab is loaded?
                        // content takes a while to load doesnt it...
                        await Task.Delay(7000);

                        // Error: Invocation of form tabs.captureVisibleTab(object, null, function) doesn't match definition tabs.captureVisibleTab(optional integer windowId, optional object options, function callback)

                        //var captureVisibleTab = await tab.windowId.captureVisibleTab(null);

                        // Unchecked runtime.lastError while running tabs.captureVisibleTab: Failed to capture tab: unknown error

                        retry_captureVisibleTab:
                        var captureVisibleTab = await tabwindow.id.captureVisibleTab(options: new { format = "png" });


                        if (captureVisibleTab == null)
                        {
                            await Task.Delay(500);
                            Console.WriteLine("extension chrome.tabs.create done. about to capture... error");
                            goto retry_captureVisibleTab;
                        }

                        // extension captureVisibleTab {{ Length = 47743 }}
                        Console.WriteLine("extension captureVisibleTab " + new { captureVisibleTab.Length });

                        await Task.Delay(500);

                        // or just unload the window?
                        //await tab.id.remove();
                        await tabwindow.id.remove();


                        Console.WriteLine("extension to app chrome.tabs.create removed, jump back?");
                        #endregion

                        await default(HopToChromeApp);

                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeapp
                        Console.WriteLine("extension to app chrome.tabs.create removed, jump back done! did the strings make it?");
                        if (captureVisibleTab == null)
                            Console.WriteLine("app chrome.tabs.create removed, jump back done! did the strings make it? no");
                        else
                            Console.WriteLine("app chrome.tabs.create removed, jump back done! did the strings make it? yes " + new { captureVisibleTab.Length });



                        Console.WriteLine("app chrome.fileSystem.chooseEntry");

                        // not available in background?
                        // TypeError: Cannot read property 'chooseEntry' of undefined
                        // Unchecked runtime.lastError while running fileSystem.chooseEntry: Invalid calling page. This function can't be called from a background page.
                        //var dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });

                        // can we jump to extension to open our tab?



                        //// https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                        // defined at?
                        await default(HopToChromeAppWindow);

                        #region HopToChromeAppWindow
                        if (captureVisibleTab == null)
                            Console.WriteLine("appwindow chrome.tabs.create removed, jump back done! did the strings make it? no");
                        else
                            Console.WriteLine("appwindow chrome.tabs.create removed, jump back done! did the strings make it? yes " + new { captureVisibleTab.Length });


                        // 182ms appwindow chrome.fileSystem.chooseEntry
                        Console.WriteLine("appwindow chrome.fileSystem.chooseEntry");

                        // Unchecked runtime.lastError while running fileSystem.chooseEntry: User cancelled

                        Native.body.style.overflow = IStyle.OverflowEnum.auto;
                        Native.body.Clear();

                        chrome.app.window.current().show();

                        var icaptureVisibleTabFull = await new IHTMLImage { src = captureVisibleTab }.async.oncomplete;
                        ;

                        // 200, 80
                        // 1600, 880

                        // 1920x1080
                        var focusw = icaptureVisibleTabFull.width - 320;
                        var focush = icaptureVisibleTabFull.height - 200;

                        new IHTMLPre { new { focusw, focush } }.AttachToDocument();

                        var focus = new CanvasRenderingContext2D(focusw, focush);

                        focus.drawImage(icaptureVisibleTabFull, 200, 80, focusw, focush, 0, 0, focusw, focush);



                        // this is a thumbnail
                        var icaptureVisibleTab = new IHTMLImage { src = captureVisibleTab }.AttachToDocument();

                        new IStyle(icaptureVisibleTab)
                        {
                            width = "120px",
                            border = "1px dashed blue"
                        };



                        Native.document.documentElement.style.overflow = IStyle.OverflowEnum.auto;

                        if (dir == null)
                        {
                            await new IHTMLButton { "openDirectory" }.AttachToDocument().async.onclick;

                            dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });
                        }

                        var file = index.ToString().PadLeft(5, '0') + ".png";

                        new IHTMLPre { "WriteAllBytes... " + new { file } }.AttachToDocument();

                        //await dir.WriteAllBytes("0001.png", icaptureVisibleTabFull);

                        // chrome://blob-internals/
                        // those blobs wont go away...
                        // GC kicks in at 36 it seems.
                        await dir.WriteAllBytes(file, focus);
                        focus = null;

                        //                        [Window Title]
                        //Location is not available

                        //[Content]
                        //R:\ is not accessible.

                        //Logon failure: unknown user name or bad password.


                        //[OK]

                        //                        ---------------------------
                        //                        Restoring Network Connections
                        //---------------------------
                        //An error occurred while reconnecting R:
                        //                            to
                        //\\192.168.1.12\x$
                        //Microsoft Windows Network: The local device name is already in use.


                        //This connection has not been restored.
                        //---------------------------
                        //OK
                        //-------------------------- -


                        new IHTMLPre { "WriteAllBytes... done " + new { file } }.AttachToDocument();

                        index++;
                        #endregion




                        //Console.WriteLine("app chrome.app.window content loaded!");


                        //Console.WriteLine("app chrome.app.runtime.Launched ready to exit");
                        //await Task.Delay(3000);

                        //// wont work?
                        //w.close();

                        ////1343ms app chrome.runtime.MessageExternal {{ message = extension to app! }}
                        ////2015-08-22 15:18:44.738 view-source:53670 1357ms app chrome.runtime.ConnectExternal {{ id = jadmeogmbokffpkdfeiemjplohfgkidd }}
                        ////2015-08-22 15:18:52.314 view-source:53670 8933ms app chrome.app.runtime.Launched
                        ////2015-08-22 15:18:52.342 view-source:53670 8961ms app chrome.app.runtime.Launched exit
                        ////2015-08-22 15:18:52.348 view-source:53670 8967ms app  port.onMessage {{ message = chrome.tabs.Created {{ tab = [object Object] }} }}
                        ////2015-08-22 15:18:52.652 view-source:53670 9271ms app  port.onMessage {{ message = chrome.tabs.Updated  {{ tabId = 419, x = [object Object], tab = [object Object] }} }}
                        ////2015-08-22 15:18:52.690 view-source:53670 9308ms app  port.onMessage {{ message = chrome.tabs.Updated  {{ tabId = 419, x = [object Object], tab = [object Object] }} }}

                        //Console.WriteLine("app chrome.app.runtime.Launched exit");


                        // or tcp?
                        //await new IHTMLButton { "next take" }.AttachToDocument().async.onclick;


                        // var countdown = Stopwatch.StartNew();

                        //Error CS1929  'int' does not contain a definition for 'GetAwaiter' and the best extension method overload 'IXMLHttpRequestAsyncExtensions.GetAwaiter(IXMLHttpRequest)' requires a receiver of type 'IXMLHttpRequest'  ChromeHybridCapture Z:\jsc.svn\examples\javascript\chrome\hybrid\ChromeHybridCapture\ChromeHybridCapture\Application.cs 1141    IntelliSense

                        // script: error JSC1000: No implementation found for this native method, please implement [static System.TimeSpan.op_Subtraction(System.TimeSpan, System.TimeSpan)]

                        // TypeError: Cannot set property 'countdown' of null

                        //  Cannot set property 'sw' of null
                        countdown = Stopwatch.StartNew();

                        new IHTMLPre { () => "close to abort... " + countdown.ElapsedMilliseconds }.AttachToDocument();

                        // GC?
                        await Task.Delay(2000);

                        //await Task.WhenAny(
                        //      new IHTMLButton {
                        //          "click next take or wait "
                        //      }.AttachToDocument().async.onclick,
                        //      Task.Delay(1000)
                        //  );


                        //await
                        //  new IHTMLButton {
                        //          "click next take "
                        //  }.AttachToDocument().async.onclick;


                        new IHTMLPre { "preparing..." }.AttachToDocument();

                        Console.WriteLine("appwindow: appwindow to app");

                        await default(HopToChromeApp);

                        Console.WriteLine("app: appwindow to app");

                        goto nexttake;



                    };
                    #endregion


                    return;
                }
            }
            #endregion


            // running as regular web page?

            Console.WriteLine("running as content?");

            // were we loaded into chrome.app.window?


            //new IHTMLButton { "openDirectory" }.AttachToDocument().onclick += async delegate
            // {
            //     var dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });

            // };

        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            new { }.With(
                async delegate
            {
                var vid = "TXExg6Xj3aA";



                var thumbnail = $"https://img.youtube.com/vi/{vid}/0.jpg";

                var thumbnailImage = new IHTMLImage
                {
                    // 0 pixels? useless. will extension be able to bypass?
                    crossOrigin = "anonymous",

                    src = thumbnail
                };

                //					naturalHeight:
                //					90
                //naturalWidth:
                //					120

                // {{ thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, width = 0, height = 0 }}
                new IHTMLPre {
                    new { thumbnail, thumbnailImage.complete, thumbnailImage.naturalWidth, thumbnailImage.naturalHeight }
                }.AttachToDocument();

                await thumbnailImage.async.oncomplete;

                //thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = false, naturalWidth = 0, naturalHeight = 0 }}
                //		thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = true, naturalWidth = 120, naturalHeight = 90 }}


                //thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = true, naturalWidth = 0, naturalHeight = 0 }}
                thumbnailImage.style.SetSize(
                    thumbnailImage.naturalWidth, thumbnailImage.naturalHeight
                    );

                new IHTMLPre {
                    new { thumbnail, thumbnailImage.complete, thumbnailImage.width, thumbnailImage.naturalWidth, thumbnailImage.naturalHeight }
                }.AttachToDocument();

                //				{
                //					{
                //						thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = false, width = 0, height = 0 }}
                //{
                //							{
                //								thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = true, width = 0, height = 0 }}

                thumbnailImage.AttachToDocument();

                new IHTMLPre {
                    new { thumbnail, thumbnailImage.complete, thumbnailImage.naturalWidth, thumbnailImage.naturalHeight }
                }.AttachToDocument();

                var div = new IHTMLDiv
                {
                }.AttachToDocument();

                // 404 image does show as a background, can we copy it?
                new IStyle(div)
                {
                    width  = 120 + "px",
                    height = 90 + "px",
                    //overflow = IStyle.OverflowEnum.hidden,
                    //position = IStyle.PositionEnum.relative,
                    backgroundImage = $"url('{thumbnail}')",
                };

                //Image from origin 'https://img.youtube.com' has been blocked from loading by Cross - Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://192.168.1.12:15367' is therefore not allowed access.The response had HTTP status code 404.

                var idiv = (IHTMLImage)div;

                idiv.AttachToDocument();

                new IHTMLPre {
                    new { idiv.complete, idiv.width, idiv.naturalWidth, idiv.naturalHeight }
                }.AttachToDocument();
            }
                );

            //			Severity Code    Description Project File Line
            //Error CS7069  Reference to type 'TaskAwaiter<>' claims it is defined in 'mscorlib', but it could not be found TestCRCYTImage X:\jsc.svn\examples\javascript\test\TestCRCYTImage\TestCRCYTImage\Application.cs    56
        }
        public void Initialize(ExternalContext Context)
        {
            KnownMoviesFilter = e => true;

            //Context.Document.title = "2 token: " + Context.PrivateKey;

            // wtf? we cannot modify body without resetting our flash
            // http://dojotoolkit.org/forum/dojo-core-dojo-0-9/dojo-core-support/firefox-reloads-flash-when-portion-page-refreshed-using-a
            //Context.Document.body.style.overflow = "hidden";
            //Context.Document.body.style.backgroundColor = "black";
            //Context.Document.body.style.color = "white";

            #region ContainerForPosters
            var ContainerForPosters = new IHTMLDiv().AttachTo(Context);

            ContainerForPosters.style.position = "absolute";
            ContainerForPosters.style.width    = "100%";
            ContainerForPosters.style.height   = "100%";
            //ContainerForPosters.style.background = "black url('http://www.stripegenerator.com/generators/generate_stripes.php?fore=000000&h=30&w=6&p=7&back1=333333&back2=ff0000&gt=0&d=0&shadow=0&')";
            ContainerForPosters.style.backgroundColor = "black";
            ContainerForPosters.style.color           = "white";
            ContainerForPosters.style.textAlign       = "center";
            ContainerForPosters.style.overflow        = "auto";
            #endregion

            var PostersGroup = new IHTMLDiv().AttachTo(ContainerForPosters);
            var FooterGroup  = new IHTMLDiv().AttachTo(ContainerForPosters);

            var ButtonsOnRightEdge = new IHTMLSpan().AttachTo(Context);

            ButtonsOnRightEdge.style.Apply(
                s =>
            {
                s.position   = "absolute";
                s.marginLeft = "-8em";
                s.marginTop  = "-2em";
                s.top        = "100%";
                s.left       = "100%";
            }
                );

            ButtonsOnRightEdge.innerHTML =
                Info.GoogleGadget.AddImage.ToImageMiddle().ToLink(Info.GoogleGadget.AddToYourWebPageLink) + "&nbsp;" +
                Info.RSSImage.ToImageMiddle().ToLink(Info.BuzzBlogPost);

            var Toolbar = new IHTMLDiv
            {
                innerHTML = ""
            }.AttachTo(Context);


            Toolbar.style.Apply(
                s =>
            {
                s.position  = "absolute";
                s.marginTop = "-2em";
                s.top       = "100%";
                s.left      = "1em";
            }
                );

            #region ToggleScrollbar
            var ToggleScrollbar = new IHTMLSpan {
                innerHTML = "&raquo; toggle scrollbar"
            }.AttachTo(Toolbar);

            ToggleScrollbar.style.Apply(
                s =>
            {
                s.border          = "1px dotted white";
                s.cursor          = "pointer";
                s.backgroundColor = "black";
                s.color           = "white";
                s.marginLeft      = "1em";
            }
                );

            var ToggleScrollbarCounter = 0;
            ToggleScrollbar.onclick +=
                delegate
            {
                ToggleScrollbarCounter++;

                if (ToggleScrollbarCounter % 2 == 0)
                {
                    ContainerForPosters.style.overflow = "auto";
                }
                else
                {
                    ContainerForPosters.style.overflow = "hidden";
                }
            };
            #endregion



            #region Shadow
            var Shadow = new IHTMLDiv().AttachTo(Context);

            Shadow.style.position = "absolute";
            Shadow.style.left     = "0px";
            Shadow.style.top      = "0px";
            Shadow.style.width    = "100%";
            Shadow.style.height   = "100%";



            // http://www.stripegenerator.com/generators/generate_stripes.php?fore=000000&h=30&w=1&p=18&back1=171313&back2=ff0000&gt=0&d=0&shadow=5&


            Shadow.style.overflow = "hidden";
            // chrome does not support opacity?
            #endregion

            Func <string, int, double, IHTMLDiv> AddContainerShadow =
                (color, margin, opacity) =>
            {
                var ContainerShadow = new IHTMLDiv().AttachTo(Shadow);

                ContainerShadow.style.position        = "absolute";
                ContainerShadow.style.left            = "50%";
                ContainerShadow.style.top             = "50%";
                ContainerShadow.style.marginLeft      = (-400 - margin) + "px";
                ContainerShadow.style.marginTop       = (-300 - margin) + "px";
                ContainerShadow.style.backgroundColor = color;
                ContainerShadow.style.width           = (800 + margin * 2) + "px";
                ContainerShadow.style.height          = (600 + margin * 2) + "px";

                Action <double> ContainerShadow_set_opacity =
                    value =>
                {
                    ContainerShadow.style.opacity = "" + value;
                    ContainerShadow.style.filter  = "Alpha(Opacity=" + Convert.ToInt32(value * 100) + ")";
                };

                if (opacity < 1.0)
                {
                    ContainerShadow_set_opacity(opacity);
                }

                return(ContainerShadow);
            };

            AddContainerShadow("#000000", 800, 0.5);
            for (int i = 0; i < 8; i++)
            {
                AddContainerShadow("#000000", i * 4, 0.4);
            }

            var SuggestionDialog = InitializeSuggestMovie(Context, KnownMovies, Toolbar, Shadow);

            #region ContainerForVideoPlayer
            var ContainerForVideoPlayer = new IHTMLDiv().AttachTo(Context);

            ContainerForVideoPlayer.style.position        = "absolute";
            ContainerForVideoPlayer.style.left            = "50%";
            ContainerForVideoPlayer.style.top             = "50%";
            ContainerForVideoPlayer.style.marginLeft      = "-400px";
            ContainerForVideoPlayer.style.marginTop       = "-300px";
            ContainerForVideoPlayer.style.backgroundColor = "black";
            ContainerForVideoPlayer.style.width           = "800px";
            ContainerForVideoPlayer.style.height          = "400px";
            #endregion

            #region ContainerForDetails
            var ContainerForDetails = new IHTMLDiv().AttachTo(Context);

            ContainerForDetails.style.position   = "absolute";
            ContainerForDetails.style.left       = "50%";
            ContainerForDetails.style.top        = "50%";
            ContainerForDetails.style.marginLeft = "-400px";
            ContainerForDetails.style.marginTop  = "120px";
            //ContainerForDetails.style.backgroundColor = "red";
            ContainerForDetails.style.width    = "800px";
            ContainerForDetails.style.height   = "180px";
            ContainerForDetails.style.overflow = "auto";
            ContainerForDetails.style.color    = "white";

            //            ContainerForDetails.innerHTML = @"
            //<a href='http://www.imdb.com/title/tt0421715/'  title='Movie: The Curious Case of Benjamin Button 2008'><img  src='http://tinyurl.com/dh5xay'  align='right'  /></a>
            //<h2><a href='http://piratebay.org/torrent/4710971/El.Curioso.Caso.De.Benjamin.Button.[2009].[Spanish].[DVD-Screene'>Movie: The Curious Case of Benjamin Button 2008</a></h2>
            //<div title='raiting'>8.2/10</div>
            //<div title='runtime'>166 min, 1.36 GiB</div>
            //<div title='tagline'>Life isn't measured in minutes, but in moments</div>
            //<div title='genres'>Drama, Fantasy, Mystery, Romance</div>
            //<div title='episode'></div>
            //<a href='http://tinyurl.com/cjhc2g'  title='Movie: The Curious Case of Benjamin Button 2008'><img  src='http://static.thepiratebay.org/img/dl.gif'    /> El.Curioso.Caso.De.Benjamin.Button.[2009].[Spanish].[DVD-Screene</a>
            //";
            #endregion


            YouTubePlayer.Create(ContainerForVideoPlayer, 0, 0,
                                 VideoPlayer =>
            {
                MovieItem CurrentVideo = null;

                #region ShowVideo
                Action <MovieItem> ShowVideo =
                    k =>
                {
                    if (k == null)
                    {
                        VideoPlayer.pauseVideo();

                        VideoPlayer.width  = 0;
                        VideoPlayer.height = 0;

                        ContainerForVideoPlayer.style.top = "-100%";
                        //ContainerForVideoPlayer.style.display = "none";
                        Shadow.style.display           = "none";
                        SuggestionDialog.style.display = "none";

                        ContainerForDetails.style.display = "none";
                        Context.Document.title            = "zmovies";
                        return;
                    }

                    //ContainerForVideoPlayer.style.display = "block";

                    ContainerForVideoPlayer.style.top = "50%";

                    VideoPlayer.width  = 800;
                    VideoPlayer.height = 400;

                    if (CurrentVideo == k)
                    {
                        VideoPlayer.playVideo();
                    }
                    else
                    {
                        CurrentVideo = k;
                        VideoPlayer.loadVideoById(k.YouTubeKey);
                    }

                    Context.Document.title = k.SmartTitle;

                    Shadow.style.display = "block";
                    ContainerForDetails.style.display = "block";

                    ContainerForDetails.innerHTML = k.ToDetails();
                };
                #endregion

                ShowVideo(null);


                Shadow.style.cursor = "pointer";
                Shadow.onclick     +=
                    delegate
                {
                    ShowVideo(null);
                };

                // document.getElementById('" + context.Element.id + "')['" + addfeeditem.Token + @"'](result.feed.entries[i].content);

                //{
                //      "title":"Movie: Yes Man 2008",
                //      "link":"http://feedproxy.google.com/~r/zmovies/~3/qVZESWhb0vQ/dfvlm8",
                //      "author":"",
                //      "publishedDate":"",
                //      "contentSnippet":"\n \n \n \n \n \n \n\n\nMovie: Yes Man 2008\n7.2/10\n104 min, 704.11 MiB\nOne word can change everything.\nComedy|Romance\n\n ...",
                //      "content":"\n \n \n \n \u003cembed src\u003d\"http://www.youtube.com/v/Q-Z_CUYh2Sk\u0026amp;hl\u003den\u0026amp;fs\u003d1\" allowScriptAccess\u003d\"never\" allowFullScreen\u003d\"true\" width\u003d\"640\" height\u003d\"385\" wmode\u003d\"transparent\" type\u003d\"application/x-shockwave-flash\"\u003e\u003c/embed\u003e\n \n \n\u003ca href\u003d\"http://www.youtube.com/v/Q-Z_CUYh2Sk\u0026amp;hl\u003den\u0026amp;fs\u003d1\"\u003e\u003cimg alt\u003d\"Q-Z_CUYh2Sk\" src\u003d\"http://img.youtube.com/vi/Q-Z_CUYh2Sk/0.jpg\" align\u003d\"left\"\u003e\u003c/a\u003e\n\u003ca href\u003d\"http://www.imdb.com/title/tt1068680/\" title\u003d\"Movie: Yes Man 2008\"\u003e\u003cimg src\u003d\"http://tinyurl.com/cuc2uo\" align\u003d\"right\"\u003e\u003c/a\u003e\n\u003ch2\u003e\u003ca href\u003d\"http://piratebay.org/torrent/4797620/Yes.Man.2009.DVDRip.XviD-NoRar_\"\u003eMovie: Yes Man 2008\u003c/a\u003e\u003c/h2\u003e\n\u003cdiv title\u003d\"raiting\"\u003e7.2/10\u003c/div\u003e\n\u003cdiv title\u003d\"runtime\"\u003e104 min, 704.11 MiB\u003c/div\u003e\n\u003cdiv title\u003d\"tagline\"\u003eOne word can change everything.\u003c/div\u003e\n\u003cdiv title\u003d\"genres\"\u003eComedy|Romance\u003c/div\u003e\n\u003cdiv title\u003d\"episode\"\u003e\u003c/div\u003e\n\u003ca href\u003d\"http://tinyurl.com/dfvlm8\" title\u003d\"Movie: Yes Man 2008\"\u003e\u003cimg src\u003d\"http://static.thepiratebay.org/img/dl.gif\"\u003e Yes.Man.2009.DVDRip.XviD-NoRar™\u003c/a\u003e\u003cimg src\u003d\"http://feeds2.feedburner.com/~r/zmovies/~4/qVZESWhb0vQ\" height\u003d\"1\" width\u003d\"1\"\u003e",
                //      "categories":[
                //         "Movies",
                //         "Comedy",
                //         "Romance"
                //      ]
                //   },



                VideoPlayer.onStateChange +=
                    state =>
                {
                    if (state == YouTubePlayer.States.ended)
                    {
                        ShowVideo(KnownMovies.Where(x => KnownMoviesFilter(x.Movie)).Random().Movie);
                    }
                };

                var PendingList = new List <MovieItem>();

                Action PendingListToPosters =
                    delegate
                {
                    while (PendingList.Count > 0)
                    {
                        var GroupLeader = PendingList.First();

                        PendingList.Remove(GroupLeader);

                        Func <MovieItem, bool> Filter = k => k.IMDBTagline == GroupLeader.IMDBTagline;

                        if (string.IsNullOrEmpty(GroupLeader.IMDBTagline))
                        {
                            Filter = k => k.SmartTitleWithoutQuotes == GroupLeader.SmartTitleWithoutQuotes;
                        }

                        var GroupMembers = PendingList.Where(Filter).ToArray();

                        GroupMembers.ForEach(k => PendingList.Remove(k));

                        var Group = new[] { GroupLeader }.Concat(GroupMembers).ToArray();

                        foreach (var n in Group)
                        {
                            var poster = new IHTMLImage
                            {
                                src   = n.PosterLink,
                                alt   = " ",
                                title = n.SmartTitleWithoutQuotes + " | " + n.TorrentName + " | " + n.FeedIndex + " of " + n.FeedCapacity
                            }.AttachTo(PostersGroup);

                            if (n != GroupLeader)
                            {
                                poster.style.marginLeft = "-3em";
                            }

                            KnownMovies.Add(
                                new MovieItemWithPoster
                            {
                                Movie  = n,
                                Poster = poster
                            }
                                );

                            poster.style.cursor = "pointer";
                            poster.onclick     +=
                                delegate
                            {
                                ShowVideo(n);
                            };
                        }
                    }
                };


                var GFeedReader = Context.ToExternal <object[]>(
                    data =>
                {
                    var Title        = (string)data[0];
                    var Link         = (string)data[1];
                    var Content      = (string)data[2];
                    var Categories   = (string[])data[3];
                    var FeedIndex    = (int)data[4];
                    var FeedCapacity = (int)data[5];

                    Content.ParseMovieItem(
                        n =>
                    {
                        // use feedburner link for stats
                        n.TorrentLink  = Link;
                        n.FeedIndex    = FeedIndex;
                        n.FeedCapacity = FeedCapacity;

                        PendingList.Add(n);

                        if (FeedIndex + 1 == FeedCapacity)
                        {
                            PendingListToPosters();
                        }
                    }
                        );
                }
                    );

                1.ExternalAtDelay(@"

window['piper'] = function (dummy, result)
{
    for (var i=0; i<result.feed.entries.length; i++) 
    {
		var _x = result.feed.entries[i];
       if (_x.content) 
	   {
			var _v = [_x.title, _x.link, _x.content, _x.categories, i, result.feed.entries.length];
			document.getElementById('"             + Context.Element.id + "')['" + GFeedReader + @"'](_v);
       }
    }
};

					"                    );

                // <script src='http://www.google.com/uds/Gfeeds?callback=piper&scoring=h&context=0&num=100&hl=en&output=json&q=http://feeds2.feedburner.com/zmovies&v=1.0&nocache=0'></script>

                // google seems to cache 250 items

                new IHTMLScript
                {
                    type = "text/javascript",
                    src  = "http://www.google.com/uds/Gfeeds?callback=piper&scoring=h&context=0&num=250&hl=en&output=json&q=http://feeds2.feedburner.com/zmovies&v=1.0&nocache=0"
                }.AttachTo(Context);

                // http://flagcounter.com/

                // rect (top, right, bottom, left)

                FooterGroup.innerHTML =
                    @"
					<div style='padding: 4em;'>

<center>
						<div style='width:420px;text-align:center;margin:0;padding:0;'>
							<embed src='http://widgets.amung.us/flash/v2map.swf' 
								quality='high' pluginspage='http://www.macromedia.com/go/getflashplayer' 
								wmode='transparent'
								allowScriptAccess='always' 
								allowNetworking='all' type='application/x-shockwave-flash' 
								flashvars='wausitehash=eop2ht6aucqf&map=heatmap&pin=star-blue&link=no' 
								width='420' height='210' />
							<div style='width:420px;height:210px;position:relative;margin:0 auto;margin-top:-210px;'><a href='http://whos.amung.us/stats/eop2ht6aucqf/'><img src='http://maps.amung.us/ping/eop2ht6aucqf.gif' border='0' width='420' height='210' /></a></div>
						</div>
</center>
<br />
						<div>
						<a href='http://s03.flagcounter.com/more/Y7bi'><img src='http://s03.flagcounter.com/count/Y7bi/bg=000000/txt=FFFFFF/border=CCCCCC/columns=8/maxflags=32/viewers=3/labels=0/pageviews=1/' alt='free counters' border='0'></a>
						</div>
					</div>
										"                                        ;
            }
                                 );
        }
        public Application(IApp page)
        {
            // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeTabsExperiment\ChromeTabsExperiment\Application.cs
            Console.WriteLine(" enter Application");


            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_tabs = self_chrome.tabs;

            //if (self_chrome_tabs == null)
            //	return;


            //	....488: { SourceMethod = Void.ctor(ChromeTabsCapture.HTML.Pages.IApp), i = [0x00ba] brtrue.s + 0 - 1 }
            //1984:02:01 RewriteToAssembly error: System.ArgumentException: Value does not fall within the expected range.
            //at jsc.ILInstruction.ByOffset(Int32 i) in X:\jsc.internal.git\compiler\jsc\CodeModel\ILInstruction.cs:line 1184
            //at jsc.ILInstruction.get_BranchTargets() in X:\jsc.internal.git\compiler\jsc\CodeModel\ILInstruction.cs:line 1225

            #region self_chrome_tabs
            if (self_chrome_tabs != null)
            {
                Console.WriteLine("self_chrome_tabs");

                //chrome.runtime.Startup +=
                //chrome.runtime.Installed +=



                //70ms chrome.management.getAll
                //2015-08-22 13:41:33.591 view-source:53670 98ms chrome.management.getAll {{ Length = 28 }}
                //2015-08-22 13:41:33.594 view-source:53670 101ms ExtensionInfo {{ id = aemlnmcokphbneegoefdckonejmknohh, name = ChromeTabsCapture }}
                //2015-08-22 13:41:33.597 view-source:53670 104ms ExtensionInfo {{ id = apdfllckaahabafndbhieahigkjlhalf, name = Google Drive }}
                //2015-08-22 13:41:33.599 view-source:53670 106ms ExtensionInfo {{ id = blpcfgokakmgnkcojhhkbfbldkacnbeo, name = YouTube }}
                //2015-08-22 13:41:33.602 view-source:53670 109ms ExtensionInfo {{ id = cgnjcccfcjhdnbfgjgllglbhfcgndmea, name = WebGLHZBlendCharacter }}
                //2015-08-22 13:41:33.604 view-source:53670 111ms ExtensionInfo {{ id = coobgpohoikkiipiblmjeljniedjpjpf, name = Google Search }}
                //2015-08-22 13:41:33.608 view-source:53670 114ms ExtensionInfo {{ id = fkgibadjpabiongmgoeomdbcefhabmah, name = ChromeCaptureToFile.Application.exe }}
                //2015-08-22 13:41:33.610 view-source:53670 117ms ExtensionInfo {{ id = ghbmnnjooekpmoecnnnilnnbdlolhkhi, name = Google Docs Offline }}
                //2015-08-22 13:41:33.612 view-source:53670 119ms ExtensionInfo {{ id = haebnnbpedcbhciplfhjjkbafijpncjl, name = TinEye Reverse Image Search }}
                //2015-08-22 13:41:33.614 view-source:53670 121ms ExtensionInfo {{ id = lchcahaldakdnjlkchkgncecgpcnabgo, name = Heat Zeeker }}
                //2015-08-22 13:41:33.616 view-source:53670 123ms ExtensionInfo {{ id = nhkcfbkpodjkallcfebgihcoglfaniep, name = freenode irc }}
                //2015-08-22 13:41:33.619 view-source:53670 126ms ExtensionInfo {{ id = ogmpedngmnolclkmlpcdgmfonlagkejp, name = Private Joe: Urban Warfare }}
                //2015-08-22 13:41:33.621 view-source:53670 128ms ExtensionInfo {{ id = pcklgpcdddecpmkiinpkhehanbijjepn, name = idea-remixer }}
                //2015-08-22 13:41:33.624 view-source:53670 131ms ExtensionInfo {{ id = pjkljhegncpnkpknbcohdijeoejaedia, name = Gmail }}
                //2015-08-22 13:41:33.626 view-source:53670 133ms ExtensionInfo {{ id = plgmlhohecdddhbmmkncjdmlhcmaachm, name = draw.io (Legacy) }}
                //2015-08-22 13:41:33.629 view-source:53670 136ms ExtensionInfo {{ id = aapbdbdomjkkjkaonfhkkikfgjllcleb, name = Google Translate }}
                //2015-08-22 13:41:33.631 view-source:53670 138ms ExtensionInfo {{ id = bcfddoencoiedfjgepnlhcpfikgaogdg, name = QR-Code Tag Extension }}
                //2015-08-22 13:41:33.633 view-source:53670 139ms ExtensionInfo {{ id = coblegoildgpecccijneplifmeghcgip, name = Web Cache }}
                //2015-08-22 13:41:33.635 view-source:53670 142ms ExtensionInfo {{ id = ganlifbpkcplnldliibcbegplfmcfigp, name = Collusion for Chrome }}
                //2015-08-22 13:41:33.638 view-source:53670 145ms ExtensionInfo {{ id = gighmmpiobklfepjocnamgkkbiglidom, name = AdBlock }}
                //2015-08-22 13:41:33.640 view-source:53670 147ms ExtensionInfo {{ id = iiabebggdceojiejhopnopmbkgandhha, name = Operation Heat Zeeker }}
                //2015-08-22 13:41:33.642 view-source:53670 149ms ExtensionInfo {{ id = jkgfnfnagdnjicmonpfhhdnkdjgjdamo, name = Avalon Spider Solitaire }}
                //2015-08-22 13:41:33.644 view-source:53670 151ms ExtensionInfo {{ id = kdifgkljkjhpflhalpkhehlldfakggdi, name = my.jsc-solutions.net }}
                //2015-08-22 13:41:33.646 view-source:53670 153ms ExtensionInfo {{ id = lmjegmlicamnimmfhcmpkclmigmmcbeh, name = Application Launcher for Drive (by Google) }}
                //2015-08-22 13:41:33.648 view-source:53670 155ms ExtensionInfo {{ id = mmfbcljfglbokpmkimbfghdkjmjhdgbg, name = Text }}
                //2015-08-22 13:41:33.650 view-source:53670 157ms ExtensionInfo {{ id = molncoemjfmpgdkbdlbjmhlcgniigdnf, name = Project Naptha }}
                //2015-08-22 13:41:33.652 view-source:53670 159ms ExtensionInfo {{ id = ogkcjmbhnfmlnielkjhedpcjomeaghda, name = WebGL Inspector }}
                //2015-08-22 13:41:33.653 view-source:53670 160ms ExtensionInfo {{ id = pkngagjebplcgimojegcakmnlggmcjlc, name = LBA Redux }}
                //2015-08-22 13:41:33.657 view-source:53670 164ms ExtensionInfo {{ id = ppmibgfeefcglejjlpeihfdimbkfbbnm, name = Change HTTP Request Header }}

                Action<string> __ChromeCaptureToFile_Application_sendMessage = delegate { };

                new { }.With(
                    async delegate
                    {
                        //  TypeError: chrome.management.getAll is not a function

                        Console.WriteLine("chrome.management.getAll");
                        var extensions = await chrome.management.getAll();

                        Console.WriteLine("chrome.management.getAll " + new { extensions.Length });
                        // https://developer.chrome.com/extensions/management#type-ExtensionInfo

                        //                        view - source:53670 69ms chrome.management.getAll
                        //2015 - 08 - 22 13:34:13.514 view - source:53670 89ms chrome.management.getAll { { Length = 28 } }
                        //                        2015 - 08 - 22 13:34:13.518 view - source:53670 93ms ExtensionInfo { { item = [object Object] } }

                        foreach (var item in extensions)
                        {
                            //Console.WriteLine("ExtensionInfo " + new { item });
                            //Console.WriteLine("ExtensionInfo " + new { item.id, item.name });

                            //2015-08-22 13:41:33.608 view-source:53670 114ms ExtensionInfo {{ id = fkgibadjpabiongmgoeomdbcefhabmah, name = ChromeCaptureToFile.Application.exe }}

                            // typeof(self) ?
                            if (item.name.StartsWith("ChromeCaptureToFile.Application"))
                            {
                                var __item = item;

                                // we will also know when it reloads? we have to reconnect then?

                                __ChromeCaptureToFile_Application_sendMessage = message =>
                                {
                                    Console.WriteLine(message + new { __item.id, __item.name });

                                    chrome.runtime.sendMessage(item.id, message, null);
                                };

                                chrome.runtime.sendMessage(item.id, "extension to app!", null);
                            }
                        }

                    }
                    );

                chrome.tabs.Created += async tab =>
                {
                    Console.WriteLine(" chrome.tabs.Created " + new { tab });

                };

                chrome.tabs.Updated += async (tabId, x, tab) =>
                {
                    //  Updated {{ i = 0, x = null, tab = null }}

                    Console.WriteLine("Updated " + new { tabId, x, tab });

                    // why the duck is it null?
                    if (tab == null)
                        tab = await chrome.tabs.get(tabId);

                    Console.WriteLine("Updated 2 " + new { tabId, x, tab });


                    // chrome://newtab/

                    //  TypeError: Cannot read property 'url' of null

                    if (tab == null)
                        return;

                    if (tab.url.StartsWith("chrome-devtools://"))
                        return;

                    if (tab.url.StartsWith("chrome://"))
                        return;


                    // while running tabs.insertCSS: The extensions gallery cannot be scripted.
                    if (tab.url.StartsWith("https://chrome.google.com/webstore/"))
                        return;


                    if (tab.status != "complete")
                        return;

                    //new chrome.Notification
                    //{
                    //	Message = "chrome.tabs.Updated " + new
                    //	{
                    //		tab.id,
                    //		tab.url,
                    //		tab.status,
                    //		tab.title
                    //	}
                    //};


                    // while running tabs.insertCSS: The tab was closed.

                    // 		public static Task<object> insertCSS(this TabIdInteger tabId, object details);
                    // public static void insertCSS(this TabIdInteger tabId, object details, IFunction callback);


                    // for some sites the bar wont show as they html element height is 0?



                    // where is the hop to iframe?
                    // X:\jsc.svn\examples\javascript\Test\TestSwitchToIFrame\TestSwitchToIFrame\Application.cs


                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201504/20150403


                    // can we goto back before to the hop?

                    // Error: Invocation of form pageAction.show(object) doesn't match definition pageAction.show(integer tabId)
                    //chrome.pageAction.show((TabIdInteger)(object)tabId);
                    chrome.pageAction.show(tabId);

                    //chrome.pageAction.Clicked += async delegate
                    new { }.With(async delegate
                   {
                       await tab.pageAction.async.onclick;


                       __ChromeCaptureToFile_Application_sendMessage(" chrome.pageAction.Clicked ");


                       string captureVisibleTabImageSourceLengthString = "?";

                       Console.WriteLine("enter Clicked");

                       //chrome.pageAction.hide((TabIdInteger)(object)tabId);

                       // TypeError: Cannot read property 'hide' of undefined
                       chrome.pageAction.hide(tabId);

                       // Extension manifest must request permission to access this host.
                       // jpg data url!
                       var captureVisibleTab = (string)await chrome.tabs.captureVisibleTab(null, null);

                       var captureVisibleTabImage = new IHTMLImage { src = captureVisibleTab };
                       await captureVisibleTabImage.async.oncomplete;

                       captureVisibleTab = null;

                       var captureVisibleTabImageSource = captureVisibleTabImage.toDataURL();

                       // before await delay {{ captureVisibleTabImageSourceLength = 354874 }}
                       var captureVisibleTabImageSourceLength = captureVisibleTabImageSource.Length;
                       captureVisibleTabImageSourceLengthString = captureVisibleTabImageSourceLength + "";
                       captureVisibleTabImageSource = null;


                       Console.WriteLine("before await delay " + new { captureVisibleTabImageSourceLength });
                       // statemachine fixup? off by one?
                       await Task.Delay(1);

                       new { }.With(
                           async delegate
                           {
                               Console.WriteLine("before await HopToChromeTab");
                               await (HopToChromeTab)tab;

                               //Console.WriteLine("after await HopToChromeTab " + new { captureVisibleTabImageSource.Length });

                               //b.innerText = "pageAction! " + new { captureVisibleTabImageSource.Length };

                               Console.WriteLine("after await HopToChromeTab ");

                               // 4200ms {{ AsyncStateMachineSourceField = _captureVisibleTabImageSourceLengthString_5__5, value = 385538 }}

                               // 2038ms {{ AsyncStateMachineSourceField = _captureVisibleTabImageSourceLengthString_5__1 }}
                               // ??? why wont it make it?

                               // cuz we are not reading the sent variables.
                               //b.innerText = "pageAction! " + new { captureVisibleTabImageSourceLengthString, captureVisibleTabImageSourceLength };
                               //b.innerText = "pageAction! " + new { captureVisibleTabImageSourceLengthString, captureVisibleTabImageSourceLength };
                               //b.innerText = "pageAction! only state seems to be synchronized here... for now... ";
                               b.innerText = "pageAction! about to save!";
                           }
                       );

                       // well. can we save it?
                       // TypeError: Cannot read property 'chooseEntry' of undefined
                       // {"fileSystem": ["write", "retainEntries", "directory"]} 

                       // not available for tabs. need an app for that.
                       //var dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });


                       //await dir.WriteAllBytes("0001.png", captureVisibleTabImage);

                   });

                    // keep simple scope
                    var scope_tabId = tabId;

                    //await (HopToChromeTab)tab.id;
                    await (HopToChromeTab)tab;
                    //await tab.id;

                    // are we now on the tab?
                    // can we jump back?

                    // what about jumping with files/uploads?
                    Console.WriteLine("// are we now on the tab yet?");

                    Native.body.style.borderLeft = "1em solid red";
                    Native.document.documentElement.style.borderLeft = "1em solid cyan";




                    // lets start monitoring
                    // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150821

                    //chrome.tabs.captureVisibleTab

                    //chrome.pageAction.show(tab.)
                    // what api is available if we are in th tab context?

                    //var b = new IHTMLButton { "capture" }.AttachToDocument();
                    ChromeTabsCapture.Application.b = new IHTMLButton { "click pageAction above. HUD " + new { scope_tabId } }.AttachTo(Native.document.documentElement);

                    Console.WriteLine("do you see the HUD button?");

                    b.style.SetLocation(4, 4);
                    b.css.disabled.style.backgroundColor = "red";

                    //             488: { SourceMethod = Void.ctor(ChromeTabsCapture.HTML.Pages.IApp), i = [0x00eb] brtrue.s + 0 - 1 }
                    //             2bf8: 02:01:1e RewriteToAssembly error: System.ArgumentException: Value does not fall within the expected range.
                    //at jsc.ILInstruction.ByOffset(Int32 i) in x:\jsc.internal.git\compiler\jsc\CodeModel\ILInstruction.cs:line 1188
                    //at jsc.ILInstruction.get_BranchTargets() in x:\jsc.internal.git\compiler\jsc\CodeModel\ILInstruction.cs:line 1229
                    //at jsc.ILInstruction.get_BranchSources() in x:\jsc.internal.git\compiler\jsc\CodeModel\ILInstruction.cs:line 1205
                    //at jsc.ILInstruction.get_IsFlowBreak() in x:\jsc.internal.git\compiler\jsc\CodeModel\ILInstruction.cs:line 863
                    //at jsc.ILFlow.NextInstructionBranch() in x:\jsc.internal.git\compiler\jsc\CodeModel\ILFlow.cs:line 585

                    //b.onclick += delegate
                    //{
                    //    b.disabled = true;

                    //    Native.body.style.borderLeft = "1em solid red";

                    //    // would the compiler let the chome extension know it has been updated?

                    //};

                    await b.async.onclick;


                    b.disabled = true;

                    //Native.body.style.borderLeft = "1em solid red";

                    //  TypeError: Cannot read property 'captureVisibleTab' of undefined

                    //var captureVisibleTab = await chrome.tabs.captureVisibleTab(null, null);

                    //b.innerText = new { captureVisibleTab }.ToString();



                };



                return;
            }
            #endregion


            // we made the jump?
            // need it to compile. why???
            ;
            //Native.body.style.borderLeft = "1em solid red";

            // yes we did. can we talk to the chrome extension?

            // lets do some SETI

            // The runtime.onMessage event is fired in each content script running in the specified tab for the current extension.

            // Severity	Code	Description	Project	File	Line
            //Error       'runtime.onMessage' is inaccessible due to its protection level ChromeTabsCapture X:\jsc.svn\examples\javascript\chrome\extensions\ChromeTabsCapture\ChromeTabsCapture\Application.cs 272

            // public static event System.Action<object, object, object> Message

            #region chrome.runtime.Message
            chrome.runtime.Message += (object message, chrome.MessageSender sender, IFunction sendResponse) =>
            {
                var s = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)message;

                // 59ms onmessage {{ message = hello, id = aemlnmcokphbneegoefdckonejmknohh }}
                Console.WriteLine("xonmessage " + new { s.state, sender.id });
                //Native.body.style.borderLeft = "1px solid blue";

                #region xAsyncStateMachineType
                var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
                    item =>
                    {
                        // safety check 1

                        //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

                        var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(item);
                        if (xisIAsyncStateMachine)
                        {
                            //Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

                            return item.FullName == s.TypeName;
                        }

                        return false;
                    }
                );
                #endregion


                var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
                var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

                var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

                #region 1__state
                xAsyncStateMachineType.GetFields(
                          System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
                      ).WithEach(
                       AsyncStateMachineSourceField =>
                       {

                           Console.WriteLine(new { AsyncStateMachineSourceField });

                           if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
                           {
                               AsyncStateMachineSourceField.SetValue(
                                   NewStateMachineI,
                                   s.state
                                );
                           }


                       }
                  );
                #endregion

                NewStateMachineI.MoveNext();

                //Task.Delay(1000).ContinueWith(
                //	delegate
                //	{
                //		sendResponse.apply(null, "response");
                //	}
                //);

            };
            #endregion


            //         Native.window.onmessage += e =>
            //{

            //};
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // certmgr.msc

            Native.document.icon = null;


            //#1a < 001a 0x166c bytes
            //#05 < 0005 0x0576 bytes
            new IHTMLButton { "go wild" }.AttachToDocument()
            //.WhenClicked(

            .With(
            //async
            delegate
                {
                    // X-DevTools-Emulate-Network-Conditions-Client-Id:7C66E13B-14BC-4006-BAC1-9EE2D3AC0591

                    // can we disable the implicit favicon request?
                    //Native.document.icon = new IHTMLImage { };
                    // #1a < 001a 0x0b04 bytes


                    //Native.document.icon.AttachToDocument();

                    // favicon to fail?
                    //await Task.Delay(300);
                    //await Native.window.async.onframe;


                    // there is a secondary / request?
                    //return;

                    //Native.window.requestAnimationFrame += delegate
                    {

                        // https://code.google.com/p/chromium/issues/detail?id=543982&thanks=543982&ts=1444983390

                        Console.WriteLine("about to init sides...");
                        #region sides
                        var sides = new IHTMLImage[]
                        {
                            new azi_px(),

                                new azi_nx(),

                                new azi_py(),

                                new azi_ny(),

                                new azi_pz(),


                            // #18 < 0018 0x0550 bytes

                            new azi_nz(),
                        };
                        #endregion
                        Console.WriteLine("about to init CSS3DObject sides... did chrome just abuse TCP ?");

                    };

                }
                );

        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            FormStyler.AtFormCreated = FormStylerLikeFloat.LikeFloat;

            // http://html5doctor.com/drag-and-drop-to-server/

            #region ondrop
            Native.document.body.ondragover +=
                evt =>
                {
                    evt.stopPropagation();
                    evt.preventDefault();

                    evt.dataTransfer.dropEffect = "copy"; // Explicitly show this is a copy.


                    page.Header.style.color = JSColor.Green;


                    var types = evt.dataTransfer.types == null ? 0 : evt.dataTransfer.types.Length;

                    if (evt.dataTransfer.types != null)
                        foreach (var type in evt.dataTransfer.types.AsEnumerable())
                        {
                            Console.WriteLine(
                                new { type }
                                );
                        }

                    var items = evt.dataTransfer.items == null ? 0u : evt.dataTransfer.items.length;
                    var files = evt.dataTransfer.files == null ? 0u : evt.dataTransfer.files.length;



                    Console.WriteLine("ondragover: " +
                        new
                        {

                            types,
                            items,
                            files
                        }
                    );
                };


            Native.document.body.ondragleave +=
                delegate
                {
                    page.Header.style.color = JSColor.None;
                };

            #region DetectCanvasFromBytesExperiment
            Action<Form, WebBrowser, string, string, long> DetectCanvasFromBytesExperiment =
                (ff, web, ContentValue, src, ContentBytesLength) =>
                {
                    web.Navigated +=
                           async delegate
                           {
                               if (ContentValue != "png.png")
                                   return;

                               // X:\jsc.svn\examples\javascript\canvas\CanvasFromBytes\CanvasFromBytes\Application.cs
                               //Console.WriteLine("interesting, is it one of ours? " + new { ContentValue });
                               ff.Text = "interesting, is it one of ours? " + new { ContentValue };

                               var csrci = new IHTMLImage { src = src };

                               //await csrci.async.onlo
                               await csrci;

                               if (csrci.width != csrci.height)
                                   return;


                               var w = csrci.width;


                               // do the reverse
                               var z = new CanvasRenderingContext2D(w, w);
                               z.drawImage(csrci, 0, 0, w, w);
                               //z.canvas.AttachToDocument();

                               // whats the bytes?

                               var zbytes = z.bytes;

                               ff.Text = "will decode " + new { zbytes.Length, ContentBytesLength }.ToString();

                               #region decode
                               var decodebytes = await Task.Factory.StartNew(
                                   new { zbytes },
                                   scope =>
                                   {
                                       // Native.Console.WriteLine += ?

                                       // { Length = 2053956, u4 = 3c68746d } 

                                       Console.WriteLine(
                                        new
                                        {
                                            scope.zbytes.Length,

                                            u4 = new[] { 
                                            scope.zbytes[0 * 4 + 0],
                                            scope.zbytes[0 * 4 +1],
                                            scope.zbytes[0 * 4 +2],
                                            scope.zbytes[0 * 4 +3]
                                        }.ToHexString()
                                        }
                                       );


                                       // Uncaught Error: InvalidOperationException: { MethodToken = dAAABv_a4OTKgLfLC20SaJA } function is not available at { href =

                                       var wwbytes = new byte[scope.zbytes.Length / 4];
                                       var wi = 0;

                                       for (int i = 0; i < scope.zbytes.Length; i += 4)
                                       {
                                           // that be the red
                                           //wwbytes[wi] = scope.zbytes[i];

                                           // bet we need alpha
                                           wwbytes[wi] = scope.zbytes[i + 3];
                                           wi++;
                                       }



                                       return wwbytes;
                                   }
                               );
                               #endregion


                               var html = Encoding.UTF8.GetString(decodebytes);

                               ff.Text = "decoded " + new { html.Length, ContentBytesLength }.ToString();

                               //Console.WriteLine(new { html });


                               // um hide old data.
                               web.Hide();

                               var xweb = new WebBrowser { Dock = DockStyle.Fill };
                               xweb.AttachTo(ff);
                               xweb.DocumentText = html;
                               ff.Text = "!decoded " + new { html.Length, ContentBytesLength }.ToString();
                           };

                };
            #endregion


            Native.document.body.ondrop +=
                evt =>
                {
                    //if (evt.dataTransfer == null)
                    //    return;

                    var types = evt.dataTransfer.types == null ? 0 : evt.dataTransfer.types.Length;

                    var items = evt.dataTransfer.items == null ? 0u : evt.dataTransfer.items.length;
                    var files = evt.dataTransfer.files == null ? 0u : evt.dataTransfer.files.length;


                    Console.WriteLine("ondrop: " +
                        new
                        {

                            types,
                            items,
                            files
                        }
                    );


                    page.Header.style.color = JSColor.None;


                    //var xfiles = evt.dataTransfer.files.AsEnumerable().Concat(
                    //    from x in evt.dataTransfer.items.AsEnumerable()
                    //    let f = x.getAsFile()
                    //    where f != null
                    //    select f
                    //);

                    #region DataTable
                    if (evt.dataTransfer.items != null)
                    {
                        // X:\jsc.svn\examples\javascript\DragDataTableIntoCSVFile\DragDataTableIntoCSVFile\Application.cs

                        evt.dataTransfer.items.AsEnumerable().Where(
                            x =>

                                x.type.ToLower() ==

                                // let jsc type system sort it out?
                                // how much reflection does jsc give us nowadays?
                                typeof(DataTable).Name.ToLower()

                        ).WithEach(
                            async x =>
                            {
                                // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dfnReturnLink-0
                                var DataTable_xml = await x.getAsString();

                                var DataTable = StringConversionsForDataTable.ConvertFromString(DataTable_xml);

                                var ff = new Form { Text = new { typeof(DataTable).Name }.ToString() };

                                var g = new DataGridView { DataSource = DataTable, Dock = DockStyle.Fill };

                                ff.Controls.Add(g);


                                ff.Show();

                            }
                        );
                    }
                    #endregion

                    #region files
                    evt.dataTransfer.files.AsEnumerable().WithEachIndex(
                        (f, index) =>
                        {
                            Console.WriteLine(
                                new
                                {

                                    f.name,
                                    f.size,
                                    f.lastModifiedDate
                                }
                            );

                            var ff = new Form();
                            ff.PopupInsteadOfClosing(HandleFormClosing: false);



                            ff.Text = new { f.type, f.name, f.size }.ToString();


                            ff.Show();

                            ff.MoveTo(
                                evt.CursorX + 32 * index,
                                evt.CursorY + 24 * index
                            );

                            var fc = ff.GetHTMLTargetContainer();

                            fc.title = ff.Text;

                            #region image
                            var i = default(IHTMLImage);

                            if (f.type.StartsWith("image/"))
                            {
                                // um would we have a timing issue here?
                                f.ToDataURLAsync(
                                    src =>
                                    {
                                        i = new IHTMLImage { src = src }.AttachTo(fc);
                                        i.style.width = "100%";

                                        i.InvokeOnComplete(
                                            delegate
                                            {

                                                ff.ClientSize = new System.Drawing.Size(
                                                    // keep it reasonable!
                                                    i.width.Min(600),
                                                    i.height.Min(400)
                                                );

                                            }
                                        );
                                    }
                                );
                            }
                            #endregion

                            // http://html5doctor.com/drag-and-drop-to-server/

#if FUTURE
                            service.XUpload(f, delegate { });
#endif


                            var d = new FormData();

                            d.append("foo", f, f.name);

                            var xhr = new IXMLHttpRequest();

                            xhr.open(ScriptCoreLib.Shared.HTTPMethodEnum.POST, "/upload");

                            #region InvokeOnComplete
                            xhr.InvokeOnComplete(
                                delegate
                                {
                                    Console.WriteLine("upload complete!");

                                    SystemSounds.Beep.Play();

                                    //Console.Beep();
                                    XElement.Parse(xhr.responseText).Elements("ContentKey").WithEach(
                                        ContentKey =>
                                        {
                                            var __ContentKey = (Table1_ContentKey)int.Parse(ContentKey.Value);

                                            var web = new WebBrowser { Dock = DockStyle.Fill };

                                            web.Hide();
                                            web.AttachTo(ff);


                                            var src = "/io/" + ContentKey.Value;

                                            if (i == null)
                                            {
                                                web.Show();
                                            }
                                            else
                                            {
                                                web.Navigated +=
                                                    delegate
                                                    {
                                                        i.Orphanize();
                                                        web.Show();
                                                    };
                                            }


                                            // "X:\jsc.svn\examples\javascript\canvas\CanvasFromBytes\png.png"
                                            DetectCanvasFromBytesExperiment(
                                                ff,
                                                web,
                                                 f.name,
                                                src,
                                               (long)f.size
                                            );

                                            web.Navigate(src);


                                            //if (i != null)
                                            //{
                                            //    i.src = src;
                                            //}

                                            __ContentKey.SetLeft(ff.Left);
                                            __ContentKey.SetTop(ff.Top);

                                            ff.LocationChanged +=
                                                delegate
                                                {
                                                    __ContentKey.SetLeft(ff.Left);
                                                    __ContentKey.SetTop(ff.Top);
                                                };

                                            ff.SizeChanged +=
                                                delegate
                                                {
                                                    __ContentKey.SetWidth(ff.Width);
                                                    __ContentKey.SetHeight(ff.Height);
                                                };

                                            ff.FormClosing +=
                                                delegate
                                                {
                                                    __ContentKey
                                                        .Delete();
                                                };


                                            #region onmousewheel
                                            ff.GetHTMLTarget().With(
                                                ffh =>
                                                {
                                                    dynamic ffhs = ffh.style;
                                                    // http://css-infos.net/property/-webkit-transition
                                                    //ffhs.webkitTransition = "webkitTransform 0.3s linear";

                                                    ffh.onmousewheel +=
                                                        e =>
                                                        {
                                                            e.preventDefault();
                                                            e.stopPropagation();


                                                            if (e.WheelDirection > 0)
                                                            {
                                                                ff.Width = (int)(ff.Width * 1.1);
                                                                ff.Height = (int)(ff.Height * 1.1);
                                                            }
                                                            else
                                                            {
                                                                ff.Width = (int)(ff.Width * 0.9);
                                                                ff.Height = (int)(ff.Height * 0.9);
                                                            }

                                                        };

                                                }
                                            );
                                            #endregion

                                        }
                                    );
                                }
                            );
                            #endregion


                            //------WebKitFormBoundaryDmGHAZzeMBbcD5mu
                            //Content-Disposition: form-data; name="foo"; filename="FlashHeatZeeker.UnitPedControl.ApplicationSprite.swf"
                            //Content-Type: application/x-shockwave-flash


                            //------WebKitFormBoundaryDmGHAZzeMBbcD5mu--

                            Console.WriteLine("before upload...");
                            xhr.send(d);
                        }
                    );
                    #endregion


                    // let's disable other handlers
                    //evt.dataTransfer = null;

                    evt.stopPropagation();
                    evt.stopImmediatePropagation();

                    evt.preventDefault();
                };
            #endregion

            #region restore
            {
                var index = 0;

                default(Table1_ContentKey).WithEach(
                    (__ContentKey, ContentBytesLength, ContentValue, Left, Top, Width, Height) =>
                    {

                        var ff = new Form();
                        ff.PopupInsteadOfClosing(HandleFormClosing: false);


                        ff.Text = new { __ContentKey, ContentValue, ContentBytesLength }.ToString();


                        ff.Show();

                        if (Left > 0)
                            ff.MoveTo(
                                Left,
                                Top
                            );
                        else

                            ff.MoveBy(
                                32 * index,
                                24 * index
                            );

                        index++;

                        #region onmousewheel
                        ff.GetHTMLTarget().With(
                            ffh =>
                            {
                                dynamic ffhs = ffh.style;
                                // http://css-infos.net/property/-webkit-transition
                                //ffhs.webkitTransition = "webkitTransform 0.3s linear";

                                ffh.onmousewheel +=
                                    e =>
                                    {
                                        e.preventDefault();
                                        e.stopPropagation();

                                        if (e.WheelDirection > 0)
                                        {
                                            ff.Width = (int)(ff.Width * 1.1);
                                            ff.Height = (int)(ff.Height * 1.1);
                                        }
                                        else
                                        {
                                            ff.Width = (int)(ff.Width * 0.9);
                                            ff.Height = (int)(ff.Height * 0.9);
                                        }

                                    };

                            }
                        );
                        #endregion



                        //var fc = ff.GetHTMLTargetContainer();
                        var src = "/io/" + __ContentKey;

                        //var i = new IHTMLImage { src = src }.AttachTo(fc);
                        //i.style.width = "100%";

                        var web = new WebBrowser { Dock = DockStyle.Fill };

                        web.AttachTo(ff);

                        //script: error JSC1000: No implementation found for this native method, please implement [System.Windows.Forms.WebBrowser.add_DocumentCompleted(System.Windows.Forms.WebBrowserDocumentCompletedEventHandler)]
                        //script: warning JSC1000: Did you reference ScriptCoreLib via IAssemblyReferenceToken?
                        //script: error JSC1000: error at DropFileIntoSQLite.Application+<>c__DisplayClass2e.<.ctor>b__15,
                        // assembly: V:\DropFileIntoSQLite.Application.exe
                        // type: DropFileIntoSQLite.Application+<>c__DisplayClass2e, DropFileIntoSQLite.Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

                        //web.DocumentCompleted +=
                        //    delegate
                        //    {



                        //};

                        DetectCanvasFromBytesExperiment(
                            ff,
                            web,
                            ContentValue,
                            src,
                            ContentBytesLength
                        );


                        web.Navigate(src);

                        if (Width > 0)
                            ff.SizeTo(
                               Width,
                               Height
                           );
                        //else
                        //    i.InvokeOnComplete(
                        //        delegate
                        //        {


                        //            ff.ClientSize = new System.Drawing.Size(i.width, i.height);

                        //        }
                        //    );

                        ff.LocationChanged +=
                            delegate
                            {
                                __ContentKey.SetLeft(ff.Left);
                                __ContentKey.SetTop(ff.Top);
                            };

                        ff.SizeChanged +=
                            delegate
                            {
                                __ContentKey.SetWidth(ff.Width);
                                __ContentKey.SetHeight(ff.Height);
                            };

                        ff.FormClosing +=
                            delegate
                            {
                                __ContentKey.Delete();
                            };
                    }
                );
            }
            #endregion



            // can we write about this?
            #region bookmark launcher
            var href = @"javascript:
((function(h,i)
{ 
    

    var a=-1, 
    b='onreadystatechange', 
    c=document.getElementsByTagName('HEAD')[0], 
    d, 
    e, 
    f, 
    g=c.childNodes, 
    d; 

    e=document.createElement('base');   
    e.href='%%';
    c.appendChild(e);     

    d = function () 
    {  
        next: while (1)  
        {   
            a++;     
            if (a ==h.length)   
            {   
                i();    
                return;   
            }     

            /*
            for (f=0;f<g.length;f++)   
            {   
                var v =g[f];    
                var w =h[a];       

                if (v.nodeName =='SCRIPT')    
                    if (v.src ==w || v.src.substr(v.src.length - w.length - 1,w.length + 1) =='/' + w)    
                        continue next;   
            } */      
            e=document.createElement('SCRIPT');   
            e.src='%%' + h[a];     
            e[b in e?b:'onload']=  function()    
            {       
                var f=e.readyState;    
                if(f==null||f=='loaded'||f=='complete')     
                    d();    
            };  
 
        c.appendChild(e);     
        return;  
    } 
}; 
d();

}

)(['view-source'],function(){}))".Replace("%%", Native.Document.location + "");

            page.Header.draggable = true;
            page.Header.ondragstart +=
                e =>
                {
                    e.dataTransfer.setData("text/uri-list", href);
                };


            IStyleSheet.Default["#Header:hover"].style.color = "red";
            IStyleSheet.Default["#Header:hover"].style.cursor = IStyle.CursorEnum.pointer;

            #endregion


            new About().Show();
        }
        // http://youtu.be/Lo1IU8UAutE
        // 60hz 2160 4K!

        // The equirectangular projection was used in map creation since it was invented around 100 A.D. by Marinus of Tyre. 

        //        C:\Users\Arvo> "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\hzsky.png" "/sdcard/oculus/360photos/"
        //1533 KB/s(3865902 bytes in 2.461s)

        //C:\Users\Arvo> "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\hznosky.png" "/sdcard/oculus/360photos/"
        //1556 KB/s(2714294 bytes in 1.703s)

        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\hz2048c3840x2160.png" "/sdcard/oculus/360photos/"



        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150809/chrome360hz

        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150809

        // the eye nor the display will be able to do any stereo
        // until tech is near matrix capability. 2019?

        // cubemap can be used for all long range scenes
        // http://www.imdb.com/title/tt0112111/?ref_=nv_sr_1


        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150808/cubemapcamera
        // subst a: s:\jsc.svn\examples\javascript\chrome\apps\WebGL\Chrome360HZ\Chrome360HZ\bin\Debug\staging\Chrome360HZ.Application\web
        // Z:\jsc.svn\examples\javascript\chrome\apps\WebGL\Chrome360HZ\Chrome360HZ\bin\Debug\staging\Chrome360HZ.Application\web

        // ColladaLoader: Empty or non-existing file (assets/Chrome360HZ/S6Edge.dae)

        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            //FormStyler.AtFormCreated =
            //s =>
            //{
            //    s.Context.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

            //    //var x = new ChromeTCPServerWithFrameNone.HTML.Pages.AppWindowDrag().AttachTo(s.Context.GetHTMLTarget());
            //    var x = new ChromeTCPServerWithFrameNone.HTML.Pages.AppWindowDragWithShadow().AttachTo(s.Context.GetHTMLTarget());



            //    s.Context.GetHTMLTarget().style.backgroundColor = "#efefef";
            //    //s.Context.GetHTMLTarget().style.backgroundColor = "#A26D41";

            //};

#if AsWEBSERVER
            #region += Launched chrome.app.window
            // X:\jsc.svn\examples\javascript\chrome\apps\ChromeTCPServerAppWindow\ChromeTCPServerAppWindow\Application.cs
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                // if we run as a server. we can open up on android.

                //chrome.Notification.DefaultTitle = "Nexus7";
                //chrome.Notification.DefaultIconUrl = new x128().src;
                ChromeTCPServer.TheServerWithStyledForm.Invoke(
                     AppSource.Text
                //, AtFormCreated: FormStyler.AtFormCreated

                //AtFormConstructor:
                //    f =>
                //    {
                //        //arg[0] is typeof System.Int32
                //        //script: error JSC1000: No implementation found for this native method, please implement [static System.Drawing.Color.FromArgb(System.Int32)]

                //        // X:\jsc.svn\examples\javascript\forms\Test\TestFromArgb\TestFromArgb\ApplicationControl.cs

                //        f.BackColor = System.Drawing.Color.FromArgb(0xA26D41);
                //    }
                );
                return;
            }
            #endregion
#else

            #region += Launched chrome.app.window
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    //chrome.runtime.UpdateAvailable += delegate
                    //{
                    //    new chrome.Notification(title: "UpdateAvailable");

                    //};

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "Chrome360HZ");

                        // https://developer.chrome.com/apps/app_window#type-CreateWindowOptions
                        var xappwindow = await chrome.app.window.create(
                               Native.document.location.pathname, options: new
                               {
                                   alwaysOnTop = true,
                                   visibleOnAllWorkspaces = true
                               }
                        );

                        //xappwindow.setAlwaysOnTop

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion


#endif

            //const int size = 128;
            //const int size = 256; // 6 faces, 12KB
            //const int size = 512; // 6 faces, ?

            // WebGL: drawArrays: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'. Or the texture is Float or Half Float type with linear filtering while OES_float_linear or OES_half_float_linear extension is not enabled.

            //const int size = 720; // 6 faces, ?
            //const int size = 1024; // 6 faces, ?
            //const int size = 1024; // 6 faces, ?
            //const int cubefacesize = 2048; // 6 faces, ?
            const int cubefacesize = 512; // 6 faces, ?



            var uizoom = 0.05;

            var far = 0xfffff;

            Native.css.style.backgroundColor = "blue";
            Native.css.style.overflow = IStyle.OverflowEnum.hidden;

            Native.body.Clear();

            new IHTMLPre { "can we stream it into VR, shadertoy, youtube 360, youtube stereo yet?" }.AttachToDocument();


            var sw = Stopwatch.StartNew();

            var pause = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.checkbox, title = "pause" }.AttachToDocument();


            pause.onchange += delegate
            {

                if (pause.@checked)
                    sw.Stop();
                else
                    sw.Start();


            };

            var oo = new List<THREE.Object3D>();

            #region scene
            var window = Native.window;


            // what about physics and that portal rendering?

            // if we are running as a chrome web server, we may also be opened as android ndk webview app
            //var cameraPX = new THREE.PerspectiveCamera(fov: 90, aspect: window.aspect, near: 1, far: 2000);
            // once we update source
            // save the source
            // manually recompile 
            //cameraPX.position.z = 400;

            //// the camera should be close enough for the object to float off the FOV of PX
            //cameraPX.position.z = 200;

            // scene
            // can we make the 3D object orbit around us ?
            // and
            // stream it to vr?
            var scene = new THREE.Scene();

            var ambient = new THREE.AmbientLight(0x303030);
            scene.add(ambient);

            // should we fix jsc to do a more correct IDL?
            //var directionalLight = new THREE.DirectionalLight(0xffffff, 0.7);
            //directionalLight.position.set(0, 0, 1);
            //scene.add(directionalLight);

            #region light
            //var light = new THREE.DirectionalLight(0xffffff, 1.0);
            var light = new THREE.DirectionalLight(0xffffff, 2.5);
            //var light = new THREE.DirectionalLight(0xffffff, 2.5);
            //var light = new THREE.DirectionalLight(0xffffff, 1.5);
            //var lightOffset = new THREE.Vector3(0, 1000, 2500.0);
            var lightOffset = new THREE.Vector3(
                2000,
                700,

                // lower makes longer shadows 
                700.0
                );
            light.position.copy(lightOffset);
            light.castShadow = true;

            var xlight = light as dynamic;
            xlight.shadowMapWidth = 4096;
            xlight.shadowMapHeight = 2048;

            xlight.shadowDarkness = 0.1;
            //xlight.shadowDarkness = 0.5;

            xlight.shadowCameraNear = 10;
            xlight.shadowCameraFar = 10000;
            xlight.shadowBias = 0.00001;
            xlight.shadowCameraRight = 4000;
            xlight.shadowCameraLeft = -4000;
            xlight.shadowCameraTop = 4000;
            xlight.shadowCameraBottom = -4000;

            xlight.shadowCameraVisible = true;

            scene.add(light);
            #endregion




            // whats WebGLRenderTargetCube do?

            // WebGLRenderer preserveDrawingBuffer 



            var renderer0 = new THREE.WebGLRenderer(

                new
                {
                    antialias = true,
                    alpha = true,
                    preserveDrawingBuffer = true
                }
            );

            // https://github.com/mrdoob/three.js/issues/3836

            // the construct. white bg
            renderer0.setClearColor(0xfffff, 1);

            //renderer.setSize(window.Width, window.Height);
            renderer0.setSize(cubefacesize, cubefacesize);

            //renderer0.domElement.AttachToDocument();
            //rendererPX.domElement.style.SetLocation(0, 0);
            //renderer0.domElement.style.SetLocation(4, 4);


            // top

            // http://stackoverflow.com/questions/27612524/can-multiple-webglrenderers-render-the-same-scene


            // need a place to show the cubemap face to GUI 
            // how does the stereo OTOY do it?
            // https://www.opengl.org/wiki/Sampler_(GLSL)

            // http://www.richardssoftware.net/Home/Post/25

            // [+X, –X, +Y, –Y, +Z, –Z] fa



            // move up
            //camera.position.set(-1200, 800, 1200);
            //var cameraoffset = new THREE.Vector3(0, 15, 0);
            var cameraoffset = new THREE.Vector3(-1200, 800, 1200);

            #region y
            // need to rotate90?
            var cameraNY = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            cameraNY.lookAt(new THREE.Vector3(0, -1, 0));
            cameraNY.position.add(cameraoffset);

            //cameraNY.lookAt(new THREE.Vector3(0, 1, 0));
            var canvasNY = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasNY.canvas.style.SetLocation(8 + (int)(uizoom * cubefacesize + 8) * 1, 8 + (int)(uizoom * cubefacesize + 8) * 2);
            canvasNY.canvas.title = "NY";
            canvasNY.canvas.AttachToDocument();
            canvasNY.canvas.style.transformOrigin = "0 0";
            canvasNY.canvas.style.transform = "scale(" + uizoom + ")";

            var cameraPY = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            cameraPY.lookAt(new THREE.Vector3(0, 1, 0));
            cameraPY.position.add(cameraoffset);
            //cameraPY.lookAt(new THREE.Vector3(0, -1, 0));
            var canvasPY = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPY.canvas.style.SetLocation(8 + (int)(uizoom * cubefacesize + 8) * 1, 8 + (int)(uizoom * cubefacesize + 8) * 0);
            canvasPY.canvas.title = "PY";
            canvasPY.canvas.AttachToDocument();
            canvasPY.canvas.style.transformOrigin = "0 0";
            canvasPY.canvas.style.transform = "scale(" + uizoom + ")";
            #endregion

            // transpose xz?

            #region x
            var cameraNX = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            cameraNX.lookAt(new THREE.Vector3(0, 0, 1));
            cameraNX.position.add(cameraoffset);
            //cameraNX.lookAt(new THREE.Vector3(0, 0, -1));
            //cameraNX.lookAt(new THREE.Vector3(-1, 0, 0));
            //cameraNX.lookAt(new THREE.Vector3(1, 0, 0));
            var canvasNX = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasNX.canvas.style.SetLocation(8 + (int)(uizoom * cubefacesize + 8) * 2, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasNX.canvas.title = "NX";
            canvasNX.canvas.AttachToDocument();
            canvasNX.canvas.style.transformOrigin = "0 0";
            canvasNX.canvas.style.transform = "scale(" + uizoom + ")";

            var cameraPX = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            cameraPX.lookAt(new THREE.Vector3(0, 0, -1));
            cameraPX.position.add(cameraoffset);
            //cameraPX.lookAt(new THREE.Vector3(0, 0, 1));
            //cameraPX.lookAt(new THREE.Vector3(1, 0, 0));
            //cameraPX.lookAt(new THREE.Vector3(-1, 0, 0));
            var canvasPX = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPX.canvas.style.SetLocation(8 + (int)(uizoom * cubefacesize + 8) * 0, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasPX.canvas.title = "PX";
            canvasPX.canvas.AttachToDocument();
            canvasPX.canvas.style.transformOrigin = "0 0";
            canvasPX.canvas.style.transform = "scale(" + uizoom + ")";
            #endregion



            #region z
            var cameraNZ = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            //cameraNZ.lookAt(new THREE.Vector3(0, 0, -1));
            cameraNZ.lookAt(new THREE.Vector3(1, 0, 0));
            cameraNZ.position.add(cameraoffset);
            //cameraNX.lookAt(new THREE.Vector3(-1, 0, 0));
            //cameraNZ.lookAt(new THREE.Vector3(0, 0, 1));
            var canvasNZ = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasNZ.canvas.style.SetLocation(8 + (int)(uizoom * cubefacesize + 8) * 3, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasNZ.canvas.title = "NZ";
            canvasNZ.canvas.AttachToDocument();
            canvasNZ.canvas.style.transformOrigin = "0 0";
            canvasNZ.canvas.style.transform = "scale(" + uizoom + ")";

            var cameraPZ = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            //cameraPZ.lookAt(new THREE.Vector3(1, 0, 0));
            cameraPZ.lookAt(new THREE.Vector3(-1, 0, 0));
            cameraPZ.position.add(cameraoffset);
            //cameraPZ.lookAt(new THREE.Vector3(0, 0, 1));
            //cameraPZ.lookAt(new THREE.Vector3(0, 0, -1));
            var canvasPZ = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPZ.canvas.style.SetLocation(8 + (int)(uizoom * cubefacesize + 8) * 1, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasPZ.canvas.title = "PZ";
            canvasPZ.canvas.AttachToDocument();
            canvasPZ.canvas.style.transformOrigin = "0 0";
            canvasPZ.canvas.style.transform = "scale(" + uizoom + ")";
            #endregion




            // c++ alias locals would be nice..
            var canvas0 = (IHTMLCanvas)renderer0.domElement;


            var old = new
            {



                CursorX = 0,
                CursorY = 0
            };


            var st = new Stopwatch();
            st.Start();

            //canvas0.css.active.style.cursor = IStyle.CursorEnum.move;

            #region onmousedown
            Native.body.onmousedown +=
                async e =>
                {
                    if (e.Element.nodeName.ToLower() != "canvas")
                        return;

                    // movementX no longer works
                    old = new
                    {


                        e.CursorX,
                        e.CursorY
                    };


                    //e.CaptureMouse();
                    var release = e.Element.CaptureMouse();
                    await e.Element.async.onmouseup;

                    release();


                };
            #endregion



            // X:\jsc.svn\examples\javascript\Test\TestMouseMovement\TestMouseMovement\Application.cs
            #region onmousemove
            Native.body.onmousemove +=
                e =>
                {
                    if (e.Element.nodeName.ToLower() != "canvas")
                    {
                        Native.body.style.cursor = IStyle.CursorEnum.@default;
                        return;
                    }

                    e.preventDefault();
                    e.stopPropagation();


                    Native.body.style.cursor = IStyle.CursorEnum.move;

                    var pointerLock = canvas0 == Native.document.pointerLockElement;


                    //Console.WriteLine(new { e.MouseButton, pointerLock, e.movementX });

                    if (e.MouseButton == IEvent.MouseButtonEnum.Left)
                    {

                        oo.WithEach(
                            x =>
                            {
                                x.rotation.y += 0.006 * (e.CursorX - old.CursorX);
                                x.rotation.x += 0.006 * (e.CursorY - old.CursorY);
                            }
                        );

                        old = new
                        {


                            e.CursorX,
                            e.CursorY
                        };



                    }

                };
            #endregion

            // THREE.WebGLProgram: gl.getProgramInfoLog() C:\fakepath(78,3-98): warning X3557: loop only executes for 1 iteration(s), forcing loop to unroll
            // THREE.WebGLProgram: gl.getProgramInfoLog() (79,3-98): warning X3557: loop only executes for 1 iteration(s), forcing loop to unroll

            // http://www.roadtovr.com/youtube-confirms-stereo-3d-360-video-support-coming-soon/
            // https://www.youtube.com/watch?v=D-Wl9jAB45Q



            #region spherical
            var gl = new WebGLRenderingContext(alpha: true, preserveDrawingBuffer: true);
            var c = gl.canvas.AttachToDocument();

            //  3840x2160

            //c.style.SetSize(3840, 2160);

            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150722/360-youtube


            c.width = 3840;
            c.height = 2160;


            //c.width = 3840 * 2;
            //c.height = 2160 * 2;


            //c.width = 3840;
            //c.height = 2160;
            // 1,777777777777778

            // https://www.youtube.com/watch?v=fTfJwzRsE-w
            //c.width = 7580;
            //c.height = 3840;
            //1,973958333333333

            //7580
            //    3840

            // wont work
            //c.width = 8192;
            //c.height = 4096;


            // this has the wrong aspect?
            //c.width = 6466;
            //c.height = 3232;

            new IHTMLPre { new { c.width, c.height } }.AttachToDocument();

            //6466x3232

            //var suizoom = 720f / c.height;
            //var suizoom = 360f / c.height;
            var suizoom = 480f / c.width;

            c.style.transformOrigin = "0 0";
            c.style.transform = "scale(" + suizoom + ")";
            c.style.backgroundColor = "yellow";
            c.style.position = IStyle.PositionEnum.absolute;

            c.style.SetLocation(8 + (int)(uizoom * cubefacesize + 8) * 0, 8 + (int)(uizoom * cubefacesize + 8) * 3);

            var pass = new CubeToEquirectangular.Library.ShaderToy.EffectPass(
                       null,
                       gl,
                       precission: CubeToEquirectangular.Library.ShaderToy.DetermineShaderPrecission(gl),
                       supportDerivatives: gl.getExtension("OES_standard_derivatives") != null,
                       callback: null,
                       obj: null,
                       forceMuted: false,
                       forcePaused: false,
                //quadVBO: Library.ShaderToy.createQuadVBO(gl, right: 0, top: 0),
                       outputGainNode: null
                   );

            // how shall we upload our textures?
            // can we reference GLSL.samplerCube yet?
            //pass.mInputs[0] = new samplerCube { };
            pass.mInputs[0] = new CubeToEquirectangular.Library.ShaderToy.samplerCube { };

            pass.MakeHeader_Image();
            var vs = new Shaders.ProgramFragmentShader();
            pass.NewShader_Image(vs);

            #endregion




            //var frame0 = new HTML.Images.FromAssets.tiles_regrid().AttachToDocument();
            var frame0 = new HTML.Images.FromAssets.anvil___spherical_hdri_panorama_skybox_by_macsix_d6vv4hs().AttachToDocument();
            //var xor = new HTML.Images.FromAssets.Orion360_test_image_8192x4096().AttachToDocument();
            //var xor = new HTML.Images.FromAssets._2_no_clouds_4k().AttachToDocument();
            //var frame0 = new HTML.Images.FromAssets._2294472375_24a3b8ef46_o().AttachToDocument();


            // 270px
            //xor.style.height = "";
            frame0.style.height = "270px";
            frame0.style.width = "480px";
            frame0.style.SetLocation(
                8 + (int)(uizoom * cubefacesize + 8) * 0 + 480 + 16, 8 + (int)(uizoom * cubefacesize + 8) * 3);


            var mesh = new THREE.Mesh(new THREE.SphereGeometry(far / 2, 50, 50),
           new THREE.MeshBasicMaterial(new
           {
               map = THREE.ImageUtils.loadTexture(
                   //new HTML.Images.FromAssets._2294472375_24a3b8ef46_o().src
                   //new HTML.Images.FromAssets._4008650304_7f837ccbb7_b().src
                  frame0.src
                   //new WebGLEquirectangularPanorama.HTML.Images.FromAssets.PANO_20130616_222058().src
                   //new WebGLEquirectangularPanorama.HTML.Images.FromAssets.PANO_20121225_210448().src

                   )
           }));
            mesh.scale.x = -1;

            #region fixup rotation

            //mesh.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI / 2);
            //mesh.rotateOnAxis(new THREE.Vector3(1, 0, 0), -Math.PI / 2);
            mesh.rotateOnAxis(new THREE.Vector3(0, 1, 0), -Math.PI / 2);
            #endregion


            scene.add(mesh);


            //new IHTMLButton { }

            var dir = default(DirectoryEntry);

            new IHTMLButton { "openDirectory" }.AttachToDocument().onclick += async delegate
            {
                dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });
            };

            frame0.onclick += delegate
            {
                // http://paulbourke.net/papers/vsmm2006/vsmm2006.pdf
                //            A method of creating synthetic stereoscopic panoramic images that can be implemented
                //in most rendering packages has been presented. If single panoramic pairs can be created
                //then stereoscopic panoramic movies are equally possible giving rise to the prospect of
                //movies where the viewer can interact with, at least with regard to what they choose to look
                //at.These images can be projected so as to engage the two features of the human visual
                //system that assist is giving us a sense of immersion, the feeling of “being there”. That is,
                //imagery that contains parallax information as captured from two horizontally separated eye
                //positions (stereopsis)and imagery that fills our peripheral vision.The details that define
                //how the two panoramic images should be created in rendering packages are provided, in
                //particular, how to precisely configure the virtual cameras and control the distance to zero
                //parallax.

                // grab a frame


                var f0 = new IHTMLImage { src = gl.canvas.toDataURL() };

                //var f0 = (IHTMLImage)gl.canvas;
                //var f0 = (IHTMLImage)gl.canvas;
                //var base64 = gl.canvas.toDataURL();


                //frame0.src = base64;
                frame0.src = f0.src;

                // 7MB!

                if (dir == null)
                    return;

                //                // ---------------------------
                //IrfanView
                //---------------------------
                //Warning !
                //The file: "X:\vr\tape1\0001.jpg" is a PNG file with incorrect extension !
                //Rename ?
                //---------------------------
                //Yes   No   
                //---------------------------

                // haha this will render the thumbnail.
                //dir.WriteAllBytes("0000.png", frame0);

                dir.WriteAllBytes("0000.png", f0);
                // 3.7MB
                // 3840x2160

            };



            // "Z:\jsc.svn\examples\javascript\WebGL\WebGLColladaExperiment\WebGLColladaExperiment\WebGLColladaExperiment.csproj"

            #region WebGLRah66Comanche
            // why isnt it being found?
            // "Z:\jsc.svn\examples\javascript\WebGL\collada\WebGLRah66Comanche\WebGLRah66Comanche\WebGLRah66Comanche.csproj"
            new global::WebGLRah66Comanche.Comanche(
            ).Source.Task.ContinueWithResult(
                dae =>
                {

                    //dae.position.y = -40;
                    //dae.position.z = 280;
                    scene.add(dae);
                    //oo.Add(dae);

                    // wont do it
                    //dae.castShadow = true;

                    dae.children[0].children[0].children.WithEach(x => x.castShadow = true);


                    // the rotors?
                    dae.children[0].children[0].children.Last().children.WithEach(x => x.castShadow = true);


                    dae.scale.set(0.5, 0.5, 0.5);
                    dae.position.x = -900;
                    dae.position.z = +900;

                    // raise it up
                    dae.position.y = 400;

                    //var sw = Stopwatch.StartNew();

                    //Native.window.onframe += delegate
                    //{
                    //    //dae.children[0].children[0].children.Last().al
                    //    //dae.children[0].children[0].children.Last().rotation.z = sw.ElapsedMilliseconds * 0.01;
                    //    //dae.children[0].children[0].children.Last().rotation.x = sw.ElapsedMilliseconds * 0.01;
                    //    dae.children[0].children[0].children.Last().rotation.y = sw.ElapsedMilliseconds * 0.01;
                    //};
                }
            );
            #endregion



            #region tree
            // "Z:\jsc.svn\examples\javascript\WebGL\WebGLGodRay\WebGLGodRay\WebGLGodRay.csproj"

            var materialScene = new THREE.MeshBasicMaterial(new { color = 0x000000, shading = THREE.FlatShading });
            var tloader = new THREE.JSONLoader();

            // http://stackoverflow.com/questions/16539736/do-not-use-system-runtime-compilerservices-dynamicattribute-use-the-dynamic
            // https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.dynamicattribute%28v=vs.110%29.aspx
            //System.Runtime.CompilerServices.DynamicAttribute

            tloader.load(

                new WebGLGodRay.Models.tree().Content.src,

                new Action<THREE.Geometry>(
                xgeometry =>
                {

                    var treeMesh = new THREE.Mesh(xgeometry, materialScene);
                    treeMesh.position.set(0, -150, -150);
                    treeMesh.position.x = -900;
                    treeMesh.position.z = -900;

                    treeMesh.position.y = 25;

                    var tsc = 400;
                    treeMesh.scale.set(tsc, tsc, tsc);

                    treeMesh.matrixAutoUpdate = false;
                    treeMesh.updateMatrix();


                    treeMesh.AttachTo(scene);

                }
                )
                );
            #endregion

            #region create field

            // THREE.PlaneGeometry: Consider using THREE.PlaneBufferGeometry for lower memory footprint.

            // could we get some film grain?
            var planeGeometry = new THREE.CubeGeometry(512, 512, 1);
            var plane = new THREE.Mesh(planeGeometry,
                    new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })

                );
            //plane.castShadow = false;
            plane.receiveShadow = true;


            {

                var parent = new THREE.Object3D();
                parent.add(plane);
                parent.rotation.x = -Math.PI / 2;
                parent.scale.set(10, 10, 10);

                scene.add(parent);
            }

            var random = new Random();
            var meshArray = new List<THREE.Mesh>();
            var geometry = new THREE.CubeGeometry(1, 1, 1);
            //var sw = Stopwatch.StartNew();

            for (var i = 3; i < 9; i++)
            {

                //THREE.MeshPhongMaterial
                var ii = new THREE.Mesh(geometry,


                    new THREE.MeshPhongMaterial(new { ambient = 0x000000, color = 0xA06040, specular = 0xA26D41, shininess = 1 })

                    //new THREE.MeshLambertMaterial(
                    //new
                    //{
                    //    color = (Convert.ToInt32(0xffffff * random.NextDouble())),
                    //    specular = 0xffaaaa,
                    //    ambient= 0x050505, 
                    //})

                    );
                ii.position.x = i % 7 * 200 - 2.5f;

                // raise it up
                ii.position.y = .5f * 100;
                ii.position.z = -1 * i * 100;
                ii.castShadow = true;
                ii.receiveShadow = true;
                //ii.scale.set(100, 100, 100 * i);
                ii.scale.set(100, 100 * i, 100);


                meshArray.Add(ii);

                scene.add(ii);

                if (i % 2 == 0)
                {
#if FWebGLHZBlendCharacter
                    #region SpeedBlendCharacter
					var _i = i;
					{ WebGLHZBlendCharacter.HTML.Pages.TexturesImages ref0; }

					var blendMesh = new THREE.SpeedBlendCharacter();
					blendMesh.load(
						new WebGLHZBlendCharacter.Models.marine_anims().Content.src,
						new Action(
							delegate
							{
								// buildScene
								//blendMesh.rotation.y = Math.PI * -135 / 180;
								blendMesh.castShadow = true;
								// we cannot scale down we want our shadows
								//blendMesh.scale.set(0.1, 0.1, 0.1);

								blendMesh.position.x = (_i + 2) % 7 * 200 - 2.5f;

								// raise it up
								//blendMesh.position.y = .5f * 100;
								blendMesh.position.z = -1 * _i * 100;


								var xtrue = true;
								// run
								blendMesh.setSpeed(1.0);

								// will in turn call THREE.AnimationHandler.play( this );
								//blendMesh.run.play();
								// this wont help. bokah does not see the animation it seems.
								//blendMesh.run.update(1);

								blendMesh.showSkeleton(!xtrue);

								scene.add(blendMesh);


								Native.window.onframe +=
								 delegate
								 {

									 blendMesh.rotation.y = Math.PI * 0.0002 * sw.ElapsedMilliseconds;



									 ii.rotation.y = Math.PI * 0.0002 * sw.ElapsedMilliseconds;

								 };

							}
						)
					);
                    #endregion
#endif
                }

            }
            #endregion


            #region HZCannon
            // "Z:\jsc.svn\examples\javascript\WebGL\HeatZeekerRTSOrto\HeatZeekerRTSOrto\HeatZeekerRTSOrto.csproj"
            new HeatZeekerRTSOrto.HZCannon().Source.Task.ContinueWithResult(
                async cube =>
                {
                    // https://github.com/mrdoob/three.js/issues/1285
                    //cube.children.WithEach(c => c.castShadow = true);

                    //cube.traverse(
                    //    new Action<THREE.Object3D>(
                    //        child =>
                    //        {
                    //            // does it work? do we need it?
                    //            //if (child is THREE.Mesh)

                    //            child.castShadow = true;
                    //            //child.receiveShadow = true;

                    //        }
                    //    )
                    //);

                    // um can edit and continue insert code going back in time?
                    cube.scale.x = 10.0;
                    cube.scale.y = 10.0;
                    cube.scale.z = 10.0;



                    //cube.castShadow = true;
                    //dae.receiveShadow = true;

                    //cube.position.x = -100;

                    ////cube.position.y = (cube.scale.y * 50) / 2;
                    //cube.position.z = Math.Floor((random() * 1000 - 500) / 50) * 50 + 25;



                    // if i want to rotate, how do I do it?
                    //cube.rotation.z = random() + Math.PI;
                    //cube.rotation.x = random() + Math.PI;
                    var sw2 = Stopwatch.StartNew();



                    scene.add(cube);
                    //interactiveObjects.Add(cube);

                    // offset is wrong
                    //while (true)
                    //{
                    //    await Native.window.async.onframe;

                    //    cube.rotation.y = Math.PI * 0.0002 * sw2.ElapsedMilliseconds;

                    //}
                }
            );
            #endregion


            #region HZCannon
            new HeatZeekerRTSOrto.HZCannon().Source.Task.ContinueWithResult(
                async cube =>
                {
                    // https://github.com/mrdoob/three.js/issues/1285
                    //cube.children.WithEach(c => c.castShadow = true);

                    //cube.traverse(
                    //    new Action<THREE.Object3D>(
                    //        child =>
                    //        {
                    //            // does it work? do we need it?
                    //            //if (child is THREE.Mesh)

                    //            child.castShadow = true;
                    //            //child.receiveShadow = true;

                    //        }
                    //    )
                    //);

                    // um can edit and continue insert code going back in time?
                    cube.scale.x = 10.0;
                    cube.scale.y = 10.0;
                    cube.scale.z = 10.0;



                    //cube.castShadow = true;
                    //dae.receiveShadow = true;


                    // jsc shat about out of band code patching?
                    cube.position.z = 600;
                    cube.position.x = -900;
                    //cube.position.y = -400;

                    //cube.position.x = -100;
                    //cube.position.y = -400;

                    ////cube.position.y = (cube.scale.y * 50) / 2;
                    //cube.position.z = Math.Floor((random() * 1000 - 500) / 50) * 50 + 25;



                    // if i want to rotate, how do I do it?
                    //cube.rotation.z = random() + Math.PI;
                    //cube.rotation.x = random() + Math.PI;
                    var sw2 = Stopwatch.StartNew();



                    scene.add(cube);
                    //interactiveObjects.Add(cube);

                    // offset is wrong
                    //while (true)
                    //{
                    //    await Native.window.async.onframe;

                    //    cube.rotation.y = Math.PI * 0.0002 * sw2.ElapsedMilliseconds;

                    //}
                }
            );
            #endregion


            #region HZBunker
            new HeatZeekerRTSOrto.HZBunker().Source.Task.ContinueWithResult(
                     cube =>
                     {
                         // https://github.com/mrdoob/three.js/issues/1285
                         //cube.children.WithEach(c => c.castShadow = true);
                         cube.castShadow = true;

                         //cube.traverse(
                         //    new Action<THREE.Object3D>(
                         //        child =>
                         //        {
                         //            // does it work? do we need it?
                         //            //if (child is THREE.Mesh)
                         //            child.castShadow = true;
                         //            //child.receiveShadow = true;

                         //        }
                         //    )
                         //);

                         // um can edit and continue insert code going back in time?
                         cube.scale.x = 10.0;
                         cube.scale.y = 10.0;
                         cube.scale.z = 10.0;

                         //cube.castShadow = true;
                         //dae.receiveShadow = true;

                         cube.position.x = -1000;
                         //cube.position.y = (cube.scale.y * 50) / 2;
                         cube.position.z = 0;

                         scene.add(cube);
                     }
                 );
            #endregion


            new Models.ColladaS6Edge().Source.Task.ContinueWithResult(
                   dae =>
                   {
                       // 90deg
                       dae.rotation.x = -Math.Cos(Math.PI);

                       //dae.scale.x = 30;
                       //dae.scale.y = 30;
                       //dae.scale.z = 30;
                       dae.position.z = -(65 - 200);





                       var scale = 0.9;

                       // jsc, do we have ILObserver available yet?
                       dae.scale.x = scale;
                       dae.scale.y = scale;
                       dae.scale.z = scale;


                       #region onmousewheel
                       Native.body.onmousewheel +=
                           e =>
                           {
                               e.preventDefault();

                               //camera.position.z = 1.5;

                               // min max. shall adjust speed also!
                               // max 4.0
                               // min 0.6
                               dae.position.z -= 10.0 * e.WheelDirection;

                               //camera.position.z = 400;
                               //dae.position.z = dae.position.z.Max(-200).Min(200);

                               //Native.document.title = new { z }.ToString();

                           };
                       #endregion


                       //dae.position.y = -80;

                       scene.add(dae);
                       oo.Add(dae);




                       // view-source:http://threejs.org/examples/webgl_multiple_canvases_circle.html
                       // https://threejsdoc.appspot.com/doc/three.js/src.source/extras/cameras/CubeCamera.js.html
                       Native.window.onframe +=
                           e =>
                           {
                               //if (pause) return;
                               //if (pause.@checked)
                               //    return;


                               // can we float out of frame?
                               // haha. a bit too flickery.
                               //dae.position.x = Math.Sin(e.delay.ElapsedMilliseconds * 0.01) * 50.0;
                               //dae.position.x = Math.Sin(e.delay.ElapsedMilliseconds * 0.001) * 190.0;
                               dae.position.x = Math.Sin(sw.ElapsedMilliseconds * 0.0001) * 190.0;
                               dae.position.y = Math.Cos(sw.ElapsedMilliseconds * 0.0001) * 90.0;
                               // manual rebuild?
                               // red compiler notifies laptop chrome of pending update
                               // app reloads


                               renderer0.clear();
                               //rendererPY.clear();

                               //cameraPX.aspect = canvasPX.aspect;
                               //cameraPX.updateProjectionMatrix();

                               // um what does this do?
                               //cameraPX.position.z += (z - cameraPX.position.z) * e.delay.ElapsedMilliseconds / 200.0;
                               // mousewheel allos the camera to move closer
                               // once we see the frame in vr, can we udp sync vr tracking back to laptop?


                               //this.targetPX.x += 1;
                               //this.targetNX.x -= 1;

                               //this.targetPY.y += 1;
                               //this.targetNY.y -= 1;

                               //this.targetPZ.z += 1;
                               //this.targetNZ.z -= 1;

                               // how does the 360 or shadertoy want our cubemaps?


                               // and then rotate right?

                               // how can we render cubemap?


                               #region x
                               // upside down?
                               renderer0.render(scene, cameraPX);
                               canvasPX.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);

                               renderer0.render(scene, cameraNX);
                               canvasNX.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                               #endregion

                               #region z
                               renderer0.render(scene, cameraPZ);
                               canvasPZ.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);

                               renderer0.render(scene, cameraNZ);
                               canvasNZ.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                               #endregion



                               #region y
                               renderer0.render(scene, cameraPY);

                               //canvasPY.save();
                               //canvasPY.translate(0, size);
                               //canvasPY.rotate((float)(-Math.PI / 2));
                               canvasPY.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                               //canvasPY.restore();


                               renderer0.render(scene, cameraNY);
                               //canvasNY.save();
                               //canvasNY.translate(size, 0);
                               //canvasNY.rotate((float)(Math.PI / 2));
                               canvasNY.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                               //canvasNY.restore();
                               // ?
                               #endregion


                               //renderer0.render(scene, cameraPX);


                               //rendererPY.render(scene, cameraPY);

                               // at this point we should be able to render the sphere texture

                               //public const uint TEXTURE_CUBE_MAP_POSITIVE_X = 34069;
                               //public const uint TEXTURE_CUBE_MAP_NEGATIVE_X = 34070;
                               //public const uint TEXTURE_CUBE_MAP_POSITIVE_Y = 34071;
                               //public const uint TEXTURE_CUBE_MAP_NEGATIVE_Y = 34072;
                               //public const uint TEXTURE_CUBE_MAP_POSITIVE_Z = 34073;
                               //public const uint TEXTURE_CUBE_MAP_NEGATIVE_Z = 34074;


                               //var cube0 = new IHTMLImage[] {
                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_px(),
                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_nx(),

                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_py(),
                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_ny(),


                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_pz(),
                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_nz()
                               //};

                               new[] {
                                   canvasPX, canvasNX,
                                   canvasPY, canvasNY,
                                   canvasPZ, canvasNZ
                               }.WithEachIndex(
                                   (img, index) =>
                                   {
                                       gl.bindTexture(gl.TEXTURE_CUBE_MAP, pass.tex);

                                       //gl.pixelStorei(gl.UNPACK_FLIP_X_WEBGL, false);
                                       gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);

                                       // http://stackoverflow.com/questions/15364517/pixelstoreigl-unpack-flip-y-webgl-true

                                       // https://msdn.microsoft.com/en-us/library/dn302429(v=vs.85).aspx
                                       //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
                                       //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);

                                       gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + (uint)index, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img.canvas);

                                   }
                                );


                               pass.Paint_Image(
                                     0,

                                     0,
                                     0,
                                     0,
                                     0
                                   //,

                                // gl_FragCoord
                                   // cannot be scaled, and can be referenced directly.
                                   // need another way to scale
                                   //zoom: 0.3f
                                );

                               //paintsw.Stop();


                               // what does it do?
                               gl.flush();

                           };


                   }
               );


            #endregion



            Console.WriteLine("do you see it?");
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150812/cssstereo



            // https://www.reddit.com/r/GearVR/comments/35g8w7/real_world_stereoscopic_360_panoramas/
            // https://www.reddit.com/r/oculus/comments/35gcn2/real_world_stereoscopic_panoramas_with_gear_vr/
            // http://stackoverflow.com/questions/9032050/canvas-mask-an-image-and-preserve-its-alpha-channel
            // https://3dwarehouse.sketchup.com/model.html?id=48bcce07b0baf689d9e6f00e848ea18
            // https://www.youtube.com/watch?v=OurzBO1cDto

            Native.body.style.margin = "0px";
            Native.body.style.overflow = IStyle.OverflowEnum.hidden;
            Native.body.Clear();

            new IHTMLPre { "loading stereo... 2MB!" }.AttachToDocument();

            // if this is a chrome app
            // would GearVR 360 app be able to request current stereo cubemap?






            // Uncaught TypeError: Cannot read property '0' of undefined
            var keys = new int[0xffff];

            //c = a[0].keys[jAEABqtXvT6n4h6m6ZavdA(b)];
            //d = c[0];
            //c[0] = (((d + 1)));



            Native.document.body.onkeyup +=
             e =>
             {

                 var z = keys[e.KeyCode];

                 if (z > 0)
                     z++;
                 else
                     z = 1;

                 // what does it do?
                 keys[e.KeyCode] = z;

                 // 4333ms {{ KeyCode = 83, S = 83, z = NaN }}
                 Console.WriteLine(new { e.KeyCode, System.Windows.Forms.Keys.S, z });

             };


            // skybox cubemap
            var iii = new IHTMLImage[] {
                        new px(), new nx(),
                        new py(), new ny(),
                        new pz(), new nz()
                    };


            //var f12 = await new airplane().async.oncomplete;
            //var f12 = new airplane();



            Task.WhenAll(from x in iii select x.async.oncomplete).ContinueWithResult(
                ii =>



               // how can we do an alpha clear on the jpg?
               //new airplane().async.oncomplete.ContinueWithResult(
               //new airplane_leftwindows().async.oncomplete.ContinueWithResult(
               new airplane_mask().async.oncomplete.ContinueWithResult(
               f12_mask =>
               new airplane().async.oncomplete.ContinueWithResult(
               f12 =>
               {
                   //Func<int, string, IHTMLImage> xf = (i, globalCompositeOperation) =>
                   //{
                   //    // we do have a skybox example somewhere...
                   //    var f1 = new CanvasRenderingContext2D(w: f12.height, h: f12.height);

                   //    f1.drawImage(f12, i * f12.height, 0, sw: f12.height, sh: f12.height, dx: 0, dy: 0, dw: f12.height, dh: f12.height);

                   //    // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
                   //    f1.globalCompositeOperation = globalCompositeOperation;

                   //    f1.drawImage(f12_mask, i * f12.height, 0, sw: f12.height, sh: f12.height, dx: 0, dy: 0, dw: f12.height, dh: f12.height);

                   //    return f1;
                   //};


                   //new[] {
                   //    "source-over",
                   //    "source-in",
                   //    "source-out",
                   //    "source-atop",
                   //    "destination-over",
                   //    "destination-in",
                   //    "destination-out",
                   //    "destination-atop",
                   //    "lighter",
                   //    "copy",
                   //    "xor",
                   //    "multiply",
                   //    "screen",
                   //    "overlay",
                   //    "darken",
                   //    "lighten",
                   //    "color-dodge",
                   //    "color-burn",
                   //    "hard-light",
                   //    "soft-light",
                   //    "difference",
                   //    "exclusion",
                   //    "hue",
                   //    "saturation",
                   //    "color",
                   //    "luminosity"
                   //}.WithEach(globalCompositeOperation =>
                   //    {

                   //        xf(4, globalCompositeOperation).AttachToDocument().title = globalCompositeOperation;
                   //    }
                   //);


                   Func<int, IHTMLImage> f = i =>
                   {
                       // we do have a skybox example somewhere...
                       var f1 = new CanvasRenderingContext2D(w: f12.height, h: f12.height);

                       f1.drawImage(f12, i * f12.height, 0, sw: f12.height, sh: f12.height, dx: 0, dy: 0, dw: f12.height, dh: f12.height);

                       // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
                       f1.globalCompositeOperation = "multiply";

                       f1.drawImage(f12_mask, i * f12.height, 0, sw: f12.height, sh: f12.height, dx: 0, dy: 0, dw: f12.height, dh: f12.height);

                       return f1;
                   };



                   var skyScene0 = new THREE.Scene();
                   var skyScene1 = new THREE.Scene();
                   var skyScene2 = new THREE.Scene { };


                   #region  createSky
                   // gearvr has photos360 app



                   //var textureCube = THREE.ImageUtils.loadTextureCube(urls);


                   var vertexShader =
            @"
varying vec3 vWorldPosition;
            "
            //+ THREE.ShaderChunk["logdepthbuf_pars_vertex"]
            +
            @"
void main() {
vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); 
vWorldPosition = worldPosition.xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
"
    //+ THREE.ShaderChunk["logdepthbuf_vertex"]
    + @"
}
"

        ;
                   // https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/texturing.php

                   var fragmentShader =
            @"
uniform samplerCube tCube; 
uniform float tFlip; 
varying vec3 vWorldPosition;
                   "
    //+ THREE.ShaderChunk["logdepthbuf_pars_fragment"] 
    + @"
void main() 
{

vec4 c = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );
"

    // : gl.getShaderInfoLog() ERROR: 0:52: 'assign' :  cannot convert from 'const int' to 'highp float'

    //+ THREE.ShaderChunk["logdepthbuf_fragment"] 
    + @"

// _mask.png has the bits
if (c.r == 0.0) if (c.g == 0.0) if (c.b == 0.0) discard;

gl_FragColor = c;

}
"
               // vec4 textureCube(samplerCube s, vec3 coord [, float bias])
               // 
               ;



                   var skyMeshmaterial0 = new THREE.ShaderMaterial(new
                   {
                       fragmentShader = fragmentShader,
                       vertexShader = vertexShader,
                       uniforms = new
                       {
                           tCube = new
                           {
                               type = "t",
                               value = new THREE.CubeTexture(ii
                           )
                               {
                                   flipY = false,

                                   // !!
                                   needsUpdate = true
                               }
                           },
                           tFlip = new { type = "f", value = -1 }
                       },
                       depthWrite = false,
                       side = THREE.BackSide
                   });

                   var mesh0 = new THREE.Mesh(new THREE.BoxGeometry(10000, 10000, 10000), skyMeshmaterial0).AttachTo(skyScene0);



                   // stereo vs mono skybox
                   var skyMeshmaterial1 = new THREE.ShaderMaterial(new
                   {
                       fragmentShader = fragmentShader,
                       vertexShader = vertexShader,
                       uniforms = new
                       {
                           tCube = new
                           {
                               type = "t",
                               value = new THREE.CubeTexture(
                                 f(0), f(1),
                                f(2), f(3),
                                f(4), f(5)
                               )
                               {
                                   flipY = false,

                                   // !!
                                   needsUpdate = true
                               }
                           },
                           tFlip = new { type = "f", value = -1 }
                       },
                       depthWrite = false,
                       side = THREE.BackSide,

                   });

                   var mesh1 = new THREE.Mesh(new THREE.BoxGeometry(10000, 10000, 10000), skyMeshmaterial1).AttachTo(skyScene1);


                   var skyMeshmaterial2 = new THREE.ShaderMaterial(new
                   {
                       fragmentShader = fragmentShader,
                       vertexShader = vertexShader,
                       uniforms = new
                       {
                           tCube = new
                           {
                               type = "t",
                               value = new THREE.CubeTexture(
                                f(0 + 6), f(1 + 6),
                               f(2 + 6), f(3 + 6),
                               f(4 + 6), f(5 + 6)
                              )
                               {
                                   flipY = false,


                                   // !!
                                   needsUpdate = true
                               }
                           },
                           tFlip = new { type = "f", value = -1 }
                       },
                       depthWrite = false,
                       side = THREE.BackSide
                   });

                   var mesh2 = new THREE.Mesh(new THREE.BoxGeometry(10000, 10000, 10000), skyMeshmaterial2).AttachTo(skyScene2);
                   #endregion


                   Native.body.Clear();

                   var skyCamera = new THREE.PerspectiveCamera(90, Native.window.aspect, 1, 20000);
                   //var skyCamera = new THREE.PerspectiveCamera(45, Native.window.aspect, 1, 20000);

                   // not using css?
                   // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150812/cssstereo

                   var renderer = new THREE.WebGLRenderer(new { antialias = true, alpha = false })
                   {
                       autoClear = false,
                       shadowMapEnabled = true,
                       shadowMapType = THREE.PCFSoftShadowMap
                   };

                   renderer.setSize(Native.window.Width, Native.window.Height);
                   renderer.domElement.AttachToDocument();


                   #region onresize
                   new { }.With(
                        async delegate
                        {
                            do
                            {
                                skyCamera.aspect = Native.window.aspect;
                                skyCamera.updateProjectionMatrix();
                                renderer.setSize(Native.window.Width, Native.window.Height);

                            } while (await Native.window.async.onresize);
                        }
                    );
                   #endregion

                   Native.document.body.onmousewheel +=
                      e =>
                      {
                          skyCamera.fov -= e.WheelDirection * 5.0;
                          skyCamera.updateProjectionMatrix();
                      };



                   var target0 = new THREE.Vector3();

                   var lon = 90.0;
                   var lat = 0.0;
                   var phi = 0.0;
                   var theta = 0.0;





                   var drag = false;

                   var sw = Stopwatch.StartNew();

                   Native.window.onframe +=
                        delegate
                        {
                            var sinfps = 1 + (int)(((Math.Sin(sw.ElapsedMilliseconds * 0.0001) + 1.0) / 2.0) * 59);
                            Native.document.title = "" + new { sinfps };


                            //var eye = (sw.ElapsedMilliseconds / (200)) % 2;
                            //var eye = (sw.ElapsedMilliseconds / (1000 / 15)) % 2;
                            //var eye = (sw.ElapsedMilliseconds / (1000 / 30)) % 2;
                            //var eye = (sw.ElapsedMilliseconds / (1000 / 45)) % 2;
                            //var eye = (sw.ElapsedMilliseconds / (1000 / 60)) % 2;
                            var eye = (sw.ElapsedMilliseconds / (1000 / sinfps)) % 2;
                            //  if we are a multiprocess renderer, get the volatile eye id 


                            // doesnt work?
                            //skyMesh0.visible = eye == 0;

                            //mesh0.rotation = new THREE.Vector3(0, 0, sw.ElapsedMilliseconds);


                            if (Native.document.pointerLockElement == Native.document.body)
                                lon += 0.00;
                            else
                            {

                                lon += 0.01;
                            }

                            lat = Math.Max(-85, Math.Min(85, lat));


                            // this is wrong, but gets the idea across.
                            phi = THREE.Math.degToRad(90 - lat) + Math.Sin(sw.ElapsedMilliseconds * 0.001) * 0.1 - 0.3;
                            theta = THREE.Math.degToRad(lon);

                            target0.x = Math.Sin(phi) * Math.Cos(theta);
                            target0.y = Math.Cos(phi);
                            target0.z = Math.Sin(phi) * Math.Sin(theta);

                            skyCamera.lookAt(target0);


                            renderer.clear();

                            renderer.render(skyScene0, skyCamera);


                            phi = THREE.Math.degToRad(90 - lat);
                            theta = THREE.Math.degToRad(lon);

                            target0.x = Math.Sin(phi) * Math.Cos(theta);
                            target0.y = Math.Cos(phi);
                            target0.z = Math.Sin(phi) * Math.Sin(theta);

                            skyCamera.lookAt(target0);

                            if ((keys[(int)System.Windows.Forms.Keys.S] % 3) == 0)
                            {

                                if (eye == 0)
                                    renderer.render(skyScene1, skyCamera);
                                else
                                    renderer.render(skyScene2, skyCamera);
                            }
                            else if ((keys[(int)System.Windows.Forms.Keys.S] % 3) == 1)
                            {
                                renderer.render(skyScene1, skyCamera);
                            }
                        };

                   #region ontouchmove
                   var touchX = 0;
                   var touchY = 0;

                   Native.document.body.ontouchstart +=
                                          e =>
                                          {
                                              e.preventDefault();

                                              var touch = e.touches[0];

                                              touchX = touch.screenX;
                                              touchY = touch.screenY;

                                          };


                   Native.document.body.ontouchmove +=
                     e =>
                     {
                         e.preventDefault();

                         var touch = e.touches[0];

                         lon -= (touch.screenX - touchX) * 0.1;
                         lat += (touch.screenY - touchY) * 0.1;

                         touchX = touch.screenX;
                         touchY = touch.screenY;

                     };
                   #endregion






                   #region camera rotation
                   Native.document.body.onmousemove +=
                      e =>
                      {
                          e.preventDefault();

                          if (Native.document.pointerLockElement == Native.document.body)
                          {
                              lon += e.movementX * 0.1;
                              lat -= e.movementY * 0.1;

                              //Console.WriteLine(new { lon, lat, e.movementX, e.movementY });
                          }
                      };


                   Native.document.body.onmouseup +=
                     e =>
                     {
                         drag = false;
                         e.preventDefault();
                     };

                   Native.document.body.onmousedown +=
                       e =>
                       {
                           //e.CaptureMouse();

                           drag = true;
                           e.preventDefault();
                           Native.document.body.requestPointerLock();

                       };


                   Native.document.body.ondblclick +=
                       e =>
                       {
                           e.preventDefault();

                           Console.WriteLine("requestPointerLock");
                       };

                   #endregion



               }
           )
           )
           );

        }
        void Spawn(DudeAnimationInfo LoadedCharacter, Scene.Document LoadedScene)
        {
            var ViewSize = new Size { Width = 640, Height = 480 };

            var Container = new IHTMLDiv();
            Container.AttachToDocument();
            Container.style.SetSize(ViewSize.Width, ViewSize.Height + 22);
            Container.KeepInCenter();

            //Container.MakeCSSShaderCrumple();

            var Wallpaper = new IHTMLDiv().AttachTo(Container);
            Wallpaper.style.SetSize(ViewSize.Width, ViewSize.Height + 22);


            new power().ToBackground(Wallpaper.style);
            Wallpaper.style.position = IStyle.PositionEnum.absolute;
            Wallpaper.style.backgroundRepeat = "no-repeat";
            Wallpaper.style.backgroundPosition = "center center";





            var Margin = 48;
            var MarginSafe = 72;



            var CurrentFrame = LoadedScene.Frames.Randomize().First();
            //var CurrentFrame = LoadedScene.Frames.Single(f => f.Name == "C");

            var Room = new IHTMLDiv();



            Room.style.border = "1px solid #00ff00";
            Room.style.SetSize(ViewSize.Width, ViewSize.Height);
            Room.style.position = IStyle.PositionEnum.absolute;
            Room.style.overflow = IStyle.OverflowEnum.hidden;

            Room.AttachTo(Container);
            Room.style.SetLocation(0, 22);

            //Room.AttachToDocument();
            //Room.KeepInCenter();




            var tween = Room.ToOpacityTween();

            Action HideRoom = () => tween.Value = 1;
            Action ShowRoom = () => tween.Value = 0;

            HideRoom();

            //var GroundOverlay2 = new IHTMLDiv();

            //GroundOverlay2.style.backgroundColor = Color.Blue;
            ////GroundOverlay.style.Opacity = 0;

            //GroundOverlay2.style.position = IStyle.PositionEnum.absolute;
            //GroundOverlay2.style.SetLocation(0, 0, ViewSize.Width, ViewSize.Height);
            //GroundOverlay2.AttachTo(Room);

            var LostInTime_Images = new ImpAdventures.HTML.Pages.LostInTimeImages().Images;

            var BackgroundImage = new IHTMLImage();

            LostInTime_Images.FirstOrDefault(
                                   k => k.src.SkipUntilLastIfAny("/") == CurrentFrame.Image.Source.SkipUntilLastIfAny("/")
                               ).With(
                                   ImageSource =>
                                   {
                                       Console.WriteLine(ImageSource.src);
                                       BackgroundImage.src = ImageSource.src;
                                   }
                               );

            BackgroundImage.style.SetLocation(0, 0, ViewSize.Width, ViewSize.Height);
            BackgroundImage.alt = "BackgroundImage";
            BackgroundImage.AttachTo(Room);

            //GroundOverlay2.style.backgroundImage = "url(" + CurrentFrame.Image.Source + ")";
            //BackgroundImage.InvokeOnComplete(
            //    delegate
            //    {
            //        //BackgroundImage.style.backgroundColor = Color.Red;
            //        //BackgroundImage.style.SetLocation(0,0, ViewSize.Width, ViewSize.Height);
            //        BackgroundImage.AttachTo(GroundOverlay2);
            //    }
            //);


            var GroundOverlay = new IHTMLDiv();

            GroundOverlay.style.backgroundColor = Color.Blue;
            GroundOverlay.style.Opacity = 0;
            GroundOverlay.style.SetLocation(0, 0, ViewSize.Width, ViewSize.Height);
            GroundOverlay.AttachTo(Room);

            var Ground = new IHTMLDiv();

            Ground.style.SetLocation(0, 0, ViewSize.Width, ViewSize.Height);
            Ground.AttachTo(Room);




            var AnimateRoomChange = default(Action<Action>);

            #region TryToChangeRooms
            Func<TryToChangeRoomsArgs, bool> TryToChangeRooms =
                e =>
                {
                    if (e == null)
                        return false;

                    if (e.NextRoomSelector == null) throw new ArgumentNullException("NextRoomSelector");

                    var next = LoadedScene.Frames.SingleOrDefault(e.NextRoomSelector);

                    var r = next != null;

                    if (r)
                    {
                        AnimateRoomChange(
                            delegate
                            {
                                CurrentFrame = next;

                                Console.WriteLine("AnimateRoomChange");

                                LostInTime_Images.FirstOrDefault(
                                    k => k.src.SkipUntilLastIfAny("/") == CurrentFrame.Image.Source.SkipUntilLastIfAny("/")
                                ).With(
                                    ImageSource =>
                                    {
                                        Console.WriteLine(ImageSource.src);
                                        BackgroundImage.src = ImageSource.src;
                                    }
                                );

                                //GroundOverlay2.style.backgroundImage = "url(" + CurrentFrame.Image.Source + ")";
                                //BackgroundImage.src = CurrentFrame.Image.Source;

                                e.ReadyToTeleport();
                            }
                        );
                    }


                    return r;
                };
            #endregion


            var dude = CreateDude(LoadedCharacter);

            dude.Control.AttachTo(Ground);

            #region Doors
            var Doors = new[]
                {
                    new TryToChangeRoomsArgs
                            {
                                Condition = () => dude.CurrentLocation.X > ViewSize.Width - Margin,
                                NextRoomSelector = f => f.Name == CurrentFrame.Right,
                                ReadyToTeleport = delegate
                                {

                                    dude.TeleportTo(-MarginSafe, dude.CurrentLocation.Y);
                                    dude.LookAt(new Point(MarginSafe, (int)dude.CurrentLocation.Y));
                                }
                            },
                    new TryToChangeRoomsArgs
                            {
                                Condition = () => dude.CurrentLocation.X < Margin,
                                NextRoomSelector = f => f.Name == CurrentFrame.Left,
                                ReadyToTeleport = delegate
                                {

                                    dude.TeleportTo(ViewSize.Width + MarginSafe, dude.CurrentLocation.Y);
                                    dude.LookAt(new Point(ViewSize.Width - MarginSafe, (int)dude.CurrentLocation.Y));
                                }
                            },
                    new TryToChangeRoomsArgs
                            {
                                Condition = () => dude.CurrentLocation.Y < Margin,
                                NextRoomSelector = f => f.Name == CurrentFrame.Top,
                                ReadyToTeleport = delegate
                                {

                                     dude.TeleportTo(dude.CurrentLocation.X, ViewSize.Height + MarginSafe);
                                    dude.LookAt(new Point((int)dude.CurrentLocation.X, ViewSize.Height - MarginSafe));

                                }
                            },
                    new TryToChangeRoomsArgs
                            {
                                Condition = () => dude.CurrentLocation.Y > ViewSize.Height - Margin,
                                NextRoomSelector = f => f.Name == CurrentFrame.Bottom,
                                ReadyToTeleport = delegate
                                {

                                  dude.TeleportTo(dude.CurrentLocation.X, -Margin);
                                dude.LookAt(new Point((int)dude.CurrentLocation.X, MarginSafe));

                                }
                            }
                };
            #endregion

            Console.WriteLine(new { Doors = Doors.Length });

            Doors.WithEachIndex(
                (x, index) =>
                {
                    Console.WriteLine(new { index, x });
                    Console.WriteLine(new { index, x.Condition });
                }
            );


            var ChangeRoom = new ChangeRoom { autobuffer = true };
            var Talk = new Talk { autobuffer = true };
            var Argh_RChannel = new Argh_RChannel { autobuffer = true };
            var Argh_LChannel = new Argh_LChannel { autobuffer = true };
            var Argh_Disabled = false;
            var Argh_VolumeMultiplier = 1.0;

            #region Argh_Stereo
            Action<double, double> Argh_Stereo =
                (volume, balance) =>
                {
                    if (Argh_Disabled)
                        return;

                    Argh_RChannel.AttachToDocument();
                    Argh_LChannel.AttachToDocument();

                    Argh_RChannel.volume = Argh_VolumeMultiplier * volume * balance;
                    Argh_LChannel.volume = Argh_VolumeMultiplier * volume * (1 - balance);

                    Argh_RChannel.play();
                    Argh_LChannel.play();

                    Argh_RChannel = new Argh_RChannel { autobuffer = true };
                    Argh_LChannel = new Argh_LChannel { autobuffer = true };

                    Argh_Disabled = true;
                    Argh_VolumeMultiplier /= 2;

                    new Timer(t => Argh_Disabled = false).StartTimeout(800);
                    new Timer(t => Argh_VolumeMultiplier = 1).StartTimeout(5000);
                };
            #endregion

            #region PrintText
            Action<string, Action> PrintText =
                (text, done) =>
                {
                    Talk.AttachToDocument();
                    Talk.load();
                    Talk.volume = Math.Min(1, dude.Zoom.DynamicZoom / 4);
                    Talk.play();
                    Talk = new Talk { autobuffer = true };

                    text.Length.Range().AsyncForEach(
                        i =>
                        {
                            Wallpaper.innerText = text.Left(i + 1);

                            var c = text[i];

                            if (LoadedScene.SlowText.Contains("" + c))
                                return 100.Random();

                            return 50.Random();
                        }, done
                    );
                };
            #endregion

            Action<string, Action> PrintRandomText =
                (text, done) => PrintText(text.Split(LoadedScene.TextDelimiter).Randomize().First(), done);




            dude.DoneWalking +=
                delegate
                {
                    // compiler bug: cannot invoke Action<func, action> delegate ?

                    System.Console.WriteLine("done walking in " + CurrentFrame.Name + " at " + dude.CurrentLocation);

                    var xFirstOrDefault = Doors.FirstOrDefault(d => d.Condition());

                    System.Console.WriteLine("done walking in " + new { xFirstOrDefault });

                    // Doors null?
                    if (TryToChangeRooms(xFirstOrDefault))
                        return;


                    if (CurrentFrame.Items != null)
                    {
                        var item = CurrentFrame.Items.Where(
                            i => new Point(i.X.ToInt32(), i.Y.ToInt32()).GetRange(dude.CurrentLocation) < i.R.ToInt32()
                            ).FirstOrDefault();

                        if (item != null)
                        {


                            dude.IsSelected = false;
                            dude.LookDown();

                            PrintRandomText(item.Text,
                                delegate
                                {

                                    dude.WalkingOnce +=
                                        delegate
                                        {
                                            Wallpaper.innerText = "";
                                        };

                                    dude.IsSelected = true;
                                }
                            );
                        }
                    }

                };

            #region AnimateRoomChange
            AnimateRoomChange =
                ReadyToTeleport =>
                {
                    var Step1 = default(System.Action);
                    var Step2 = default(System.Action);
                    var Step3 = default(Action);

                    Step1 =
                        delegate
                        {
                            tween.Done -= Step1;

                            ReadyToTeleport();

                            tween.Done += Step2;

                            ShowRoom();
                        };

                    Step2 =
                        delegate
                        {
                            tween.Done -= Step2;

                            dude.DoneWalking += Step3;

                            dude.IsWalking = true;

                        };

                    Step3 =
                        delegate
                        {
                            dude.DoneWalking -= Step3;

                            dude.IsSelected = true;
                        };

                    dude.IsSelected = false;

                    tween.Done += Step1;
                    // go left
                    HideRoom();

                    // http://stackoverflow.com/questions/3009888/autoplay-audio-files-on-an-ipad-with-html5
                    ChangeRoom.AttachToDocument();
                    ChangeRoom.load();
                    ChangeRoom.volume = 0.2;
                    ChangeRoom.play();
                    ChangeRoom = new ChangeRoom();
                };
            #endregion

            var pointer_x = 0;
            var pointer_y = 0;

            #region onmousemove
            Container.onmousemove +=
                ev =>
                {
                    if (Native.Document.pointerLockElement == Container)
                    {
                        if (dude.IsSelected)
                        {
                            var volume = Math.Min(1, dude.Zoom.DynamicZoom / 4);
                            var balance = dude.CurrentLocation.X / ViewSize.Width;

                            pointer_x += ev.movementX;
                            pointer_y += ev.movementY;

                            pointer_x = Math.Min(ViewSize.Width - 0, Math.Max(0, pointer_x));
                            pointer_y = Math.Min(ViewSize.Height - 0, Math.Max(0, pointer_y));

                            var OffsetPosition = new Point(pointer_x, pointer_y

                            );

                            Console.WriteLine(OffsetPosition);

                            Argh_Stereo(volume, balance);
                            dude.WalkTo(OffsetPosition);
                        }
                    }
                };
            #endregion

            #region ontouchstart
            Container.ontouchstart +=
                ev =>
                {
                    ev.preventDefault();

                    System.Console.WriteLine(ev.CursorPosition);

                    if (dude.IsSelected)
                    {
                        var volume = Math.Min(1, dude.Zoom.DynamicZoom / 4);
                        var balance = dude.CurrentLocation.X / ViewSize.Width;

                        var ev_OffsetPosition = new Point(
                            ev.touches[0].clientX - Container.Bounds.Left,
                            ev.touches[0].clientY - Container.Bounds.Top
                            );

                        Argh_Stereo(volume, balance);
                        dude.WalkTo(ev_OffsetPosition);
                    }
                };
            #endregion

            #region onclick
            Container.onclick +=
                ev =>
                {
                    ev.preventDefault();

                    if (ev.MouseButton == IEvent.MouseButtonEnum.Middle)
                    {
                        if (Native.Document.pointerLockElement == Container)
                        {
                            Native.Document.exitPointerLock();
                            return;
                        }

                        pointer_x = (int)dude.CurrentLocation.X;
                        pointer_y = (int)dude.CurrentLocation.Y;

                        //Container.requestFullscreen();
                        Container.requestPointerLock();
                        return;
                    }

                    if (ev.Element != Ground)
                        return;

                    System.Console.WriteLine(ev.CursorPosition);

                    if (dude.IsSelected)
                    {
                        var volume = Math.Min(1, dude.Zoom.DynamicZoom / 4);
                        var balance = dude.CurrentLocation.X / ViewSize.Width;

                        Argh_Stereo(volume, balance);
                        dude.WalkTo(ev.OffsetPosition);
                    }
                };
            #endregion



            //GroundOverlay.onclick +=
            //    ev =>
            //    {
            //        if (ev.Element != GroundOverlay)
            //            return;

            //        System.Console.WriteLine(ev.CursorPosition);

            //        if (dude.IsSelected)
            //        {
            //            new Argh().play();

            //            dude.WalkTo(ev.OffsetPosition);
            //        }
            //    };


            dude.TeleportTo(ViewSize.Width / 2, (ViewSize.Height - MarginSafe) / 2);
            dude.LookDown();

            ShowRoom();

            dude.DoneWalkingOnce +=
                delegate
                {
                    PrintRandomText(
                        LoadedScene.IntroText,
                        delegate
                        {

                            dude.WalkingOnce +=
                              delegate
                              {
                                  Wallpaper.innerText = "";
                              };

                            dude.IsSelected = true;
                        }
                    );
                };

            dude.WalkToArc(MarginSafe, dude.Direction);

        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            //FormStyler.AtFormCreated =
            //s =>
            //{
            //    s.Context.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

            //    //var x = new ChromeTCPServerWithFrameNone.HTML.Pages.AppWindowDrag().AttachTo(s.Context.GetHTMLTarget());
            //    var x = new ChromeTCPServerWithFrameNone.HTML.Pages.AppWindowDragWithShadow().AttachTo(s.Context.GetHTMLTarget());



            //    s.Context.GetHTMLTarget().style.backgroundColor = "#efefef";
            //    //s.Context.GetHTMLTarget().style.backgroundColor = "#A26D41";

            //};

#if AsWEBSERVER
            #region += Launched chrome.app.window
            // X:\jsc.svn\examples\javascript\chrome\apps\ChromeTCPServerAppWindow\ChromeTCPServerAppWindow\Application.cs
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                // if we run as a server. we can open up on android.

                //chrome.Notification.DefaultTitle = "Nexus7";
                //chrome.Notification.DefaultIconUrl = new x128().src;
                ChromeTCPServer.TheServerWithStyledForm.Invoke(
                     AppSource.Text
                //, AtFormCreated: FormStyler.AtFormCreated

                //AtFormConstructor:
                //    f =>
                //    {
                //        //arg[0] is typeof System.Int32
                //        //script: error JSC1000: No implementation found for this native method, please implement [static System.Drawing.Color.FromArgb(System.Int32)]

                //        // X:\jsc.svn\examples\javascript\forms\Test\TestFromArgb\TestFromArgb\ApplicationControl.cs

                //        f.BackColor = System.Drawing.Color.FromArgb(0xA26D41);
                //    }
                );
                return;
            }
            #endregion
#else

            #region += Launched chrome.app.window
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    //chrome.runtime.UpdateAvailable += delegate
                    //{
                    //    new chrome.Notification(title: "UpdateAvailable");

                    //};

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "x360stereomidnightsun");

                        // https://developer.chrome.com/apps/app_window#type-CreateWindowOptions
                        var xappwindow = await chrome.app.window.create(
                               Native.document.location.pathname, options: new
                               {
                                   alwaysOnTop = true,
                                   visibleOnAllWorkspaces = true
                               }
                        );

                        //xappwindow.setAlwaysOnTop

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion


#endif


            // crash
            //int cubefacesizeMAX = 2048 * 2; // 6 faces, ?
            int cubefacesizeMAX = 1024; // 6 faces, ?
            int cubefacesize = cubefacesizeMAX; // 6 faces, ?
            //int cubefacesize = 1024; // 6 faces, ?
            // "X:\vr\tape1\0000x2048.png"
            // for 60hz render we may want to use float camera percision, not available for ui.
            //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\tape1\0000x2048.png" "/sdcard/oculus/360photos/"
            //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\tape1\0000x128.png" "/sdcard/oculus/360photos/"

            if (Environment.ProcessorCount < 8)
                //cubefacesize = 64; // 6 faces, ?

                // fast gif?
                cubefacesize = 1024; // 6 faces, ?


            // can we keep fast fps yet highp?

            // can we choose this on runtime? designtime wants fast fps, yet for end product we want highdef on our render farm?
            //const int cubefacesize = 128; // 6 faces, ?

            //var cubecameraoffsetx = 256;
            var cubecameraoffsetx = 400;


            //var uizoom = 0.1;
            //var uizoom = cubefacesize / 128f;
            var uizoom = 128f / cubefacesize;


            Native.css.style.backgroundColor = "darkcyan";
            Native.css.style.overflow = IStyle.OverflowEnum.hidden;

            Native.body.Clear();
            (Native.body.style as dynamic).webkitUserSelect = "text";

            IHTMLCanvas shader1canvas = null;




            //return;

            // Earth params
            //var radius = 0.5;
            //var radius = 1024;
            //var radius = 2048;
            //var radius = 512;
            //var radius = 256;
            //var radius = 400;

            // can we have not fly beyond moon too much?
            //var radius = 500;
            var radius = 480;

            //var segments = 32;
            var segments = 128 * 2;
            //var rotation = 6;


            //const int size = 128;
            //const int size = 256; // 6 faces, 12KB
            //const int size = 512; // 6 faces, ?

            // WebGL: drawArrays: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'. Or the texture is Float or Half Float type with linear filtering while OES_float_linear or OES_half_float_linear extension is not enabled.

            //const int size = 720; // 6 faces, ?
            //const int size = 1024; // 6 faces, ?
            //const int cubefacesize = 1024; // 6 faces, ?

            // THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter is set to THREE.LinearFilter or THREE.NearestFilter. ( chrome-extension://aemlnmcokphbneegoefdckonejmknohh/assets/x360stereomidnightsun/anvil___spherical_hdri_panorama_skybox_by_macsix_d6vv4hs.jpg )


            var far = 0xffffff;

            new IHTMLPre { new { Environment.ProcessorCount, cubefacesize } }.AttachToDocument();

            //new IHTMLPre { "can we stream it into VR, shadertoy, youtube 360, youtube stereo yet?" }.AttachToDocument();


            var sw = Stopwatch.StartNew();



            var oo = new List<THREE.Object3D>();

            var window = Native.window;


            // what about physics and that portal rendering?

            // if we are running as a chrome web server, we may also be opened as android ndk webview app
            //var cameraPX = new THREE.PerspectiveCamera(fov: 90, aspect: window.aspect, near: 1, far: 2000);
            // once we update source
            // save the source
            // manually recompile 
            //cameraPX.position.z = 400;

            //// the camera should be close enough for the object to float off the FOV of PX
            //cameraPX.position.z = 200;

            // scene
            // can we make the 3D object orbit around us ?
            // and
            // stream it to vr?
            var scene = new THREE.Scene();



            // since our cube camera is somewhat a fixed thing
            // would it be easier to move mountains to come to us?
            // once we change code would chrome app be able to let VR know that a new view is available?
            var sceneg = new THREE.Group();
            sceneg.AttachTo(scene);


            // fly up?
            //sceneg.translateZ(-1024);
            // rotate the world, as the skybox then matches what we have on filesystem
            scene.rotateOnAxis(new THREE.Vector3(0, 1, 0), -Math.PI / 2);
            // yet for headtracking we shall rotate camera


            //sceneg.position.set(0, 0, -1024);
            //sceneg.position.set(0, -1024, 0);

            //scene.add(new THREE.AmbientLight(0x333333));
            //scene.add(new THREE.AmbientLight(0xffffff));
            //scene.add(new THREE.AmbientLight(0xaaaaaa));
            //scene.add(new THREE.AmbientLight(0xcccccc));
            //scene.add(new THREE.AmbientLight(0xeeeeee));
            scene.add(new THREE.AmbientLight(0xffffff));




            //var light = new THREE.DirectionalLight(0xffffff, 1);
            //// sun should be beyond moon
            ////light.position.set(-5 * virtualDistance, -3 * virtualDistance, -5 * virtualDistance);
            ////light.position.set(-15 * virtualDistance, -1 * virtualDistance, -15 * virtualDistance);

            //// where shall the light source be to see half planet?
            //light.position.set(-1 * virtualDistance, -1 * virtualDistance, -15 * virtualDistance);
            //scene.add(light);



            //var lightX = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -60, max = 60, valueAsNumber = 0, title = "lightX" }.AttachToDocument();
            //var lightY = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -60, max = 60, valueAsNumber = 0, title = "lightY" }.AttachToDocument();
            //var lightZ = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -60, max = 60, valueAsNumber = 0, title = "lightZ" }.AttachToDocument();

            //new IHTMLHorizontalRule { }.AttachToDocument();

            // whats WebGLRenderTargetCube do?

            // WebGLRenderer preserveDrawingBuffer 



            var renderer0 = new THREE.WebGLRenderer(

                new
                {
                    //antialias = true,
                    alpha = true,
                    preserveDrawingBuffer = true
                }
            );

            // https://github.com/mrdoob/three.js/issues/3836

            // the construct. white bg
            //renderer0.setClearColor(0xfffff, 1);
            //renderer0.setClearColor(0x0, 1);
            renderer0.setClearColor(0x0, 0);

            //renderer.setSize(window.Width, window.Height);
            renderer0.setSize(cubefacesize, cubefacesize);

            //renderer0.domElement.AttachToDocument();
            //rendererPX.domElement.style.SetLocation(0, 0);
            //renderer0.domElement.style.SetLocation(4, 4);


            // top

            // http://stackoverflow.com/questions/27612524/can-multiple-webglrenderers-render-the-same-scene


            // need a place to show the cubemap face to GUI 
            // how does the stereo OTOY do it?
            // https://www.opengl.org/wiki/Sampler_(GLSL)

            // http://www.richardssoftware.net/Home/Post/25

            // [+X, –X, +Y, –Y, +Z, –Z] fa



            // move up
            //camera.position.set(-1200, 800, 1200);
            //var cameraoffset = new THREE.Vector3(0, 15, 0);

            // can we aniamte it?
            //var cameraoffset = new THREE.Vector3(0, 800, 1200);
            // can we have linear animation fromcenter of the map to the edge and back?
            // then do the flat earth sun orbit?
            var cameraoffset = new THREE.Vector3(
                // left?
                -512,
                // height?
                //0,
                //1600,
                //1024,

                // if the camera is in the center, would we need to move the scene?
                // we have to move the camera. as we move the scene the lights are messed up
                //2014,
                1024,

                //1200
                0
                // can we hover top of the map?
                );

            // original vieworigin
            //var cameraoffset = new THREE.Vector3(-1200, 800, 1200);

            // whatif we want more than 30sec video? 2min animation? more frames to render? 2gb disk?





            var maxfps = 60;
            //var maxlengthseconds = 60;
            var maxlengthseconds = 120;

            var maxframes = maxlengthseconds * maxfps;

            var frameIDanimation = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.checkbox, title = "frameIDanimation", @checked = false }.AttachToDocument();

            // whatif we want more than 30sec video? 2min animation? more frames to render? 2gb disk?
            var frameIDslider = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = 0, max = maxframes, valueAsNumber = 0, title = "frameIDslider" }.AttachToDocument();
            //var frameIDslider = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = 0, max = 1800, valueAsNumber = 1800 / 2, title = "frameIDslider" }.AttachToDocument();




            new IHTMLHorizontalRule { }.AttachToDocument();

            var camerax = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -32, max = 32, valueAsNumber = 0, title = "camerax" }.AttachToDocument();
            camerax.css.after.contentText = "x: ";
            new IHTMLBreak { }.AttachToDocument();

            //camerax.style.borderLeft = "1em solid red";

            // up. whats the most high a rocket can go 120km?
            //new IHTMLHorizontalRule { }.AttachToDocument();

            // how high is the bunker?
            var cameray = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -32, max = 32, valueAsNumber = 0, title = "cameray" }.AttachToDocument();
            cameray.css.after.contentText = "y: ";
            new IHTMLBreak { }.AttachToDocument();

            // we wont be going to orbit
            //new IHTMLBreak { }.AttachToDocument();
            //var camerayHigh = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = cameray.max, max = 1024 * 256, valueAsNumber = cameray.max, title = "cameray" }.AttachToDocument();
            //new IHTMLHorizontalRule { }.AttachToDocument();
            //var cameraz = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = 0 - 2048 * 4, max = 0 + 2048 * 4, valueAsNumber = 0, title = "cameraz" }.AttachToDocument();
            //var cameraz = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -2048 / 2, max = 0 + 2048 / 2, valueAsNumber = 0, title = "cameraz" }.AttachToDocument();
            var cameraz = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -32, max = 32, valueAsNumber = 0, title = "cameraz" }.AttachToDocument();
            cameraz.css.after.contentText = "z: ";

            // for render server
            var fcamerax = 0.0;
            var fcameray = 0.0;
            var fcameraz = 0.0;


            new IHTMLHorizontalRule { }.AttachToDocument();





            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151114/stereo

            // not used for this example tho...
            var itemRotation = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -180, max = 180, valueAsNumber = 0, title = "itemRotation" }.AttachToDocument();
            var spriteOffset = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = 0, max = 11, valueAsNumber = 0, title = "spriteOffset" }.AttachToDocument();
            //var itemRotation = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -90, max = 90, valueAsNumber = 33, title = "itemRotation" }.AttachToDocument();

            //while (await camerax.async.onchange)

            //cameray.onchange += delegate
            //{
            //    if (cameray.valueAsNumber < cameray.max)
            //        camerayHigh.valueAsNumber = camerayHigh.min;
            //};

            //camerayHigh.onmousedown += delegate
            //{
            //    //if (camerayHigh.valueAsNumber > camerayHigh.min)
            //    cameray.valueAsNumber = cameray.max;
            //};


            Action applycameraoffset = delegate
            {
                // make sure UI and gpu sync up

                var cy = cameray;



                // we wont be going to orbit

                //if (cameray.valueAsNumber < cameray.max)
                //    camerayHigh.valueAsNumber = camerayHigh.min;

                //if (camerayHigh.valueAsNumber > camerayHigh.min)
                //    cameray.valueAsNumber = cameray.max;

                //if (cameray.valueAsNumber == cameray.max)
                //    cy = camerayHigh;



                cameraoffset = new THREE.Vector3(
                    // left?
                  1.0 * (camerax + fcamerax),
                    // height?
                    //0,
                    //1600,
                    //1024,

                   // if the camera is in the center, would we need to move the scene?
                    // we have to move the camera. as we move the scene the lights are messed up
                    //2014,
                   1.0 * (cy + fcameray),

                 //1200c
                 1.0 * (cameraz + fcameraz)
                    // can we hover top of the map?
                   );
            };


            #region y
            // need to rotate90?
            var cameraNY = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            applycameraoffset += delegate
            {
                cameraNY.position.copy(new THREE.Vector3(0, 0, 0));
                cameraNY.lookAt(new THREE.Vector3(0, -1, 0));
                cameraNY.position.add(cameraoffset);
            };

            //cameraNY.lookAt(new THREE.Vector3(0, 1, 0));
            var canvasNY = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasNY.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 1, 8 + (int)(uizoom * cubefacesize + 8) * 2);
            canvasNY.canvas.title = "NY";
            canvasNY.canvas.AttachToDocument();
            canvasNY.canvas.style.transformOrigin = "0 0";
            // roslyn!
            canvasNY.canvas.style.transform = "scale(" + uizoom + ")";

            var cameraPY = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            applycameraoffset += delegate
            {
                cameraPY.position.copy(new THREE.Vector3(0, 0, 0));
                cameraPY.lookAt(new THREE.Vector3(0, 1, 0));
                cameraPY.position.add(cameraoffset);
            };
            //cameraPY.lookAt(new THREE.Vector3(0, -1, 0));
            var canvasPY = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPY.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 1, 8 + (int)(uizoom * cubefacesize + 8) * 0);
            canvasPY.canvas.title = "PY";
            canvasPY.canvas.AttachToDocument();
            canvasPY.canvas.style.transformOrigin = "0 0";
            canvasPY.canvas.style.transform = "scale(" + uizoom + ")";
            #endregion

            // transpose xz?

            #region x
            var cameraNX = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            applycameraoffset += delegate
            {
                cameraNX.position.copy(new THREE.Vector3(0, 0, 0));
                cameraNX.lookAt(new THREE.Vector3(0, 0, 1));
                cameraNX.position.add(cameraoffset);
            };
            //cameraNX.lookAt(new THREE.Vector3(0, 0, -1));
            //cameraNX.lookAt(new THREE.Vector3(-1, 0, 0));
            //cameraNX.lookAt(new THREE.Vector3(1, 0, 0));
            var canvasNX = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasNX.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 2, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasNX.canvas.title = "NX";
            canvasNX.canvas.AttachToDocument();
            canvasNX.canvas.style.transformOrigin = "0 0";
            canvasNX.canvas.style.transform = "scale(" + uizoom + ")";

            var cameraPX = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            applycameraoffset += delegate
            {
                cameraPX.position.copy(new THREE.Vector3(0, 0, 0));
                cameraPX.lookAt(new THREE.Vector3(0, 0, -1));
                cameraPX.position.add(cameraoffset);
            };
            //cameraPX.lookAt(new THREE.Vector3(0, 0, 1));
            //cameraPX.lookAt(new THREE.Vector3(1, 0, 0));
            //cameraPX.lookAt(new THREE.Vector3(-1, 0, 0));

            var canvasPX = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPX.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 0, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasPX.canvas.title = "PX";
            canvasPX.canvas.AttachToDocument();
            canvasPX.canvas.style.transformOrigin = "0 0";
            canvasPX.canvas.style.transform = "scale(" + uizoom + ")";
            #endregion

            // lets have the item twice the cube item size. and offset -0.5 to recenter.
            // this wont work as we are cloning the buffer for now!
            //var canvasPXitem = new CanvasRenderingContext2D(cubefacesize, cubefacesize * 2);
            var canvasPXitem = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPXitem.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 0, 8 + (int)(uizoom * cubefacesize + 8) * 2);
            canvasPXitem.canvas.title = "item";
            canvasPXitem.canvas.AttachToDocument();
            canvasPXitem.canvas.style.transformOrigin = "0 0";
            canvasPXitem.canvas.style.transform = "scale(" + uizoom + ")";
            canvasPXitem.canvas.style.border = "1px solid yellow";

            //canvasPXitem.fillText("hello", 1, 1, cubefacesize);

            //canvasPXitem.drawImage(
            //    //new IHTMLPre { "hello" }
            //    new IHTMLDiv { "hello world. can we draw html into 360 VR yet?" }, 0, 0, cubefacesize, cubefacesize
            //);







            // http://www.w3schools.com/tags/canvas_fillstyle.asp
            canvasPXitem.fillStyle = "red";

            // too big?
            //canvasPXitem.fillRect(
            //    x: cubefacesize / 3,
            //    y: cubefacesize / 4,
            //    w: cubefacesize / 3,
            //    h: cubefacesize / 2
            //);



            // canvasPXitem.fillRect(
            //    x: (cubefacesize - cubefacesize / 6) / 2,
            //    y: (cubefacesize - cubefacesize / 3) / 2,

            //    w: cubefacesize / 6,
            //    h: cubefacesize / 3
            //);



            #region z
            var cameraNZ = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            //cameraNZ.lookAt(new THREE.Vector3(0, 0, -1));
            applycameraoffset += delegate
            {
                cameraNZ.position.copy(new THREE.Vector3(0, 0, 0));
                cameraNZ.lookAt(new THREE.Vector3(1, 0, 0));
                cameraNZ.position.add(cameraoffset);
            };
            //cameraNX.lookAt(new THREE.Vector3(-1, 0, 0));
            //cameraNZ.lookAt(new THREE.Vector3(0, 0, 1));
            var canvasNZ = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasNZ.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 3, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasNZ.canvas.title = "NZ";
            canvasNZ.canvas.AttachToDocument();
            canvasNZ.canvas.style.transformOrigin = "0 0";
            canvasNZ.canvas.style.transform = "scale(" + uizoom + ")";

            var cameraPZ = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            //cameraPZ.lookAt(new THREE.Vector3(1, 0, 0));
            applycameraoffset += delegate
            {
                cameraPZ.position.copy(new THREE.Vector3(0, 0, 0));
                cameraPZ.lookAt(new THREE.Vector3(-1, 0, 0));
                cameraPZ.position.add(cameraoffset);
            };
            //cameraPZ.lookAt(new THREE.Vector3(0, 0, 1));
            //cameraPZ.lookAt(new THREE.Vector3(0, 0, -1));
            var canvasPZ = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPZ.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 1, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasPZ.canvas.title = "PZ";
            canvasPZ.canvas.AttachToDocument();
            canvasPZ.canvas.style.transformOrigin = "0 0";
            canvasPZ.canvas.style.transform = "scale(" + uizoom + ")";
            #endregion




            // c++ alias locals would be nice..
            var canvas0 = (IHTMLCanvas)renderer0.domElement;


            var old = new
            {



                CursorX = 0,
                CursorY = 0
            };


            var st = new Stopwatch();
            st.Start();

            //canvas0.css.active.style.cursor = IStyle.CursorEnum.move;




            // X:\jsc.svn\examples\javascript\Test\TestMouseMovement\TestMouseMovement\Application.cs


            // THREE.WebGLProgram: gl.getProgramInfoLog() C:\fakepath(78,3-98): warning X3557: loop only executes for 1 iteration(s), forcing loop to unroll
            // THREE.WebGLProgram: gl.getProgramInfoLog() (79,3-98): warning X3557: loop only executes for 1 iteration(s), forcing loop to unroll

            // http://www.roadtovr.com/youtube-confirms-stereo-3d-360-video-support-coming-soon/
            // https://www.youtube.com/watch?v=D-Wl9jAB45Q



            #region spherical
            var gl = new WebGLRenderingContext(alpha: true, preserveDrawingBuffer: true);
            var c = gl.canvas.AttachToDocument();

            //  3840x2160

            //c.style.SetSize(3840, 2160);

            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150722/360-youtube

            // bots cannot get a bigger mp4 from yt, and vrideo renders 2k on gearvr.
            c.width = 3840;
            c.height = 2160;


            //c.width = 3840 * 2;
            //c.height = 2160 * 2;


            //c.width = 3840;
            //c.height = 2160;
            // 1,777777777777778

            // https://www.youtube.com/watch?v=fTfJwzRsE-w
            //c.width = 7580;
            //c.height = 3840;
            //1,973958333333333

            //7580
            //    3840

            // wont work
            //c.width = 8192;
            //c.height = 4096;


            // this has the wrong aspect?
            //c.width = 6466;
            //c.height = 3232;

            new IHTMLPre { new { c.width, c.height } }.AttachToDocument();

            //6466x3232

            //var suizoom = 720f / c.height;
            //var suizoom = 360f / c.height;
            var suizoom = 480f / c.width;

            c.style.transformOrigin = "0 0";
            c.style.transform = "scale(" + suizoom + ")";
            //c.style.backgroundColor = "yellow";
            c.style.position = IStyle.PositionEnum.absolute;

            c.style.SetLocation(8 + (int)(uizoom * cubefacesize + 8) * 0, 8 + (int)(uizoom * cubefacesize + 8) * 3);

            var pass = new CubeToEquirectangular.Library.ShaderToy.EffectPass(
                       null,
                       gl,
                       precission: CubeToEquirectangular.Library.ShaderToy.DetermineShaderPrecission(gl),
                       supportDerivatives: gl.getExtension("OES_standard_derivatives") != null,
                       callback: null,
                       obj: null,
                       forceMuted: false,
                       forcePaused: false,
                //quadVBO: Library.ShaderToy.createQuadVBO(gl, right: 0, top: 0),
                       outputGainNode: null
                   );

            // how shall we upload our textures?
            // can we reference GLSL.samplerCube yet?
            //pass.mInputs[0] = new samplerCube { };
            pass.mInputs[0] = new CubeToEquirectangular.Library.ShaderToy.samplerCube { };

            pass.MakeHeader_Image();
            var vs = new Shaders.ProgramFragmentShader();
            pass.NewShader_Image(vs);

            #endregion




            //var frame0 = new HTML.Images.FromAssets.tiles_regrid().AttachToDocument();
            var frame0 = new HTML.Images.FromAssets.galaxy_starfield().AttachToDocument();
            //var frame0 = new HTML.Images.FromAssets.galaxy_starfield150FOV().AttachToDocument();
            //var xor = new HTML.Images.FromAssets.Orion360_test_image_8192x4096().AttachToDocument();
            //var xor = new HTML.Images.FromAssets._2_no_clouds_4k().AttachToDocument();
            //var frame0 = new HTML.Images.FromAssets._2294472375_24a3b8ef46_o().AttachToDocument();


            // 270px
            //xor.style.height = "";
            frame0.style.height = "270px";
            frame0.style.width = "480px";
            frame0.style.SetLocation(
                8 + (int)(uizoom * cubefacesize + 8) * 0 + 480 + 16, 8 + (int)(uizoom * cubefacesize + 8) * 3);



            var frame2 = new HTML.Images.FromAssets.galaxy_starfield().AttachToDocument();

            frame2.style.height = "270px";
            frame2.style.width = "480px";
            frame2.style.SetLocation(
                8 + (int)(uizoom * cubefacesize + 8) * 0 + 480 * 2 + 16 * 2, 8 + (int)(uizoom * cubefacesize + 8) * 3);




            #region DirectoryEntry
            var dir = default(DirectoryEntry);

            new IHTMLButton { "openDirectory" }.AttachToDocument().onclick += async delegate
            {
                dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });
            };
            frame0.style.cursor = IStyle.CursorEnum.pointer;
            frame0.title = "save frame";


            frame0.onclick += delegate
            {
                // http://paulbourke.net/papers/vsmm2006/vsmm2006.pdf
                //            A method of creating synthetic stereoscopic panoramic images that can be implemented
                //in most rendering packages has been presented. If single panoramic pairs can be created
                //then stereoscopic panoramic movies are equally possible giving rise to the prospect of
                //movies where the viewer can interact with, at least with regard to what they choose to look
                //at.These images can be projected so as to engage the two features of the human visual
                //system that assist is giving us a sense of immersion, the feeling of “being there”. That is,
                //imagery that contains parallax information as captured from two horizontally separated eye
                //positions (stereopsis)and imagery that fills our peripheral vision.The details that define
                //how the two panoramic images should be created in rendering packages are provided, in
                //particular, how to precisely configure the virtual cameras and control the distance to zero
                //parallax.

                // grab a frame

                if (dir == null)
                {
                    // not exporting to file system?
                    var f0 = new IHTMLImage { src = gl.canvas.toDataURL() };

                    //var f0 = (IHTMLImage)gl.canvas;
                    //var f0 = (IHTMLImage)gl.canvas;
                    //var base64 = gl.canvas.toDataURL();


                    //frame0.src = base64;
                    frame0.src = f0.src;

                    // 7MB!

                    return;
                }

                //                // ---------------------------
                //IrfanView
                //---------------------------
                //Warning !
                //The file: "X:\vr\tape1\0001.jpg" is a PNG file with incorrect extension !
                //Rename ?
                //---------------------------
                //Yes   No   
                //---------------------------

                // haha this will render the thumbnail.
                //dir.WriteAllBytes("0000.png", frame0);

                //dir.WriteAllBytes("0000.png", gl.canvas);

                var glsw = Stopwatch.StartNew();
                dir.WriteAllBytes("0000.png", gl);

                new IHTMLPre { new { glsw.ElapsedMilliseconds } }.AttachToDocument();

                // {{ ElapsedMilliseconds = 1548 }}

                // 3.7MB
                // 3840x2160

            };

            #endregion

            var vsync = default(TaskCompletionSource<object>);


            // "Z:\jsc.svn\examples\javascript\WebGL\WebGLColladaExperiment\WebGLColladaExperiment\WebGLColladaExperiment.csproj"






            // asus will hang
            // https://3dwarehouse.sketchup.com/model.html?id=fb7a0448d940e575edc01389f336fb0a
            // can we get one frame into vr?

            // cube: mesh to cast shadows



            //{
            //    var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
            //    var floor2 = new THREE.Mesh(planeGeometry0,
            //        //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
            //        //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
            //        //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
            //        new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000 })

            //    );
            //    floor2.position.set(0, 0, -cubefacesize / 2);
            //    floor2.AttachTo(scene);
            //}
            //{
            //    var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
            //    var floor2 = new THREE.Mesh(planeGeometry0,
            //        //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
            //        //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
            //        //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
            //        new THREE.MeshPhongMaterial(new { ambient = 0x0000ff, color = 0x0000ff })

            //    );
            //    floor2.position.set(-cubefacesize / 2, 0, 0);
            //    floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI / 2);

            //    floor2.AttachTo(scene);
            //}

            //var tex0 = new THREE.Texture { image = new moon(), needsUpdate = true };
            //var tex0 = new THREE.Texture(new moon());
            //var tex0 = new THREE.Texture(new moon()) { needsUpdate = true };
            var texPXitem = new THREE.Texture(

                //shader1canvas

                canvasPXitem.canvas

                ) { needsUpdate = true };


            var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
            var floor2 = new THREE.Mesh(planeGeometry0,
                //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
                //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
                //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
                new THREE.MeshPhongMaterial(
                    new
                    {

                        map = texPXitem,

                        transparent = true,
                        alphaTest = 0.5

                        //ambient = 0x00ff00,
                        //color = 0x00ff00
                    })

            );
            //floor2.position.set(0, 0, -cubefacesize  * 0.55);

            floor2.AttachTo(scene);

            applycameraoffset += delegate
            {
                texPXitem.needsUpdate = true;

                //floor2.position.set(-cubefacesize * 0.5, 0, 0);
                //floor2.position.set(-cubefacesize * 0.33, 0, 0);
                // floor2.position.set(-cubefacesize * 0.25, 0, 0);

                //floor2.position.set(-cubefacesize * 0.225, 0, 0);
                floor2.position.set(-cubefacesize * 0.23, 0, 0);

                // too close!
                //floor2.position.set(-cubefacesize * 0.20, 0, 0);

                floor2.rotation.set(0, 0, 0);
                floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI / 2 + radians(itemRotation.valueAsNumber));
            };






            // X:\jsc.svn\examples\javascript\chrome\apps\ChromeEarth\ChromeEarth\Application.cs
            // X:\jsc.svn\examples\javascript\canvas\ConvertBlackToAlpha\ConvertBlackToAlpha\Application.cs
            // hidden for alpha AppWindows
            //#if FBACKGROUND

            new IHTMLBreak { }.AttachToDocument();

            var iskybox2 = new HTML.Images.FromAssets._2massAllskyGAMMA();
            var iskybox1 = new HTML.Images.FromAssets.anvil___spherical_hdri_panorama_skybox_by_macsix_d6vv4hs();

            var hideskybox1 = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.checkbox, title = "hide skybox1", @checked = true }.AttachToDocument();
            var hideskybox2 = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.checkbox, title = "hide skybox2", @checked = false }.AttachToDocument();

            #region drawStereoFrame
            Func<CanvasRenderingContext2D, Task> drawStereoFrame = async canvasTB =>
            {
                //var xIPD = 4.0;
                var xIPD = 6.0;

                // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151203/x360stereomidnightsun

                // fake skybox?
                canvasTB.fillStyle = "darkcyan";
                canvasTB.fillRect(0, 0, c.width, c.height);

                //canvasTB.drawImage(stereoT, 0, 0, c.width, c.height, 0, 0, c.width, c.height / 2);
                //canvasTB.drawImage(stereoB, 0, 0, c.width, c.height, 0, c.height / 2, c.width, c.height / 2);

                // 12 frames in total. lets add em all
                // can we add a secondary stereo frame ? at 45deg?

                var offsetrotation = 360 / 12;

                hideskybox1.@checked = true;
                hideskybox2.@checked = false;

                // mono bg!
                floor2.visible = false;
                fcamerax = 0;
                await Native.window.async.onframe;
                await Native.window.async.onframe;

                canvasTB.drawImage(gl.canvas, 0, 0, c.width, c.height, 0, 0, c.width, c.height / 2);
                canvasTB.drawImage(gl.canvas, 0, 0, c.width, c.height, 0, c.height / 2, c.width, c.height / 2);

                // keep only bg. hide stereo sprite
                floor2.visible = true;

                //await Native.window.async.onframe;


                // we need our stereo item frame thanks. no bg.
                hideskybox1.@checked = true;
                hideskybox2.@checked = true;

                await Native.window.async.onframe;






                //fcamerax = -xIPD;
                //await Native.window.async.onframe;
                //var stereoT = new IHTMLImage { src = gl.canvas.toDataURL() };

                //fcamerax = +xIPD;

                //await Native.window.async.onframe;
                //var stereoB = new IHTMLImage { src = gl.canvas.toDataURL() };

                ////await Native.window.async.onframe;
                //await stereoB.async.oncomplete;


                // we now have a stereo sprite.
                // can we rotate it on top of the background?


                // 8K fulldome is a resolution of 8192×8192 
                // 8K UHD is a resolution of 7680 × 4320 (33.2 megapixels) 
                // 8192×4320 t
                // Digital video formats with resolutions of 4K (3840×2160) and 8K (7680×4320)


                // WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost ?
                for (int stereoframei = 0; stereoframei < 12; stereoframei++)
                {
                    spriteOffset.valueAsNumber = stereoframei;

                    Console.WriteLine(new { stereoframei });
                    double ioffsetdeg = offsetrotation * stereoframei;


                    ioffsetdeg += (degrees(frameIDslider.valueAsNumber / (60 * 60 / 5.0) * Math.PI * 2));


                    // follow the moon?
                    //stars.rotateOnAxis(new THREE.Vector3(0, -1, 0),
                    //    frameIDslider.valueAsNumber / (60 * 60 / 5.0) * Math.PI * 2
                    //);


                    var ipxoffset = (int)Math.Floor(c.width * ioffsetdeg / 360);

                    ipxoffset = ipxoffset % c.width;

                    fcamerax = -xIPD;
                    await Native.window.async.onframe;
                    var stereoT = gl.canvas;
                    canvasTB.drawImage(stereoT, 0, 0, c.width, c.height, ipxoffset, 0, c.width, c.height / 2);
                    canvasTB.drawImage(stereoT, 0, 0, c.width, c.height, -c.width + ipxoffset, 0, c.width, c.height / 2);

                    fcamerax = +xIPD;
                    await Native.window.async.onframe;
                    var stereoB = gl.canvas;
                    canvasTB.drawImage(stereoB, 0, 0, c.width, c.height, ipxoffset, c.height / 2, c.width, c.height / 2);
                    canvasTB.drawImage(stereoB, 0, 0, c.width, c.height, -c.width + ipxoffset, c.height / 2, c.width, c.height / 2);
                }


                //var canvasTB8K = new CanvasRenderingContext2D(c.width * 2, c.height * 2);
                //canvasTB8K.drawImage(f0, 0, 0, c.width, c.height, 0, 0, c.width * 2, c.height);
                //canvasTB8K.drawImage(f1, 0, 0, c.width, c.height, 0, c.height, c.width * 2, c.height);

                // https://www.reddit.com/r/GearVR/comments/2vrfyu/id_suggest_makers_of_360_videos_make_them_the/
                // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151114/stereo
                // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151203
                // can we actually watch stereo _TB images on gearVR?

            };
            #endregion

            #region stero
            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151114/stereo
            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151112
            new IHTMLButton { "make me a stero TB image " }.AttachToDocument().With(
                async e =>
                {
                    // http://www.vrideo.com/watch/ALdE7mm
                    // https://www.youtube.com/watch?v=S3iTPxMIlCI

                    var onclick = e.async.onclick;

                    while (await onclick)
                    {




                        // keep it 4K, as hw, yt is not ready for 60fps 8K!
                        var canvasTB = new CanvasRenderingContext2D(c.width, c.height);

                        drawStereoFrame(canvasTB);

                        // gearVR will get a black screen
                        // 
                        //frame2.src = canvasTB8K.canvas.toDataURL();
                        frame2.src = canvasTB.canvas.toDataURL();


                        onclick = e.async.onclick;

                        //while (!onclick.IsCompleted)
                        //{
                        //    await Task.Delay(1000 / 30);
                        //    frame0.src = f0.src;
                        //    await Task.Delay(1000 / 30);
                        //    frame0.src = f1.src;
                        //}
                    }
                }
            );
            #endregion


            #region render 60hz 30sec
            new IHTMLButton {
                //"render 60hz 30sec"
                //$"render {maxfps}hz {maxlengthseconds}sec"
                "render " + new {maxfps} + "hz " + new {maxlengthseconds} + "sec"
            }.AttachToDocument().onclick += async e =>
            {
                e.Element.disabled = true;

                //var canvasTB = new CanvasRenderingContext2D(c.width * 2, c.height * 2);
                var canvasTB = new CanvasRenderingContext2D(c.width, c.height);


                var total = Stopwatch.StartNew();
                var status = "rendering... " + new { dir };

                new IHTMLPre { () => status }.AttachToDocument();

                if (dir == null)
                {
                    //dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });
                }

                total.Restart();



                //vsync = new TaskCompletionSource<object>();
                //await vsync.Task;

                status = "rendering... vsync";

                //var frameid = 0;
                //frameIDanimation.@checked = true;
                frameIDslider.valueAsNumber = -1;

                // allow the animation values to sink in
                //vsync = new TaskCompletionSource<object>();
                //await vsync.Task;



                goto beforeframe;


                // parallax offset?

                await_nextframe:


                var filename = frameIDslider.valueAsNumber.ToString().PadLeft(5, '0') + ".jpg";
                status = "rendering... " + new { filename };

                await drawStereoFrame(canvasTB);

                //var xIPD = 4.0;


                //// left eye
                //fcamerax = -xIPD;
                //vsync = new TaskCompletionSource<object>();
                //await vsync.Task;
                //var f0 = new IHTMLImage { src = gl.canvas.toDataURL() };


                //// right eye
                //fcamerax = +xIPD;
                //vsync = new TaskCompletionSource<object>();
                //await vsync.Task;
                //var f1 = new IHTMLImage { src = gl.canvas.toDataURL() };
                //await f1.async.oncomplete;



                //canvasTB.drawImage(f0, 0, 0, c.width, c.height, 0, 0, c.width * 2, c.height);
                //canvasTB.drawImage(f1, 0, 0, c.width, c.height, 0, c.height, c.width * 2, c.height);


                // frame0 has been rendered

                var swcapture = Stopwatch.StartNew();
                status = "WriteAllBytes... " + new { filename };
                //await Native.window.async.onframe;

                // https://code.google.com/p/chromium/issues/detail?id=404301
                if (dir == null)
                {
                    frame2.src = canvasTB.canvas.toDataURL();

                    await Task.Delay(500);
                }
                else
                    await dir.WriteAllBytes(filename, canvasTB);
                //await dir.WriteAllBytes(filename, gl);
                //await dir.WriteAllBytes(filename, gl.canvas);

                status = "WriteAllBytes... done " + new { fcamerax, filename, swcapture.ElapsedMilliseconds };
                status = "rdy " + new { filename, fcamerax };
                //await Native.window.async.onframe;





                // design mode v render mode
                if (cubefacesize < cubefacesizeMAX)
                    frameIDslider.valueAsNumber += 60;
                else
                    frameIDslider.valueAsNumber++;




            beforeframe:

                // speed? S6 slow motion?
                // this is really slow. if we do x4x2 =x8 
                // https://www.youtube.com/watch?v=r76ULW16Ib8
                //fcamerax += 16 * (1.0 / 60.0);
                // fcamerax = radius * Math.Cos(Math.PI * (frameid - (60 * 30 / 2f)) / (60 * 30 / 2f));

                // speed? S6 slow motion?
                // this is really slow. if we do x4x2 =x8 
                // https://www.youtube.com/watch?v=r76ULW16Ib8
                //fcamerax += 16 * (1.0 / 60.0);

                // some shaders need to know where the camera is looking from. can we tell them?

                //fcamerax = 2.2 * Math.Sin(Math.PI * (frameIDslider.valueAsNumber - (60 * 30 / 2f)) / (60 * 30 / 2f));
                //fcameraz = 4.4 * Math.Cos(Math.PI * (frameIDslider.valueAsNumber - (60 * 30 / 2f)) / (60 * 30 / 2f));


                //// up
                //fcameray = 4.4 * Math.Cos(Math.PI * (frameIDslider.valueAsNumber - (60 * 30 / 2f)) / (60 * 30 / 2f));

                // cameraz.valueAsNumber = (int)(cameraz.max * Math.Sin(Math.PI * (frameid - (60 * 30 / 2f)) / (60 * 30 / 2f)));


                // up
                //fcameray = 128 * Math.Cos(Math.PI * (frameid - (60 * 30 / 2f)) / (60 * 30 / 2f));

                //fcamerax += (1.0 / 60.0);

                //fcamerax += (1.0 / 60.0) * 120;



                // 60hz 30sec
                if (frameIDslider.valueAsNumber < maxframes)
                {
                    // Blob GC? either this helms or the that we made a Blob static. 
                    await Task.Delay(11);

                    goto await_nextframe;
                }

                total.Stop();
                status = "all done " + new { frameid = frameIDslider.valueAsNumber, total.ElapsedMilliseconds };
                vsync = default(TaskCompletionSource<object>);
                // http://stackoverflow.com/questions/22899333/delete-javascript-blobs

                e.Element.disabled = false;
            };
            #endregion



            new { }.With(
                async delegate
                {

                    var tex1 = new the_midnight_sun_by_isilmetriel { };

                    await tex1.async.oncomplete;

                    // first one is 124, while others is 123?
                    var tex1w = 123;
                    //var tex1w = 120;
                    var tex1h = 626;

                    //canvasPXitem.drawImage(
                    //           tex1, 2, 2, tex1w, tex1h, 0, 0, tex1w, tex1h
                    //       );


                    // how long until jsc can upstream small updates to code?



                    //// canvasPXitem.drawImage(
                    ////     (IHTMLCanvas)renderer0.domElement,



                    ////    sx: (cubefacesize - cubefacesize / 6) / 2,
                    ////    sy: (cubefacesize - cubefacesize / 3) / 2,

                    ////    sw: cubefacesize / 6,
                    ////    sh: cubefacesize / 3,

                    ////    dx: (cubefacesize - cubefacesize / 6) / 2,
                    ////    dy: (cubefacesize - cubefacesize / 3) / 2,

                    ////    dw: cubefacesize / 6,
                    ////    dh: cubefacesize / 3
                    ////);





                    await iskybox2.async.oncomplete;

                    var bytes1 = await iskybox1.async.bytes;

                    //for (int ii = 0; ii < bytes.Length; ii += 4)
                    //{

                    //    bytes[ii + 3] = (byte)(bytes[ii + 0]);

                    //    bytes[ii + 0] = 0xff;
                    //    bytes[ii + 1] = 0xff;
                    //    bytes[ii + 2] = 0xff;
                    //}

                    var cc = new CanvasRenderingContext2D(iskybox1.width, iskybox1.height);

                    cc.bytes = bytes1;

                    //s.image = cc;
                    //s.needsUpdate = true;

                    var skybox1_material = new THREE.MeshBasicMaterial(
                            new
                            {
                                //map = THREE.ImageUtils.loadTexture(new galaxy_starfield().src),
                                map = new THREE.Texture { image = cc, needsUpdate = true },
                                side = THREE.BackSide,
                                transparent = true
                            });


                    var skybox1 = new THREE.Mesh(
                        //new THREE.SphereGeometry(far * 0.92, 64, 64),
                        //new THREE.SphereGeometry(far * 0.80, 64, 64),

                            // still zfighting
                        //new THREE.SphereGeometry(far * 0.50, 64, 64),

                            // the other option is to have a single bg and blend on tht. this is just a rotation visualization.
                            new THREE.SphereGeometry(far * 0.30, 64, 64),
                           skybox1_material
                        );

                    // http://stackoverflow.com/questions/8502150/three-js-how-can-i-dynamically-change-objects-opacity
                    //(stars_material as dynamic).opacity = 0.5;


                    hideskybox1.onchange += delegate
                    {
                        skybox1.visible = !hideskybox1.@checked;
                    };
                    skybox1.visible = !hideskybox1.@checked;


                    scene.add(skybox1);




                    applycameraoffset += delegate
                    {
                        if (frameIDanimation.@checked)
                        {
                            itemRotation.valueAsNumber = (frameIDslider.valueAsNumber / 2) % 360 - 180;

                            hideskybox1.@checked = (frameIDslider.valueAsNumber / 2 + 180) % 720 < 360;
                        }
                    };


                    // target bg
                    var skybox2 = new THREE.Mesh(
                            new THREE.SphereGeometry(far * 0.95, 64, 64),
                           new THREE.MeshBasicMaterial(
                            new
                            {
                                map = new THREE.Texture { image = iskybox2, needsUpdate = true },
                                side = THREE.BackSide,
                                transparent = true
                            })
                    );


                    skybox2.AttachTo(scene).With(
                        stars =>
                        {
                            applycameraoffset += delegate
                              {

                                  skybox2.visible = !hideskybox2.@checked;



                                  skybox1.rotation.set(0, 0, 0);
                                  // spin
                                  skybox1.rotateOnAxis(new THREE.Vector3(0, -1, 0),
                                     frameIDslider.valueAsNumber / (60 * 60 / 5.0) * Math.PI * 2
                                 );

                                  // reset
                                  stars.rotation.set(0, 0, 0);

                                  // slow rotate in place
                                  stars.rotateOnAxis(new THREE.Vector3(1, 0, 0),
                                      frameIDslider.valueAsNumber / 3600.0 * Math.PI * 2
                                  );

                                  // follow the moon?
                                  stars.rotateOnAxis(new THREE.Vector3(0, -1, 0),
                                      frameIDslider.valueAsNumber / (60 * 60 / 5.0) * Math.PI * 2
                                  );
                              };
                        }

                    );

                    // can we get our stereo sprite this way?
                    // do we get clean tiles with transparency?
                    // on x83 on frame0 we were able to hide skybox. how?
                    //hideskybox2.onchange += delegate
                    //{
                    //    skybox2.visible = !hideskybox2.@checked;
                    //};
                    //skybox2.visible = !hideskybox2.@checked;



                    Console.WriteLine("skybox added");






                    //dae.position.y = -80;

                    //dae.AttachTo(sceneg);
                    //scene.add(dae);
                    //oo.Add(dae);




                    // view-source:http://threejs.org/examples/webgl_multiple_canvases_circle.html
                    // https://threejsdoc.appspot.com/doc/three.js/src.source/extras/cameras/CubeCamera.js.html
                    Native.window.onframe +=
                        e =>
                        {
                            // let render man know..
                            if (vsync != null)
                                if (vsync.Task.IsCompleted)
                                    return;


                            //if (pause) return;
                            //if (pause.@checked)
                            //    return;


                            // can we float out of frame?
                            // haha. a bit too flickery.
                            //dae.position.x = Math.Sin(e.delay.ElapsedMilliseconds * 0.01) * 50.0;
                            //dae.position.x = Math.Sin(e.delay.ElapsedMilliseconds * 0.001) * 190.0;
                            //globesphere.position.y = Math.Sin(fcamerax * 0.001) * 90.0;
                            //clouds.position.y = Math.Cos(fcamerax * 0.001) * 90.0;

                            //sphere.rotation.y += speed;
                            //clouds.rotation.y += speed;

                            // manual rebuild?
                            // red compiler notifies laptop chrome of pending update
                            // app reloads

                            applycameraoffset();
                            renderer0.clear();





                            // spriteOffset
                            canvasPXitem.drawImage(
                                       tex1,

                                       //2px black border!
                                //((tex1w + 4) * spriteOffset.valueAsNumber) + 2,
                                       ((tex1w + 2) * spriteOffset.valueAsNumber) + 3,

                                       2, tex1w, tex1h,

                                       // dest
                                       (cubefacesize - tex1w) / 2,
                                       (cubefacesize - tex1h) / 2,

                                       tex1w, tex1h
                                   );



                            //rendererPY.clear();

                            //cameraPX.aspect = canvasPX.aspect;
                            //cameraPX.updateProjectionMatrix();

                            // um what does this do?
                            //cameraPX.position.z += (z - cameraPX.position.z) * e.delay.ElapsedMilliseconds / 200.0;
                            // mousewheel allos the camera to move closer
                            // once we see the frame in vr, can we udp sync vr tracking back to laptop?


                            //this.targetPX.x += 1;
                            //this.targetNX.x -= 1;

                            //this.targetPY.y += 1;
                            //this.targetNY.y -= 1;

                            //this.targetPZ.z += 1;
                            //this.targetNZ.z -= 1;

                            // how does the 360 or shadertoy want our cubemaps?


                            // and then rotate right?

                            // how can we render cubemap?


                            // hide everything else


                            // inversion effect?
                            //// if (hideskybox1.@checked)
                            ////     skybox1.visible = true;
                            //// else
                            ////     skybox1.visible = false;

                            //// floor2.visible = false;
                            //// renderer0.render(scene, cameraPX);
                            //// //canvasPXitem.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);


                            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151203
                            // can we draw from that special image?


                            //canvasPXitem.drawImage(
                            //    tex1, 2, 2, 124, 630 - 4, 0, 0, 124, 626
                            //);

                            //// canvasPXitem.drawImage(
                            ////     (IHTMLCanvas)renderer0.domElement,



                            ////    sx: (cubefacesize - cubefacesize / 6) / 2,
                            ////    sy: (cubefacesize - cubefacesize / 3) / 2,

                            ////    sw: cubefacesize / 6,
                            ////    sh: cubefacesize / 3,

                            ////    dx: (cubefacesize - cubefacesize / 6) / 2,
                            ////    dy: (cubefacesize - cubefacesize / 3) / 2,

                            ////    dw: cubefacesize / 6,
                            ////    dh: cubefacesize / 3
                            ////);


                            //// skybox1.visible = !hideskybox1.@checked;
                            //// floor2.visible = true;


                            #region x
                            canvasPX.clearRect(0, 0, cubefacesize, cubefacesize);
                            // upside down?
                            renderer0.render(scene, cameraPX);
                            canvasPX.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);

                            canvasNX.clearRect(0, 0, cubefacesize, cubefacesize);
                            renderer0.render(scene, cameraNX);
                            canvasNX.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                            #endregion

                            #region z

                            canvasPZ.clearRect(0, 0, cubefacesize, cubefacesize);
                            renderer0.render(scene, cameraPZ);
                            canvasPZ.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);

                            canvasNZ.clearRect(0, 0, cubefacesize, cubefacesize);
                            renderer0.render(scene, cameraNZ);
                            canvasNZ.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                            #endregion



                            #region y
                            canvasPY.clearRect(0, 0, cubefacesize, cubefacesize);
                            renderer0.render(scene, cameraPY);

                            //canvasPY.save();
                            //canvasPY.translate(0, size);
                            //canvasPY.rotate((float)(-Math.PI / 2));
                            canvasPY.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                            //canvasPY.restore();


                            canvasNY.clearRect(0, 0, cubefacesize, cubefacesize);
                            renderer0.render(scene, cameraNY);
                            //canvasNY.save();
                            //canvasNY.translate(size, 0);
                            //canvasNY.rotate((float)(Math.PI / 2));
                            canvasNY.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                            //canvasNY.restore();
                            // ?
                            #endregion


                            //renderer0.render(scene, cameraPX);


                            //rendererPY.render(scene, cameraPY);

                            // at this point we should be able to render the sphere texture

                            //public const uint TEXTURE_CUBE_MAP_POSITIVE_X = 34069;
                            //public const uint TEXTURE_CUBE_MAP_NEGATIVE_X = 34070;
                            //public const uint TEXTURE_CUBE_MAP_POSITIVE_Y = 34071;
                            //public const uint TEXTURE_CUBE_MAP_NEGATIVE_Y = 34072;
                            //public const uint TEXTURE_CUBE_MAP_POSITIVE_Z = 34073;
                            //public const uint TEXTURE_CUBE_MAP_NEGATIVE_Z = 34074;


                            //var cube0 = new IHTMLImage[] {
                            //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_px(),
                            //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_nx(),

                            //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_py(),
                            //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_ny(),


                            //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_pz(),
                            //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_nz()
                            //};

                            new[] {
                                   canvasPX, canvasNX,
                                   canvasPY, canvasNY,
                                   canvasPZ, canvasNZ
                            }.WithEachIndex(
                             (img, index) =>
                             {
                                 gl.bindTexture(gl.TEXTURE_CUBE_MAP, pass.tex);

                                 //gl.pixelStorei(gl.UNPACK_FLIP_X_WEBGL, false);
                                 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);

                                 // http://stackoverflow.com/questions/15364517/pixelstoreigl-unpack-flip-y-webgl-true

                                 // https://msdn.microsoft.com/en-us/library/dn302429(v=vs.85).aspx
                                 //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
                                 //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);

                                 gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + (uint)index, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img.canvas);

                             }
                          );


                            //if (cameraz.valueAsNumber == 0)
                            gl.clearColor(0, 0, 0, 0);
                            //else
                            //gl4K.clearColor(0, 0, 0, 1);

                            gl.clear(gl.COLOR_BUFFER_BIT);


                            // could do dynamic resolution- fog of war or fog of FOV. where up to 150deg field of vision is encouragedm, not 360
                            pass.Paint_Image(
                               0,

                               0,
                               0,
                               0,
                               0
                                //,

                          // gl_FragCoord
                                // cannot be scaled, and can be referenced directly.
                                // need another way to scale
                                //zoom: 0.3f
                          );

                            //paintsw.Stop();


                            // what does it do?
                            gl.flush();

                            // let render man know..
                            if (vsync != null)
                                if (!vsync.Task.IsCompleted)
                                    vsync.SetResult(null);
                        };





                    Console.WriteLine("do you see it?");

                }
           );




        }
        public Application(IApp page)
        {
            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151101

            // first lets do some chrome extension magic.

            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;



            #region self_chrome_tabs extension
            object self_chrome_tabs = self_chrome.tabs;
            if (self_chrome_tabs != null)
            {
                Console.WriteLine("running as extension " + new { typeof(Application).Assembly.GetName().Name });
                //  verified.
                // running as extension {{ Name = ChromeHybridCaptureAE.Application }}

                new { }.With(
                     async delegate
                     {
                         app = (await chrome.management.getAll()).FirstOrDefault(item => item.name.StartsWith(typeof(Application).Assembly.GetName().Name));

                         if (app == null)
                         {
                             Console.WriteLine("running as extension. app not found.");
                             return;
                         }

                         // running as extension {{ shortName = ChromeHybridCaptureAE.Application.exe, launchType = OPEN_AS_WINDOW }}
                         Console.WriteLine("running as extension " + new { app.shortName, app.launchType });

                         chrome.runtime.connect(app.id).With(
                            async (chrome.Port port) =>
                            {
                                //Console.WriteLine("extension chrome.runtime.connect done " + new { port.name, port.sender.id });
                                //Console.WriteLine("extension chrome.runtime.connect done " + new { port.name, port.sender });
                                Console.WriteLine("extension chrome.runtime.connect done, click launch");



                                #region extension: HopToChromeApp.VirtualOnCompleted
                                // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeapp
                                HopToChromeApp.VirtualOnCompleted = async (that, continuation) =>
                                {
                                    // state 0 ? or state -1 ?
                                    Console.WriteLine("extension HopToChromeApp enter ");

                                    TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableContinuation r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation);

                                    // now send the jump instruction... will it make it?
                                    port.postMessage(r.shadowstate);
                                };
                                #endregion



                                // is async better than event += here?
                                var m = default(chrome.PortMessageEvent);
                                while (m = await port.async.onmessage)
                                {
                                    var message = m.data;

                                    // verified.

                                    #region IAsyncStateMachine
                                    // casting from anonymous object.
                                    var xShadowIAsyncStateMachine = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)message;

                                    // 12961ms extension  port.onMessage {{ state = null, TypeName = null }}
                                    // or constructor id?
                                    Console.WriteLine("extension  port.onMessage " + new { xShadowIAsyncStateMachine.state, xShadowIAsyncStateMachine.TypeName });


                                    // 12468ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }}, expando_isstring = true, is_string = false, equals_typeofstring = false }}
                                    //2015-08-22 15:49:45.729 view-source:53670 12471ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }} }}
                                    //2015-08-22 15:49:45.733 view-source:53670 12475ms extension  port.onMessage {{ message = [object Object], expando_isstring = false, is_string = false, equals_typeofstring = false }}
                                    //2015-08-22 15:49:45.737 view-source:53670 12479ms extension  port.onMessage {{ state = 0, TypeName = <Namespace>.___ctor_b__4_9_d }}


                                    #region xAsyncStateMachineType
                                    var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
                                        xAsyncStateMachineTypeCandidate =>
                                        {
                                            // safety check 1

                                            //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

                                            var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(xAsyncStateMachineTypeCandidate);
                                            if (xisIAsyncStateMachine)
                                            {
                                                //Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

                                                return xAsyncStateMachineTypeCandidate.FullName == xShadowIAsyncStateMachine.TypeName;
                                            }

                                            return false;
                                        }
                                    );
                                    #endregion

                                    Console.WriteLine(new { xAsyncStateMachineType });

                                    var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
                                    var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

                                    var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

                                    #region 1__state
                                    xAsyncStateMachineType.GetFields(
                                        System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
                                        ).WithEach(
                                        AsyncStateMachineSourceField =>
                                        {

                                            //Console.WriteLine(new { AsyncStateMachineSourceField });

                                            if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
                                            {
                                                AsyncStateMachineSourceField.SetValue(
                                                    NewStateMachineI,
                                                    xShadowIAsyncStateMachine.state
                                                );
                                            }

                                            var xStringField = TestSwitchToServiceContextAsync.ArrayListExtensions.AsEnumerable(xShadowIAsyncStateMachine.StringFields).FirstOrDefault(
                                               f => DecoratedString(f.FieldName) == DecoratedString(AsyncStateMachineSourceField.Name)
                                           );

                                            if (xStringField != null)
                                            {
                                                // once we are to go back to client. we need to reverse it?

                                                AsyncStateMachineSourceField.SetValue(
                                                    NewStateMachineI,
                                                    xStringField.value
                                                 );
                                                // next xml?
                                                // before lets send our strings back with the new state!
                                                // what about exceptions?
                                            }
                                        }
                                    );
                                    #endregion

                                    NewStateMachineI.MoveNext();
                                    #endregion

                                }
                            }
                          );
                     }
                );

                return;
            }
            #endregion

            object self_chrome_socket = self_chrome.socket;
            if (self_chrome_socket != null)
            {
                #region running as appwindow
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("running as appwindow");


                    MessagePort appwindow_to_app2 = null;

                    // called by? 619  app:HopToChromeAppWindow
                    #region  appwindow Native.window.onmessage
                    Native.window.onmessage += e =>
                    {
                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow

                        // appwindow Native.window.onmessage {{ data = app to appwindow! }}

                        var message = e.data;

                        //Console.WriteLine("appwindow Native.window.onmessage " + new { e.data });


                        // extension  port.onMessage {{ message = from app hello to extension }}
                        //var expando_isstring = ScriptCoreLib.JavaScript.Runtime.Expando.Of(message).IsString;

                        // look app sent a message to extension
                        //Console.WriteLine("app  port.onMessage " + new { message });

                        {
                            // DataCloneError: Failed to execute 'postMessage' on 'Window': Port at index 0 is already neutered.

                            if (e.ports != null)
                                foreach (var port in e.ports)
                                {
                                    Console.WriteLine("appwindow    Native.window.onmessage " + new { port });

                                    appwindow_to_app2 = port;
                                }

                        }

                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeapp




                        // casting from anonymous object.
                        var xShadowIAsyncStateMachine = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)message;

                        // or constructor id?
                        Console.WriteLine("appwindow     Native.window.onmessage " + new { xShadowIAsyncStateMachine.state, xShadowIAsyncStateMachine.TypeName });

                        // 12468ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }}, expando_isstring = true, is_string = false, equals_typeofstring = false }}
                        //2015-08-22 15:49:45.729 view-source:53670 12471ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }} }}
                        //2015-08-22 15:49:45.733 view-source:53670 12475ms extension  port.onMessage {{ message = [object Object], expando_isstring = false, is_string = false, equals_typeofstring = false }}
                        //2015-08-22 15:49:45.737 view-source:53670 12479ms extension  port.onMessage {{ state = 0, TypeName = <Namespace>.___ctor_b__4_9_d }}


                        #region xAsyncStateMachineType
                        var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
                            xAsyncStateMachineTypeCandidate =>
                            {
                                // safety check 1

                                //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

                                var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(xAsyncStateMachineTypeCandidate);
                                if (xisIAsyncStateMachine)
                                {
                                    //Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

                                    return xAsyncStateMachineTypeCandidate.FullName == xShadowIAsyncStateMachine.TypeName;
                                }

                                return false;
                            }
                        );
                        #endregion


                        var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
                        var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

                        var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

                        #region 1__state
                        xAsyncStateMachineType.GetFields(
                          System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
                          ).WithEach(
                           AsyncStateMachineSourceField =>
                           {

                               //Console.WriteLine(new { AsyncStateMachineSourceField });

                               if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
                               {
                                   AsyncStateMachineSourceField.SetValue(
                                       NewStateMachineI,
                                       xShadowIAsyncStateMachine.state
                                    );
                               }

                               // X:\jsc.svn\examples\javascript\async\Test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\CLRWebServiceInvoke.cs
                               // field names/ tokens need to be encrypted like typeinfo.

                               // some do manual restore
                               // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenIFrame\ChromeExtensionHopToTabThenIFrame\Application.cs
                               // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                               // or, are we supposed to initialize a string value here?

                               var xStringField = TestSwitchToServiceContextAsync.ArrayListExtensions.AsEnumerable(xShadowIAsyncStateMachine.StringFields).FirstOrDefault(
                                   f => DecoratedString(f.FieldName) == DecoratedString(AsyncStateMachineSourceField.Name)
                               );

                               if (xStringField != null)
                               {
                                   // once we are to go back to client. we need to reverse it?

                                   AsyncStateMachineSourceField.SetValue(
                                       NewStateMachineI,
                                       xStringField.value
                                    );
                                   // next xml?
                                   // before lets send our strings back with the new state!
                                   // what about exceptions?
                               }
                           }
                      );
                        #endregion

                        NewStateMachineI.MoveNext();

                    };
                    #endregion


                    #region appwindow:HopToChromeApp
                    HopToChromeApp.VirtualOnCompleted = async (that, continuation) =>
                    {
                        // do we have the port to send back our portal warp?

                        // state 0 ? or state -1 ?
                        Console.WriteLine("appwindow HopToChromeApp  enter " + new { appwindow_to_app2 });
                        // appwindow HopToChromeApp  enter {{ appwindow_to_app2 = null }}

                        //// https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                        //// async dont like ref?
                        TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableContinuation r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation);
                        // 29035ms extension  port.onMessage {{ message = do HopToChromeExtension }}
                        //appwindow_to_app.postMessage("do HopToChromeAppWindow " + new { r.shadowstate.TypeName, r.shadowstate.state });
                        // now send the jump instruction... will it make it?
                        appwindow_to_app2.postMessage(r.shadowstate);
                    };
                    #endregion

                    return;
                }
                #endregion


                // running as app {{ Name = ChromeHybridCaptureAE.Application }} now reenable extension..
                Console.WriteLine("running as app " + new { typeof(Application).Assembly.GetName().Name } + " now reenable extension..");



                #region app:appwindow_to_app
                Action<object> appwindow_to_app = data =>
                {
                    var xShadowIAsyncStateMachine = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)data;

                    Console.WriteLine("app appwindow_to_app " + new { xShadowIAsyncStateMachine.TypeName });

                    #region xAsyncStateMachineType
                    var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
                        xAsyncStateMachineTypeCandidate =>
                        {
                            // safety check 1

                            //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

                            var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(xAsyncStateMachineTypeCandidate);
                            if (xisIAsyncStateMachine)
                            {
                                //Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

                                return xAsyncStateMachineTypeCandidate.FullName == xShadowIAsyncStateMachine.TypeName;
                            }

                            return false;
                        }
                    );
                    #endregion

                    Console.WriteLine("app appwindow_to_app " + new { xAsyncStateMachineType });

                    var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
                    var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

                    var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

                    #region 1__state
                    xAsyncStateMachineType.GetFields(
                      System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
                      ).WithEach(
                       AsyncStateMachineSourceField =>
                       {

                           //Console.WriteLine(new { AsyncStateMachineSourceField });

                           if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
                           {
                               AsyncStateMachineSourceField.SetValue(
                                   NewStateMachineI,
                                   xShadowIAsyncStateMachine.state
                                );
                           }

                           // X:\jsc.svn\examples\javascript\async\Test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\CLRWebServiceInvoke.cs
                           // field names/ tokens need to be encrypted like typeinfo.

                           // some do manual restore
                           // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenIFrame\ChromeExtensionHopToTabThenIFrame\Application.cs
                           // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                           // or, are we supposed to initialize a string value here?

                           var xStringField = TestSwitchToServiceContextAsync.ArrayListExtensions.AsEnumerable(xShadowIAsyncStateMachine.StringFields).FirstOrDefault(
                               f => DecoratedString(f.FieldName) == DecoratedString(AsyncStateMachineSourceField.Name)
                           );

                           if (xStringField != null)
                           {
                               // once we are to go back to client. we need to reverse it?

                               AsyncStateMachineSourceField.SetValue(
                                   NewStateMachineI,
                                   xStringField.value
                                );
                               // next xml?
                               // before lets send our strings back with the new state!
                               // what about exceptions?
                           }
                       }
                  );
                    #endregion

                    NewStateMachineI.MoveNext();
                };
                #endregion

                var c = new MessageChannel();
                var cneutered = c;
                c.port1.onmessage += e =>
                {
                    Console.WriteLine("app HopToChromeAppWindow MessageChannel onmessage " + new { e.data });

                    appwindow_to_app(e.data);
                };

                c.port1.start();
                c.port2.start();

                #region app:HopToChromeAppWindow
                HopToChromeAppWindow.VirtualOnCompleted = async (that, continuation) =>
                {
                    // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150824/webgliframebuffer

                    // state 0 ? or state -1 ?
                    Console.WriteLine("app HopToChromeAppWindow  enter ");

                    #region outputWindow
                    if (that.window == null)
                    {
                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow


                        if (outputWindow == null)
                        {
                            // https://developer.chrome.com/apps/app_window#type-CreateWindowOptions
                            outputWindow = await chrome.app.window.create(
                                                   Native.document.location.pathname,

                                                   // https://developer.chrome.com/apps/app_window#type-CreateWindowOptions
                                                   // this ctually works. but we wont see console on app log..
                                                   options: new { hidden = true, alwaysOnTop = true }
                                            );

                            ////xappwindow.setAlwaysOnTop

                            // or can we stay hidden?
                            //that.window.show();

                            await outputWindow.contentWindow.async.onload;
                        }
                        // reuse the window...
                        that.window = outputWindow;
                    }
                    #endregion


                    // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                    // async dont like ref?
                    TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableContinuation r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation);
                    // 29035ms extension  port.onMessage {{ message = do HopToChromeExtension }}



                    // Z:\jsc.svn\core\ScriptCoreLib\JavaScript\DOM\IWindow.postMessage.cs
                    // how do we use this thing?



                    //                    15ms appwindow    Native.window.onmessage: {{ ports = [object MessagePort] }}
                    //2015-08-22 20:50:18.019 view-source:53702 17ms appwindow    Native.window.onmessage: {{ port = [object MessagePort] }}
                    //that.window.contentWindow.postMessage("do HopToChromeAppWindow " + new { r.shadowstate.TypeName, r.shadowstate.state }, transfer: c.port2);

                    // now send the jump instruction... will it make it?
                    if (cneutered != null)
                    {
                        that.window.contentWindow.postMessage(r.shadowstate, transfer: cneutered.port2);
                        cneutered = null;
                    }
                    else
                    {
                        that.window.contentWindow.postMessage(r.shadowstate);

                    }
                };
                #endregion

                #region ConnectExternal
                chrome.runtime.ConnectExternal += async port =>
                {
                    // app chrome.runtime.ConnectExternal {{ id = jadmeogmbokffpkdfeiemjplohfgkidd }} now click launch!
                    Console.WriteLine("app chrome.runtime.ConnectExternal " + new { port.sender.id } + " now click launch!");

                    new chrome.Notification(
                        title: typeof(Application).Assembly.GetName().Name,
                        message: "ready. click launch"
                    ).Clicked += delegate
                    {
                        // https://developer.chrome.com/apps/app_runtime

                        // management_api
                    };

                    // can we have async thing here?


                    #region HopToChromeExtension
                    HopToChromeExtension.VirtualOnCompleted = async (that, continuation) =>
                    {
                        // state 0 ? or state -1 ?
                        Console.WriteLine("app HopToChromeExtension enter ");

                        // where is it defined?
                        // z:\jsc.svn\examples\javascript\async\Test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\ShadowIAsyncStateMachine.cs

                        // async dont like ref?
                        TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableContinuation r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation);


                        // now send the jump instruction... will it make it?
                        port.postMessage(r.shadowstate);


                        // how would we know to continue from current continuation?
                        // or are we fine to rebuild the scope if we jump back?
                    };
                    #endregion



                    var m = default(chrome.PortMessageEvent);
                    while (m = await port.async.onmessage)
                    {
                        //var m = await port.async.onmessage;

                        var message = m.data;

                        #region IAsyncStateMachine
                        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeapp
                        // casting from anonymous object.
                        var xShadowIAsyncStateMachine = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)message;

                        // or constructor id?
                        Console.WriteLine("app  port.onMessage " + new { xShadowIAsyncStateMachine.state, xShadowIAsyncStateMachine.TypeName });

                        // 12468ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }}, expando_isstring = true, is_string = false, equals_typeofstring = false }}
                        //2015-08-22 15:49:45.729 view-source:53670 12471ms extension  port.onMessage {{ message = do HopToChromeExtension {{ TypeName = <Namespace>.___ctor_b__4_9_d, state = 0 }} }}
                        //2015-08-22 15:49:45.733 view-source:53670 12475ms extension  port.onMessage {{ message = [object Object], expando_isstring = false, is_string = false, equals_typeofstring = false }}
                        //2015-08-22 15:49:45.737 view-source:53670 12479ms extension  port.onMessage {{ state = 0, TypeName = <Namespace>.___ctor_b__4_9_d }}


                        #region xAsyncStateMachineType
                        var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault(
                            xAsyncStateMachineTypeCandidate =>
                            {
                                // safety check 1

                                //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName });

                                var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(xAsyncStateMachineTypeCandidate);
                                if (xisIAsyncStateMachine)
                                {
                                    //Console.WriteLine(new { item.FullName, isIAsyncStateMachine });

                                    return xAsyncStateMachineTypeCandidate.FullName == xShadowIAsyncStateMachine.TypeName;
                                }

                                return false;
                            }
                        );
                        #endregion


                        var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType);
                        var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine;

                        var NewStateMachineI = (IAsyncStateMachine)NewStateMachine;

                        #region 1__state
                        xAsyncStateMachineType.GetFields(
                          System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
                          ).WithEach(
                           AsyncStateMachineSourceField =>
                           {

                               //Console.WriteLine(new { AsyncStateMachineSourceField });

                               if (AsyncStateMachineSourceField.Name.EndsWith("1__state"))
                               {
                                   AsyncStateMachineSourceField.SetValue(
                                       NewStateMachineI,
                                       xShadowIAsyncStateMachine.state
                                    );
                               }


                               // z:\jsc.svn\examples\javascript\async\Test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\CLRWebServiceInvoke.cs
                               // field names/ tokens need to be encrypted like typeinfo.

                               // some do manual restore
                               // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionHopToTabThenIFrame\ChromeExtensionHopToTabThenIFrame\Application.cs
                               // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                               // or, are we supposed to initialize a string value here?

                               var xStringField = TestSwitchToServiceContextAsync.ArrayListExtensions.AsEnumerable(xShadowIAsyncStateMachine.StringFields).FirstOrDefault(
                       f => DecoratedString(f.FieldName) == DecoratedString(AsyncStateMachineSourceField.Name)
                   );

                               if (xStringField != null)
                               {
                                   // once we are to go back to client. we need to reverse it?

                                   AsyncStateMachineSourceField.SetValue(
                           NewStateMachineI,
                           xStringField.value
                        );
                                   // next xml?
                                   // before lets send our strings back with the new state!
                                   // what about exceptions?
                               }
                           }
                      );
                        #endregion

                        NewStateMachineI.MoveNext();
                        #endregion
                    }
                };
                #endregion




                // nuget chrome
                chrome.app.runtime.Launched += async delegate
                {
                    { fixup: await Task.CompletedTask; }



                    Console.WriteLine("app Launched, will hop to extension");
                    // verified.


                    await default(HopToChromeExtension);

                    // https://developer.chrome.com/extensions/management
                    // as an extension we now can inspect our app ?
                    Console.WriteLine("hop from app to extension " + new { app.name });
                    // hop from app to extension {{ name = ChromeHybridCaptureAE.Application.exe }}


                    // what else can we do as an extension?

                    // lets hop back?

                    await default(HopToChromeApp);

                    Console.WriteLine("hop from extension to app ");

                    // ok hopping works. lets do some ui now.
                    //// https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150822/hoptochromeappwindow
                    await default(HopToChromeAppWindow);


                    Native.document.documentElement.style.overflow = IStyle.OverflowEnum.auto;
                    //Native.body.style.overflow = IStyle.OverflowEnum.auto;
                    Native.body.Clear();
                    (Native.body.style as dynamic).webkitUserSelect = "text";

                    chrome.app.window.current().show();

                    // now what?

                    new IHTMLPre { "now what?" }.AttachToDocument();

                    // lets have some ui to do a fullsceen tab capture?
                    // http://earth.nullschool.net/#2015/10/31/1500Z/wind/surface/level/anim=off/overlay=temp/azimuthal_equidistant=24.64,98.15,169
                    // http://earth.nullschool.net/#2015/10/31/2100Z/wind/surface/level/anim=off/overlay=temp/azimuthal_equidistant=24.64,98.15,169

                    // TypeError: Cannot set property 'uri' of null
                    // jsc statemachine hop doesnt like scopes yet. staic it is.
                    uri = new IHTMLInput { value = "http://earth.nullschool.net/#2015/10/31/2100Z/wind/surface/level/anim=off/overlay=temp/azimuthal_equidistant=24.64,98.15,169" }.AttachToDocument();
                    uri.style.width = "100%";

                    Console.WriteLine("appwindow: " + new { uri });

                    new IHTMLPre { () => new { index } }.AttachToDocument();

                    frameID = new IHTMLInput
                    {
                        type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range,
                        min = 0,
                        //max = 3600,
                        max = 240,
                        valueAsNumber = 0
                    }.AttachToDocument().With(
                        async i =>
                        {

                            do
                            {
                                // http://earth.nullschool.net/#2015/10/01/0000Z/wind/surface/level/anim=off/overlay=temp/azimuthal_equidistant=24.64,98.15,169
                                index = (int)i.valueAsNumber;

                                var hh = 3 * index;
                                var dd = 1 + Math.Floor(hh / 24.0);

                                uri.value =
                                    "http://earth.nullschool.net/#2015/10/"
                                    + dd.ToString().PadLeft(2, '0')
                                    + "/"
                                    + (hh % 24).ToString().PadLeft(2, '0')
                                    + "00Z/wind/surface/level/anim=off/overlay=temp/azimuthal_equidistant=24.64,98.15,169";

                            }
                            while (await i.async.onchange);
                        }
                    );

                    go = new IHTMLButton { "go" }.AttachToDocument();

                    Console.WriteLine("appwindow: " + new { go });

                    go.onclick += async delegate
                    {
                        //Error CS0158  The label 'fixup' shadows another label by the same name in a contained scope ChromeHybridCaptureAE   Z:\jsc.svn\examples\javascript\chrome\hybrid\ChromeHybridCaptureAE\Application.cs   791
                        { fixup: await Task.CompletedTask; }

                        Native.body.style.backgroundColor = "yellow";

                        var scope_uri = uri.value;

                        #region  await default(HopToChromeExtension)
                        await default(HopToChromeApp);

                        Console.WriteLine("hop from appwindow to app! " + new { scope_uri });
                        // verify


                        await default(HopToChromeExtension);
                        #endregion


                        Console.WriteLine("hop from app to extension! " + new { scope_uri });

                        //  hop from app to extension! {{ scope_uri = http://earth.nullschool.net/#2015/10/31/2100Z/wind/surface/level/anim=off/overlay=temp/azimuthal_equidistant=24.64,98.15,169 }}

                        var tabwindow = await chrome.windows.create(new { state = "fullscreen", url = scope_uri });

                        // um. unless we hop into it we wont know when its ready?
                        //await Task.Delay(7000);
                        await Task.Delay(5000);

                        // Error: Invalid value for argument 2. Property 'format': Value must be one of: [jpeg, png]. at validate 
                        var captureVisibleTab = await tabwindow.id.captureVisibleTab(options: new { format = "jpeg" });

                        Console.WriteLine("extension captureVisibleTab " + new { captureVisibleTab.Length });

                        await tabwindow.id.remove();


                        #region await default(HopToChromeAppWindow)
                        await default(HopToChromeApp);
                        Console.WriteLine("app " + new { captureVisibleTab.Length });
                        await default(HopToChromeAppWindow);
                        Console.WriteLine("appwindow " + new { captureVisibleTab.Length });
                        #endregion

                        // appwindow {{ Length = 272711 }}

                        var icaptureVisibleTabFull = await new IHTMLImage { src = captureVisibleTab }.async.oncomplete;

                        // {{ width = 1920, height = 1080 }}
                        new IHTMLPre { new { icaptureVisibleTabFull.width, icaptureVisibleTabFull.height } }
                        ;
                        //                        .AttachToDocument();


                        var focus = new CanvasRenderingContext2D(icaptureVisibleTabFull.height, icaptureVisibleTabFull.height);
                        focus.drawImage(icaptureVisibleTabFull, (icaptureVisibleTabFull.width - icaptureVisibleTabFull.height) / 2, 0, icaptureVisibleTabFull.height, icaptureVisibleTabFull.height, 0, 0, icaptureVisibleTabFull.height, icaptureVisibleTabFull.height);
                        var icaptureVisibleTab = new IHTMLImage { src = focus.canvas.toDataURL() }.AttachToDocument();


                        icaptureVisibleTab.style.width = "100%";
                        icaptureVisibleTab.AttachToDocument();

                        await new IHTMLButton { "save " }.AttachToDocument().async.onclick;

                        if (dir == null)
                            dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });

                        var file = index.ToString().PadLeft(5, '0') + ".jpg";

                        await dir.WriteAllBytes(file, focus);

                        //frameID.valueAsNumber++;

                        await new IHTMLButton { "automate " + new { frameID = frameID.valueAsNumber } }.AttachToDocument().async.onclick;

                        //new IHTMLPre { uri.value }.AttachToDocument();

                        next:

                        frameID.valueAsNumber++;
                        await Native.window.async.onframe;
                        await Native.window.async.onframe;

                        //new IHTMLPre { uri.value }.AttachToDocument();

                        // go?

                        // TypeError: Cannot read property 'id' of null
                        scope_uri = uri.value;

                        #region  await default(HopToChromeExtension)
                        await default(HopToChromeApp);

                        Console.WriteLine("hop from appwindow to app! " + new { scope_uri });
                        // verify


                        await default(HopToChromeExtension);
                        #endregion
                        var tabwindow2 = await chrome.windows.create(new { state = "fullscreen", url = scope_uri });
                        await Task.Delay(5000);
                        var captureVisibleTab2 = await tabwindow2.id.captureVisibleTab(options: new { format = "jpeg" });
                        await tabwindow2.id.remove();
                        #region await default(HopToChromeAppWindow)
                        await default(HopToChromeApp);
                        Console.WriteLine("app " + new { captureVisibleTab.Length });
                        await default(HopToChromeAppWindow);
                        Console.WriteLine("appwindow " + new { captureVisibleTab.Length });
                        #endregion
                        var icaptureVisibleTabFull2 = await new IHTMLImage { src = captureVisibleTab2 }.async.oncomplete;
                        var focus2 = new CanvasRenderingContext2D(icaptureVisibleTabFull2.height, icaptureVisibleTabFull2.height);
                        focus2.drawImage(icaptureVisibleTabFull2, (icaptureVisibleTabFull2.width - icaptureVisibleTabFull2.height) / 2, 0, icaptureVisibleTabFull2.height, icaptureVisibleTabFull2.height, 0, 0, icaptureVisibleTabFull2.height, icaptureVisibleTabFull2.height);
                        var icaptureVisibleTab2 = new IHTMLImage { src = focus2.canvas.toDataURL() };
                        var file2 = index.ToString().PadLeft(5, '0') + ".jpg";
                        await dir.WriteAllBytes(file2, focus2);

                        // done?
                        goto next;

                    };


                    await default(HopToChromeApp);

                    Console.WriteLine("hop from appwindow to app!");

                };


                return;
            }

            Console.WriteLine("running as content?");
        }
        public static void ToImage(this string src, Action<IHTMLImage> a)
        {
            var img = new IHTMLImage(src);

            img.InvokeOnComplete(a);
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // what about service worker?

            Native.window.localStorage[new { index = 1 }].With(
                dataURL =>
            {
                var i = new IHTMLImage {
                    src = dataURL
                }.AttachToDocument();


                new IHTMLBreak().AttachToDocument();

                new IHTMLButton("clear localStorage").AttachToDocument().WhenClicked(
                    clear =>
                {
                    Native.window.localStorage.removeItem(new { index = 1 });

                    i.Orphanize();

                    clear.Orphanize();
                }
                    );
            }
                );


            new Preview().AttachToDocument().InvokeOnComplete(
                img =>
            {
                // https://www.ibm.com/developerworks/community/blogs/bobleah/entry/html5_code_example_store_images_using_localstorage57?lang=en
                // http://stackoverflow.com/questions/934012/get-image-data-in-javascript

                //var canvas = new IHTMLCanvas
                //{
                //    width = img.width,
                //    height = img.height
                //};

                //var context = (CanvasRenderingContext2D)canvas.getContext("2d");

                var context = new CanvasRenderingContext2D();

                context.canvas.width  = img.width;
                context.canvas.height = img.height;

                context.drawImage(img, 0, 0, img.width, img.height);

                // http://www.w3schools.com/tags/canvas_filltext.asp
                context.fillStyle = "yellow";
                context.font      = "20px Verdana";
                context.moveTo(0, 0);

                // y means bottom
                context.fillText("cache", 0, 20, img.width);


                context.canvas.AttachToDocument();

                var dataURL = context.canvas.toDataURL();

                // data. ?
                Native.window.localStorage[new { index = 1 }] = dataURL;


                new IHTMLPre {
                    innerText = new { dataURL }.ToString()
                }.AttachToDocument();
            }
                );
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IDefault page)
        {
  

            var n = new MyEditor();

            n.Container.AttachToDocument();

            //var a = new IHTMLAnchor(
            //    "http://sketchup.google.com/3dwarehouse/search?q=stargate",
            //    "Open 3dwarehouse in another window"
            //);
            //a.style.fontSize = "large-xx";
            //a.AttachToDocument();



            //ii.setAttribute("src", "http://sketchup.google.com/3dwarehouse/");


            IHTMLDiv Control = new IHTMLDiv();

            n.Edit1.parentNode.replaceChild(Control, n.Edit1);

            //n.Logo.src = "assets/TextEditorDemo2/Preview.png";

            //Control.AttachToDocument();


            var text = new TextEditor(Control);


            text.InnerHTML = "Drag images to this frame!<hr />";

            // IE error

            text.Height = 200;
            text.Width = 400;
            //text.InnerHTML = n.Edit1.value;

            text.IsFadeEnabled = false;

            //var i = new IHTMLImage(21, 20) { src = "assets/TextEditorDemo2/cal.png" };

            var CurrentList = new List<InternalExtensions.GoogleThreeDWarehouseImage>();

            n.ToLarge.onclick += e =>
            {
                CurrentList.ForEach(k => k.AnimationZoom = 4);
            };

            n.ToMedium.onclick += e =>
            {
                CurrentList.ForEach(k => k.AnimationZoom = 1);
            };
            n.ToSmall.onclick += e =>
            {
                CurrentList.ForEach(k => k.AnimationZoom = 0.5);
            };

            Action<string[], IHTMLButton> ToPreview =
                (data, button) =>
                {
                    var ii = new IHTMLImage(40, 30) { src = data[0] };
                    ii.style.verticalAlign = "middle";

                    var sp = new IHTMLSpan();
                    sp.style.marginLeft = "1em";
                    sp.AttachTo(button);

                    ii.AttachTo(button).ToGoogleThreeDWarehouseImage().Animate();

                };
            n.Nasa.onclick +=
                delegate
                {
                    text.InnerHTML = NasaSource.Text;

                };


            //n.Houses.onclick +=
            //    delegate
            //    {
            //        text.InnerHTML = Pages.Houses.Static.HTML;

            //    };

            n.CnC.onclick +=
                delegate
                {
                    text.InnerHTML = CnCSource.Text;

                };

            n.Ships.onclick +=
            delegate
            {
                text.InnerHTML = ShipsSource.Text;
            };

            //ToPreview(Ships..Images, n.Ships);
            //ToPreview(CnC.Static.Images, n.CnC);
            ////ToPreview(Houses.Static.Images, n.Houses);
            //ToPreview(Nasa.Static.Images, n.Nasa);


            //i.AttachToDocument();
            n.OK.onclick +=
                delegate
                {
                    n.ContainerForImages.removeChildren();
                    CurrentList.Clear();
                    //text.Document.getElementsByTagName("img").ToGoogleThreeDWarehouseImages().Animate();

                    var clones = text.Document.GetClonedImages();
                    foreach (IHTMLImage iii in clones)
                    {


                        var w = iii.AttachTo(n.ContainerForImages).ToGoogleThreeDWarehouseImage();

                        w.Animate();

                        CurrentList.Add(w);
                    }

                };
            //);

            //OK.Control.style.paddingLeft = "1em";
            //text.BottomToolbarContainer.appendChild(OK.Control);

            text.TopToolbarContainer.Hide();
            text.BottomToolbarContainer.Hide();
        }
        public static void InitializeContent()
        {
            #region tutorial step 2
            #region arena
            var map = new Point(2000, 2000);

            var arena = new ArenaControl();

            arena.Layers.Canvas.style.backgroundColor =
                Color.FromGray(0xc0);
            arena.SetLocation(
                Rectangle.Of(0, 0, Native.window.Width, Native.window.Height));

            arena.SetCanvasSize(map);

            arena.Control.AttachToDocument();


            arena.DrawTextToInfo(Title, new Point(8, 8), Color.Blue);

            Native.window.onresize +=
                delegate
                {
                    arena.SetLocation(
                        Rectangle.Of(0, 0, Native.window.Width, Native.window.Height));

                    arena.SetCanvasPosition(
                        arena.CurrentCanvasPosition
                        );
                };
            #endregion
            #endregion


            var pending = default(Dude2);

            #region arsenal
            var arsenal = new Dictionary<string, DudeAnimationInfo>
            {
                {"Soldier", 
                    new DudeAnimationInfo 
                    { 
                        Frames_Stand = Frames.WolfSoldier,
                        Frames_Walk = Frames.WolfSoldier_Walk
                    }
                },
                {"Imp", 
                    new DudeAnimationInfo 
                    { 
                        Frames_Stand = Frames.DoomImp,
                        Frames_Walk = Frames.DoomImp_Walk
                    }
                }
            };
            #endregion


            #region tutorial step 3

            Func<DudeAnimationInfo, Point, Dude2> CreateActor =
                (_frames, _coords) =>
                {
                    var actor = new Dude2();

                    actor.Frames = _frames.Frames_Stand;
                    actor.AnimationInfo.Frames_Stand = _frames.Frames_Stand;
                    actor.AnimationInfo.Frames_Walk = _frames.Frames_Walk;
                    actor.Zoom.DynamicZoomFunc = a => 1;
                    actor.SetSize(48, 72);
                    actor.TeleportTo(_coords.X, _coords.Y);
                    actor.Zoom.StaticZoom = DefaultActiorZoom;
                    actor.Direction = Math.PI * 0.5;
                    actor.Control.AttachTo(arena.Layers.Canvas);
                    //actor.HasShadow = _frames.Frames_Stand.Length > 1;
                    if (_frames.Frames_Stand.Length == 1)
                        actor.Shadow.style.Opacity = 0.4;
                    actor.AnimationInfo.WalkAnimationInterval = 1000 / 30;
                    return actor;
                };

            var actors = new List<Dude2>
            {

            };

            var selection = from i in actors
                            where i.IsSelected
                            select i;

            arena.ApplySelection +=
                (rect, ev) =>
                {
                    if (pending != null)
                        return;

                    foreach (var v in actors)
                        v.IsSelected = rect.Contains(v.CurrentLocation.ToInt32());
                };

            var Argh = new Argh();
            var Affirmative = new Affirmative();
            var ghoullaugh = new ghoullaugh();
            var sheep = new sheep();
            var pig = new pig();
            var click = new click().AttachToDocument();

            arena.SelectionClick +=
                (p, ev) =>
                {
                    if (pending != null)
                        return;

                    foreach (var v in selection)
                    {
                        if (v.AnimationInfo.Frames_Stand[0].Source == MyFrames.ManWithHorns.Frames_Stand[0].Source)
                        {
                            ghoullaugh.play();
                            ghoullaugh = new ghoullaugh();
                        }
                        else if (v.AnimationInfo.Frames_Stand[0].Source == MyFrames.ThePig.Frames_Stand[0].Source)
                        {
                            pig.play();
                            pig = new pig();
                        }
                        else if (v.AnimationInfo.Frames_Stand[0].Source == MyFrames.TheSheep.Frames_Stand[0].Source)
                        {
                            sheep.play();
                            sheep = new sheep();
                        }
                        else if (v.AnimationInfo.Frames_Stand[0].Source == Frames.WolfSoldier[0].Source)
                        {
                            Affirmative.play();
                            Affirmative = new Affirmative();
                        }
                        else
                        {
                            Argh.play();
                            Argh = new Argh();
                        }



                        v.WalkTo(p.ToDouble());

                        // move in group formation
                        p.X += 16;
                        p.Y += 16;
                    }
                };


            #endregion

            #region tutorial step 4



            #region CreateDialogAt
            var CreateDialogAt =
                new
                {
                    //Dialog = default(IHTMLDiv),
                    Content = default(IHTMLDiv),
                    Width = default(string)
                }
                .ToFunc(
                (Point pos, string width) =>
                {
                    var f = new Form();

                    f.Show();

                    f.SizeTo(200, 200);


                    // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151115/audio
                    //f.PopupInsteadOfClosing();

                    f.MoveTo(pos.X, pos.Y);
                    //f.SizeTo(


                    //var dialog = new IHTMLDiv();

                    //dialog.style.SetLocation(pos.X, pos.Y);

                    //dialog.style.backgroundColor = Color.Gray;
                    //dialog.style.padding = "1px";

                    //var caption = new IHTMLDiv().AttachTo(dialog);

                    //caption.style.backgroundColor = Color.Blue;
                    //caption.style.width = width;
                    //caption.style.height = "0.5em";
                    //caption.style.cursor = IStyle.CursorEnum.move;

                    //var drag = new DragHelper(caption);

                    //drag.Position = pos;
                    //drag.Enabled = true;
                    //drag.DragMove +=
                    //    delegate
                    //    {
                    //        dialog.style.SetLocation(drag.Position.X, drag.Position.Y);
                    //    };

                    var _content = new IHTMLDiv().AttachTo(f.GetHTMLTargetContainer());

                    _content.style.textAlign = IStyle.TextAlignEnum.center;
                    _content.style.backgroundColor = Color.White;
                    _content.style.padding = "1px";

                    //dialog.AttachToDocument();

                    return new
                    { //Dialog = dialog,
                        Content = _content,
                        Width = width
                    };
                }
            );
            #endregion

            #region dialog
            var toolbar = CreateDialogAt(new Point(2, 2), "8em");

            var combo = new IHTMLSelect();
            var build = new IHTMLButton();

            build.style.SetSize(72, 72);
            build.style.padding = "0px";

            var avatar = new IHTMLImage().AttachTo(build);
            var remove = new IHTMLButton("Remove");


            combo.AttachTo(toolbar.Content);
            new IHTMLBreak().AttachTo(toolbar.Content);
            build.AttachTo(toolbar.Content);
            new IHTMLBreak().AttachTo(toolbar.Content);
            remove.AttachTo(toolbar.Content);
            new IHTMLBreak().AttachTo(toolbar.Content);
            #endregion


            #region GetSelectedArsenal
            Func<DudeAnimationInfo> GetSelectedArsenal =
                () =>
                {
                    if (arsenal.ContainsKey(combo[combo.selectedIndex].value))
                        return arsenal[combo[combo.selectedIndex].value];

                    return null;
                };
            #endregion

            Action Refresh =
                delegate
                {
                    var i = GetSelectedArsenal();

                    if (i != null)
                        avatar.src = i.Images.Random().src;
                };

            combo.Add(arsenal.Keys.ToArray());
            Refresh();

            combo.onchange +=
                delegate
                {
                    Refresh();



                    click.play();
                    click = new click().AttachToDocument();
                };

            #region pending actor

            arena.MouseMove +=
                p =>
                {
                    if (pending == null)
                        return;

                    pending.TeleportTo(p.X, p.Y);
                };

            arena.Layers.User.oncontextmenu +=
                e =>
                {
                    e.preventDefault();

                    if (pending != null)
                    {
                        pending.Control.Orphanize();
                        pending = null;
                        arena.ShowSelectionRectangle = true;

                        return;
                    }

                    actors.ForEach(
                        k => k.IsSelected = false
                            );
                };

            arena.SelectionClick +=
                (p, ev) =>
                {
                    if (pending == null)
                    {

                        return;
                    }

                    pending.TeleportTo(p.X, p.Y);

                    actors.Add(pending);

                    pending.IsHot = false;


                    var x = GetSelectedArsenal();
                    pending = CreateActor(x,
                       new Point(
                           Native.window.Width / 2,
                           Native.window.Height / 2
                           )
                   );

                    pending.IsHot = true;


                    click.play();
                    click = new click().AttachToDocument();
                };

            build.onclick +=
                delegate
                {
                    if (pending != null)
                    {
                        pending.Control.Orphanize();
                        pending = null;

                        return;
                    }

                    var x = GetSelectedArsenal();

                    pending = CreateActor(x,
                        new Point(
                            Native.window.Width / 2,
                            Native.window.Height / 2
                            )
                    );

                    pending.IsHot = true;
                    arena.ShowSelectionRectangle = false;

                    click.play();
                    click = new click().AttachToDocument();
                };
            #endregion

            remove.onclick +=
                delegate
                {
                    foreach (var v in selection.ToArray())
                    {
                        v.Control.Orphanize();
                        actors.Remove(v);
                    }


                    click.play();
                    click = new click().AttachToDocument();
                };

            #endregion

            if (FilterToImpAndSoldier)
            { }
            else
            {
                #region step 6

                {
                    var n = "NPC";

                    arsenal.Add(n, MyFrames.NPC3);
                    combo.Add(n);
                }

                #endregion


                {
                    var n = "ManWithHorns";

                    arsenal.Add(n, MyFrames.ManWithHorns);
                    combo.Add(n);
                }
                {
                    var n = "TheSheep";

                    arsenal.Add(n, MyFrames.TheSheep);
                    combo.Add(n);
                }
                {
                    var n = "ThePig";

                    arsenal.Add(n, MyFrames.ThePig);
                    combo.Add(n);
                }

                {
                    var n = "TheCactus";

                    arsenal.Add(n, MyFrames.TheCactus);
                    combo.Add(n);
                }
            }


            if (BeforeAddingDebris != null)
                BeforeAddingDebris(arena.Layers.Canvas);

            3.Times(
              delegate()
              {
                  new DebrisImages().Images.ForEach(
                      img => img.AttachTo(arena.Layers.Canvas).style.SetLocation(map.X.Random(), map.Y.Random())
                  );
              }
      );

            16.Times(
                delegate()
                {
                    actors.Add(
                        CreateActor(arsenal.Random().Value, new Point(map.X.Random(), map.Y.Random()))
                        );
                }
            );
        }
            public ScoreBoard(ImageResources gfx)
            {
                Life1 = gfx.biggun.Clone();
                Life2 = gfx.biggun.Clone();
                Life3 = gfx.biggun.Clone();

                score_label.style.color = Color.White;
                lives_label.style.color = Color.White;

                score_value.style.color = Color.Green;

                var left = new IHTMLDiv(score_label, score_value);
                left.style.Float = IStyle.FloatEnum.left;

                lives_value.appendChild(
                    Life1,
                    Life2,
                    Life3
                );

                score_value.style.paddingLeft = "1em";
                Life1.style.paddingLeft = "1em";
                Life2.style.paddingLeft = "1em";
                Life3.style.paddingLeft = "1em";

                var right = new IHTMLDiv(lives_label, lives_value);
                right.style.Float = IStyle.FloatEnum.right;

                Control.style.fontSize = "22px";
                Control.appendChild(left, right);

            }
        // 20140526 roslyn friendly!
        // and broken again

        //        script: error JSC1000:
        //error:
        //  statement cannot be a load instruction(or is it a bug?)
        //  [0x000a]
        //        ldarg.0    +1 -0

        // assembly: V:\Abstractatech.JavaScript.Avatar.Application.exe
        // type: Abstractatech.JavaScript.Avatar.ApplicationImplementation+<MakeCamGrabber>d__1+<MoveNext>0600002d, Abstractatech.JavaScript.Avatar.Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
        // offset: 0x000a
        //  method:Int32<06ad> call.try(<MoveNext>0600002d, <MakeCamGrabber>d__1 ByRef, System.Runtime.CompilerServices.TaskAwaiter`1[ScriptCoreLib.JavaScript.DOM.HTML.IHTMLImage] ByRef, System.Runtime.CompilerServic

        public static async void MakeCamGrabber(
            IHTMLDiv c,
            bool sizeToWindow = false,
            Action<WebCamAvatarsSheet1Row> yield = null
            )
        {
            if (sizeToWindow)
            {
                #region onresize
                Native.window.With(
                    async window =>
                    {
                        while (true)
                        {
                            c.style.transformOrigin = "0% 0%";

                            var scale =

                                Native.window.Height / (double)(480 + 96);

                            if (Native.window.Height > Native.window.Width)
                                scale = Native.window.Width / (double)(640);


                            c.style.transform = "scale("
                                + scale
                                + ")";

                            var w = (int)(scale * (640));
                            var h = (int)(scale * (480 + 96));


                            c.style.width = w + "px";
                            c.style.height = h + "px";

                            c.style.SetLocation(
                                (Native.window.Width - w) / 2,
                                (Native.window.Height - h) / 2
                            );

                            await window.async.onresize;
                        }
                    }
                );
                #endregion

            }

            c.style.backgroundColor = "black";

            #region localStorageKeys

            // or webSQL?
            var localStorageKeys = new
            {

                img640x480 = new { img = "avatar", w = 640, h = 480 },
                img96gif = new { img = "avatar", w = 96, h = 96 },

                frames = new[] {
                            new { index= 0, img = "avatar", w = 96, h = 96 },
                            new { index= 1, img = "avatar", w = 96, h = 96 },
                            new { index= 2, img = "avatar", w = 96, h = 96 },
                            new { index= 3, img = "avatar", w = 96, h = 96 },
                        }
            };
            #endregion



            //c.css.children
            c.css.children.style.SetLocation(0, 0);

            c.style.position = IStyle.PositionEnum.relative;
            c.style.width = (640) + "px";
            c.style.height = (480 + 96) + "px";






            c.css.hover.style.cursor = IStyle.CursorEnum.pointer;

            #region empty
            var css = c.css.empty.before;

            css.style.textAlign = IStyle.TextAlignEnum.center;
            css.style.display = IStyle.DisplayEnum.block;
            css.style.width = (640) + "px";
            css.style.color = "white";
            css.style.paddingTop = 300 + "px";


            c.css.hover.empty.before.style.color = "yellow";
            #endregion




            var retry = 0;
            retry:
            retry++;

            Console.WriteLine(new { retry });


            css.contentText = "either drag a picture here -or- click here to use your webcam";

            var snapshot = new CanvasRenderingContext2D(640, 480);

            var frames = new List<IHTMLImage>();

            c.css[IHTMLElement.HTMLElementEnum.img][0].style.SetLocation(96 * 0, 480);
            c.css[IHTMLElement.HTMLElementEnum.img][1].style.SetLocation(96 * 1, 480);
            c.css[IHTMLElement.HTMLElementEnum.img][2].style.SetLocation(96 * 2, 480);
            c.css[IHTMLElement.HTMLElementEnum.img][3].style.SetLocation(96 * 3, 480);
            c.css[IHTMLElement.HTMLElementEnum.img][4].style.SetLocation(96 * 4, 480);
            c.css[IHTMLElement.HTMLElementEnum.img][5].style.SetLocation(96 * 5, 480);

            var size = 400;

            #region newmask
            Action newmask = delegate
            {
                #region grid
                new IHTMLDiv
                {

                }.AttachTo(c).With(
                    async grid =>
                    {
                        grid.style.SetLocation(
                            (640 - size) / 2,
                            (480 - size) / 2,

                            size - 2,
                            size - 2
                        );

                        var s = Stopwatch.StartNew();

                        // X:\jsc.svn\examples\javascript\LINQ\LINQWebCamAvatars\LINQWebCamAvatars\Application.cs
                        // until orphanized
                        while (c.parentNode != null)
                        {
                            //await Native.window.requestAnimationFrameAsync;
                            await Native.window.async.onframe;

                            var a = (Math.Cos(s.ElapsedMilliseconds * 0.001) + 1) / 2.0;

                            grid.style.border = "1px dotted rgba(255,255,255, "
                                + (1.0 - a)
                                + ")";

                            //mask_css.style.Opacity = a;

                        }
                    }
                );
                #endregion

                #region mask
                var mask = new CanvasRenderingContext2D(640, 480 + 96);

                mask.canvas.style.zIndex = 100;

                //mask.drawImage(
                //    v, 0, 0,

                //    mask.canvas.width,
                //    mask.canvas.height
                //);

                mask.fillStyle = "rgba(0,0,0, 0.8)";
                mask.fillRect(
                       0, 0,

                       640,
                       480 + 96
                   );


                mask.clearRect(
                      (640 - size) / 2,
                        (480 - size) / 2,

                        size,
                        size
                );



                //var bytes = i.bytes;

                mask.canvas.AttachTo(c);
                #endregion


            };
            #endregion


            #region localStorage
            var base64 = Native.window.localStorage[localStorageKeys.img640x480];
            if (base64 != null)
            {
                var base64image = new IHTMLImage { src = base64 };

                await base64image;

                snapshot.drawImage(base64image, 0, 0, 640, 480);
                snapshot.canvas.AttachTo(c);


                for (int i = 0; i < 5; i++)
                {
                    var base64f = Native.window.localStorage[localStorageKeys.frames[
                        localStorageKeys.frames.Length - i - 1]];

                    if (base64f != null)
                    {
                        var newframe = new IHTMLImage { src = base64f };
                        newframe.AttachTo(c);
                        frames.Add(newframe);
                    }
                }



                newmask();

                var base64gif = Native.window.localStorage[localStorageKeys.img96gif];

                #region atgif
                Action<string> atgif =
                    gif =>
                    {
                        //Native.document.title = new { gif.Length }.ToString();

                        var newframe = new IHTMLImage { src = gif };

                        newframe.style.zIndex = 300;

                        newframe.AttachTo(c);
                        frames.Add(newframe);

                        //if (frames.Count > 5)
                        //    frames.Remove(frames[0].Orphanize());
                    };
                #endregion


                if (base64gif != null)
                    atgif(base64gif);
                else
                {
                    var bytes = frames.Select(x => x.bytes.Result).ToArray().AsEnumerable();

                    //bytes = bytes.Concat(bytes.Skip(1).Reverse().Skip(1)).ToArray().AsEnumerable();

                    // build it
                    new GIFEncoderWorker(
                         96,
                         96,
                             delay: 1000 / 10,
                         frames: bytes,
                         AtFrame:
                          async index =>
                          {
                              //Native.document.title = new { index }.ToString();
                          }


                     ).Task.ContinueWithResult(
                        gif =>
                        {
                            Native.window.localStorage[localStorageKeys.img96gif] = gif;


                            // report sizes. smaller is better if db
                            Console.WriteLine(
                                // { Avatar640x480 = 54843, Avatar96gif = 54734 } 
                                new
                                {
                                    Avatar640x480 = base64.Length,
                                    Avatar96gif = gif.Length
                                }
                            );


                            if (yield != null)
                                yield(
                                    new WebCamAvatarsSheet1Row
                                    {
                                        Avatar640x480 = base64,
                                        Avatar96frame1 = Native.window.localStorage[localStorageKeys.frames[0]],
                                        // do we want to report frames?
                                        Avatar96gif = gif
                                    }
                                );


                            atgif(gif);
                        }
                        );
                }

            }
            #endregion

            Console.WriteLine("await c.async.onclick");
            await c.async.onclick;
            Console.WriteLine("await c.async.onclick done");

            c.Clear();

            css.content = "awaiting for video";




            var v = await Native.window.navigator.async.onvideo;


            v.AttachTo(c);
            v.play();


            var mask_css = c.css[IHTMLElement.HTMLElementEnum.canvas];



            newmask();

            var z96 = new CanvasRenderingContext2D(96, 96);

            z96.canvas.AttachTo(c);
            //z96.canvas.style.backgroundColor = "gray";
            z96.canvas.style.SetLocation(96 * 5, 480);

            z96.canvas.style.zIndex = 300;


            var ok = c.async.onclick;

            #region frames



            while (!ok.IsCompleted)
            {

                z96.drawImage(
                    image: v,
                    sx: (640 - size) / 2,
                    sy: (480 - size) / 2,

                    sw: size,
                    sh: size,
                    dx: 0,
                    dy: 0,
                    dw: 96,
                    dh: 96
                );

                var newframe = new IHTMLImage { src = z96.canvas.toDataURL() };
                newframe.AttachTo(c);
                frames.Add(newframe);

                if (frames.Count > 5)
                    frames.Remove(frames[0].Orphanize());


                await (1000 / 15);
            }
            #endregion

            snapshot.drawImage(v, 0, 0, 640, 480);

            #region localStorage

            // https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement
            //Native.window.localStorage[localStorageKeys.img640x480] = 

            var firstTry = snapshot.canvas.toDataURL(

            // shall we use enum
            type: "image/jpeg"
            );
            if (firstTry.Length >= (1024 * 64))
            {
                Console.WriteLine("Reducing quality");
                firstTry = snapshot.canvas.toDataURL(

            // shall we use enum
            type: "image/jpeg",
            quality: 0.5
            );
            }

            // can we use SQL instead now?
            Native.window.localStorage[localStorageKeys.img640x480] = firstTry;



            frames.WithEachIndex(
                (k, index) =>
                {
                    Native.window.localStorage[localStorageKeys.frames[index]] = k.src;
                }
            );

            Native.window.localStorage.removeItem(localStorageKeys.img96gif);
            #endregion


            v.src = "";
            c.Clear();



            goto retry;
        }
            public EnemyUnit(EnemyInfo i)
            {
                Info = i;
                Control = (IHTMLImage)Info.Image.Clone();

                Visible = false;
            }
        public void __Application(IApplicationLoader app)
        {
            //app.LoadingAnimation.FadeOut();

            var DefaultTitle = "jsc solutions";


            Native.Document.title = DefaultTitle;

            StringActionAction GetTitleFromServer = new UltraWebService().GetTitleFromServer;



            GetTitleFromServer(
                n => Native.Document.title = n
            );

            var MyPagesBackground = new IHTMLDiv
            {

            };

            MyPagesBackground.style.overflow = IStyle.OverflowEnum.hidden;
            MyPagesBackground.style.position = IStyle.PositionEnum.absolute;
            MyPagesBackground.style.width = "100%";
            MyPagesBackground.style.height = "100%";
            MyPagesBackground.AttachToDocument();

            var MyPages = new IHTMLDiv
            {

            };

            MyPages.style.overflow = IStyle.OverflowEnum.auto;
            MyPages.style.position = IStyle.PositionEnum.absolute;
            MyPages.style.width = "100%";
            MyPages.style.height = "100%";
            MyPages.AttachToDocument();

            var MyPagesInternal = new IHTMLDiv();

            MyPagesInternal.style.margin = "4em";
            MyPagesInternal.AttachTo(MyPages);

            // http://www.google.com/support/forum/p/Google+Analytics/thread?tid=486a963e463df665&hl=en
            var gapathname = Native.Document.location.pathname;
            var gasearch = Native.Document.location.search;
            var gahash = Native.Window.escape(Native.Document.location.hash);
            var gapageview = gapathname + gasearch + gahash;

            var hash = Native.Document.location.hash;

            Action<string> Analytics = delegate { };

        #region logo
            {
                var IsStudio = Native.Document.location.hash.StartsWith("#/studio");

                if (Native.Document.location.host.StartsWith("studio."))
                {
                    IsStudio = true;
                }

                if (IsStudio)
                {
                    new StudioView(AddSaveButton).Content.AttachToDocument();
                }
                else if (Native.Document.location.hash.StartsWith("#/docs"))
                {
                    var view = new DocumentationCompilationViewer();

                    view.TouchTypeSelected +=
                        type =>
                        {
                            Native.Document.location.hash = "#/docs/" + type.FullName;

                            Analytics("#/docs/" + type.FullName);
                        };

                }
                else if (Native.Document.location.hash.StartsWith("#/warehouse"))
                {
                    new UltraWebService().ThreeDWarehouse(
                        y =>
                        {
                            Func<string, IHTMLAnchor> Build =
                                mid =>
                                {
                                    var a = new IHTMLAnchor { href = "http://sketchup.google.com/3dwarehouse/details?ct=hppm&mid=" + mid }.AttachTo(MyPagesInternal);
                                    var img = new IHTMLImage { src = "http://sketchup.google.com/3dwarehouse/download?rtyp=st&ctyp=other&mid=" + mid }.AttachTo(a);

                                    return a;
                                };

                            var imgs = Enumerable.ToArray(
                                from k in y.Elements()
                                select Build(k.Value)

                            );
                        }
                    );

                }

                else if (Native.Document.location.hash == "#/source")
                {

                    var sln = new TreeNode(() => new VistaTreeNodePage());

                    sln.Text = "Solution";
                    sln.IsExpanded = true;

                    Action<TreeNode> AddReferences =
                        p =>
                        {
                            var r = p.Add("References", new References());

                            r.Add("System", new Assembly());
                            r.Add("System.Core", new Assembly());
                            r.Add("ScriptCoreLib", new Assembly());
                            r.Add("ScriptCoreLib.Ultra", new Assembly());
                            r.Add("ScriptCoreLib.Ultra.Library", new Assembly());
                            r.Add("ScriptCoreLib.Ultra.Controls", new Assembly());
                            r.Add("ScriptCoreLibJava", new Assembly());
                            r.Add("jsc.meta", new Assembly());
                        };

                    Action<TreeNode> AddUltraSource =
                        p =>
                        {
                            var my = p.Add("My.UltraSource");
                            my.Add("Default.htm", new HTMLDocument());
                            my.Add("jsc.png", new ImageFile());

                        };

                    {
                        var p = sln.Add("Visual C# Project", new VisualCSharpProject());


                        AddReferences(p);
                        AddUltraSource(p);



                        p.Add("Application.cs", new VisualCSharpCode());
                        p.Add("WebService.cs", new VisualCSharpCode());
                        p.Add("Program.cs", new VisualCSharpCode());
                    }

                    {
                        var p = sln.Add("Visual Basic Project", new VisualBasicProject());

                        AddReferences(p);
                        AddUltraSource(p);

                        p.Add("Application.vb", new VisualBasicCode());
                        p.Add("WebService.vb", new VisualBasicCode());
                        p.Add("Program.vb", new VisualBasicCode());
                    }


                    {
                        var p = sln.Add("Visual F# Project", new VisualFSharpProject());

                        AddReferences(p);
                        AddUltraSource(p);


                        p.Add("Application.fs", new VisualFSharpCode());
                        p.Add("WebService.fs", new VisualFSharpCode());
                        p.Add("Program.fs", new VisualFSharpCode());
                    }

                    sln.Container.style.Float = IStyle.FloatEnum.right;
                    sln.Container.AttachTo(MyPagesInternal);

                    new SourceEditorHeader().Container.AttachTo(MyPagesInternal);

                    //new IHTMLElement(IHTMLElement.HTMLElementEnum.h1, "Create your own Ultra Application project template").AttachTo(MyPagesInternal);

                    var n = new TextEditor(MyPagesInternal);

                    n.Width = 600;
                    n.Height = 400;

                    //n.InnerHTML = "<p>Create your own <b>Ultra Application</b> Project Template</p>";


                    new DefaultPage1().Container.AttachTo(n.Document.body);

                    var m1 = new SimpleCodeView();

                    m1.Container.AttachTo(MyPagesInternal);
                    //m1.SelectType.onchange +=
                    //    delegate
                    //    {
                    //        m1.TypeName.innerText = m1.SelectType.value;
                    //    };

                    //m1.RunJavaScript.onclick +=
                    //    delegate
                    //    {
                    //        m1.RunJavaScript.style.color = JSColor.Blue;

                    //        try
                    //        {
                    //            Native.Window.eval(m1.Code1.value);

                    //            1000.AtDelay(
                    //                delegate
                    //                {
                    //                    m1.RunJavaScript.style.color = JSColor.None;
                    //                }
                    //            );
                    //        }
                    //        catch
                    //        {
                    //            m1.RunJavaScript.style.color = JSColor.Red;

                    //            1000.AtDelay(
                    //                delegate
                    //                {
                    //                    m1.RunJavaScript.style.color = JSColor.None;
                    //                }
                    //            );
                    //        }
                    //    };
                    new Compilation().GetArchives().SelectMany(k => k.GetAssemblies()).First(k => k.Name == "ScriptCoreLib").WhenReady(
                        ScriptCoreLib =>
                        {
                            // we do not have reflection in place for native wrappers :/

                            m1.SelectEvent.Clear();

                            var Element = ScriptCoreLib.GetTypes().Single(k => k.FullName == "ScriptCoreLib.JavaScript.DOM.HTML.IHTMLElement");
                            //var Element = ScriptCoreLib.GetTypes().Single(k => k.HTMLElement == "ScriptCoreLib.JavaScript.DOM.HTML.IHTMLElement");

                            Action<CompilationEvent> Add =
                                SourceEvent =>
                                {
                                    m1.SelectEvent.Add(
                                        new IHTMLOption { innerText = SourceEvent.Name }
                                    );
                                };

                            Element.GetEvents().ForEach(Add);

                        }
                    );


                    m1.SelectEvent.onchange +=
                        delegate
                        {
                            m1.EventName.innerText = m1.SelectEvent.value;
                        };




                }
                else if (Native.Document.location.hash == "#/UltraApplicationWithAssets")
                {
                    new UltraApplicationWithAssets().Container.AttachToDocument();
                }
                else
                    if (Native.Document.location.hash == "#/audio")
                    {
                        Action AtTimer = delegate { };

                        (1000 / 15).AtInterval(
                            tt =>
                            {
                                AtTimer();
                            }
                        );

                        new SoundCloudBackground().Container.AttachTo(MyPagesBackground);
                        new SoundCloudHeader().Container.AttachTo(MyPagesInternal);

                        var page = 1;

                        var Tracks = new IHTMLDiv().AttachTo(MyPagesInternal);
                        Tracks.style.margin = "1em";

                        var More = new SoundCloudMore();

                        var AudioLinks = default(AudioLink);

                        var LoadCurrentPage = default(Action);

                        LoadCurrentPage = delegate
                        {
                            var loading = new SoundCloudLoading();

                            loading.Container.AttachTo(Tracks);


                            new UltraWebService().SoundCloudTracksDownload(
                                System.Convert.ToString(page),
                                ee =>
                                {
                                    if (loading != null)
                                    {
                                        loading.Container.Orphanize();
                                        loading = null;
                                    }

                                    var t = new SoundCloudTrack();

                                    t.Content.ApplyToggleConcept(t.HideContent, t.ShowContent).Hide();

                                    t.Title.innerHTML = ee.trackName;
                                    t.Waveform.src = ee.waveformUrl;

                                    t.Audio.src = ee.streamUrl;
                                    t.Audio.autobuffer = true;


                                    AudioLinks = new AudioLink
                                    {
                                        Audio = t.Audio,
                                        Prev = AudioLinks
                                    };

                                    var _AudioLinks = AudioLinks;

                                    if (AudioLinks.Prev != null)
                                        AudioLinks.Prev.Next = AudioLinks;
                                    else
                                        // we are the first  :)
                                        t.Audio.play();

                                    t.MoreButton.onclick +=
                                        delegate
                                        {
                                            t.Audio.pause();

                                            if (_AudioLinks.Next != null)
                                            {
                                                _AudioLinks.Next.Audio.currentTime = 0;
                                                _AudioLinks.Next.Audio.play();

                                                if (_AudioLinks.Next.Next == null)
                                                {
                                                    page++;
                                                    LoadCurrentPage();
                                                }
                                            }
                                        };

                                    t.Audio.onended +=
                                        delegate
                                        {
                                            if (_AudioLinks.Next != null)
                                            {
                                                _AudioLinks.Next.Audio.currentTime = 0;
                                                _AudioLinks.Next.Audio.play();

                                                if (_AudioLinks.Next.Next == null)
                                                {
                                                    page++;
                                                    LoadCurrentPage();
                                                }
                                            }
                                        };

                                    t.Identity.innerText = ee.uid;

                                    t.Play.onclick += eee => { eee.PreventDefault(); t.Audio.play(); };
                                    t.Pause.onclick += eee => { eee.PreventDefault(); t.Audio.pause(); };

                                    t.Title.style.cursor = IStyle.CursorEnum.pointer;
                                    t.Title.onclick += eee =>
                                        {
                                            eee.PreventDefault();

                                            var playing = true;

                                            if (t.Audio.paused)
                                                playing = false;

                                            if (t.Audio.ended)
                                                playing = false;

                                            if (!playing)
                                                t.Audio.play();
                                            else
                                                t.Audio.pause();
                                        };

                                    DoubleAction SetProgress1 = p =>
                                    {

                                        t.Gradient3.style.width = System.Convert.ToInt32(800 * p) + "px";
                                        t.Gradient4.style.width = System.Convert.ToInt32(800 * p) + "px";
                                    };

                                    t.Gradient5.style.Opacity = 0.4;
                                    t.Gradient6.style.Opacity = 0.4;

                                    DoubleAction SetProgress2 = p =>
                                    {

                                        t.Gradient5.style.width = System.Convert.ToInt32(800 * p) + "px";
                                        t.Gradient6.style.width = System.Convert.ToInt32(800 * p) + "px";
                                    };

                                    AtTimer +=
                                        delegate
                                        {
                                            if (t.Audio.duration == 0)
                                            {
                                                t.Play.Hide();
                                                t.Pause.Hide();
                                                return;
                                            }
                                            else
                                            {

                                                var playing = true;

                                                if (t.Audio.paused)
                                                    playing = false;

                                                if (t.Audio.ended)
                                                    playing = false;

                                                if (!playing)
                                                    t.Title.style.color = Color.None;
                                                else
                                                    t.Title.style.color = Color.Blue;

                                                t.Play.Show(!playing);
                                                t.Pause.Show(playing);
                                            }

                                            var p = t.Audio.currentTime / t.Audio.duration;
                                            SetProgress1(p);
                                        };

                                    t.Waveform.onmouseout +=
                                        delegate
                                        {
                                            SetProgress2(0);
                                        };

                                    t.Waveform.onmousemove +=
                                        eee =>
                                        {
                                            SetProgress2(eee.OffsetX / 800.0);
                                        };

                                    t.Waveform.onclick +=
                                        eee =>
                                        {
                                            t.Audio.currentTime = t.Audio.duration * (eee.OffsetX / 800.0);
                                            t.Audio.play();
                                        };

                                    t.Waveform.style.cursor = IStyle.CursorEnum.pointer;

                                    SetProgress1(0);
                                    SetProgress2(0);

                                    t.Container.AttachTo(Tracks);
                                }
                            );


                            10000.AtDelay(
                                delegate
                                {
                                    More.MoreButton.FadeIn(0, 1000, null);
                                }
                            );
                        };


                        More.MoreButton.Hide();
                        More.Container.AttachTo(MyPagesInternal);

                        More.MoreButton.onclick += eee =>
                            {
                                eee.PreventDefault();
                                More.MoreButton.FadeOut(1, 300,
                                    delegate
                                    {
                                        page++;
                                        LoadCurrentPage();
                                    }
                                );
                            };

                        LoadCurrentPage();

                    }
                    else
                    {
                        //new PromotionWebApplication1.HTML.Audio.FromAssets.Track1 { controls = true }.AttachToDocument();
                        //new PromotionWebApplication1.HTML.Audio.FromWeb.Track1 { controls = true, autobuffer = true }.AttachToDocument();

                        var IsAvalonJavaScript = hash == "#/avalon.js";
                        var IsAvalonActionScript = hash == "#/avalon.as";
                        var IsAvalon = IsAvalonActionScript || IsAvalonJavaScript;

                        //if (IsAvalon)
                        //{

                        //{
                        //    var ccc = new IHTMLDiv();

                        //    ccc.style.position = IStyle.PositionEnum.absolute;
                        //    ccc.style.left = "15%";
                        //    ccc.style.right = "15%";
                        //    ccc.style.top = "15%";


                        //    var Now = DateTime.Now;

                        //    var CountDown = new CountDownGadgetConcept(CountDownGadget.Create)
                        //    {
                        //        ShowOnlyDays = true,
                        //        Event = new DateTime(2010, 5, 24, 23, 59, 50),

                        //    };

                        //    CountDown.Element.GadgetContainer.style.color = "#808080";
                        //    CountDown.Element.GadgetContainer.style.textShadow = "#E0E0E0 1px 1px 1px";


                        //    CountDown.Element.GadgetContainer.AttachTo(ccc);
                        //    CountDown.Element.GadgetContainer.FadeIn(3000, 2000, null);

                        //    ccc.AttachToDocument();
                        //}

                        {
                            var ccc = new IHTMLDiv();

                            ccc.style.position = IStyle.PositionEnum.absolute;
                            ccc.style.left = "50%";
                            ccc.style.top = "50%";
                            ccc.style.marginLeft = (-JSCSolutionsNETCarouselCanvas.DefaultWidth / 2) + "px";
                            ccc.style.marginTop = (-JSCSolutionsNETCarouselCanvas.DefaultHeight / 2) + "px";

                            ccc.style.SetSize(JSCSolutionsNETCarouselCanvas.DefaultWidth, JSCSolutionsNETCarouselCanvas.DefaultHeight);

                            ccc.AttachToDocument();

                            if (IsAvalonActionScript)
                            {
                                var alof = new UltraSprite();
                                alof.ToTransparentSprite();
                                alof.AttachSpriteTo(ccc);
                            }
                            else
                            {
                                var alo = new JSCSolutionsNETCarouselCanvas();
                                alo.Container.AttachToContainer(ccc);

                                alo.AtLogoClick +=
                                    delegate
                                    {
                                        //Native.Window.open("http://sourceforge.net/projects/jsc/", "_blank");
                                        Native.Window.open("/download", "_blank");
                                    };

                            }
                        }
                        //}
                        //else
                        //{
                        //    var cc = new HTML.Pages.FromAssets.Controls.Named.CenteredLogo_Kamma();

                        //    cc.Container.AttachToDocument();

                        //    // see: http://en.wikipedia.org/wiki/Perl_control_structures
                        //    // "Unless" == "if not"  ;)

                        //    IsMicrosoftInternetExplorer.YetIfNotThen(cc.TheLogoImage.BeginPulseAnimation).ButIfSoThen(cc.TheLogoImage.HideNowButShowAtDelay);
                        //}

                        var aa = new About();
                        aa.Service.innerText = gapageview;
                        aa.Container.AttachToDocument();

                    }
            }
        #endregion


            Analytics =
                __hash =>
                {
                    var __gahash = Native.Window.escape(__hash);
                    var __gapageview = gapathname + gasearch + __gahash;


                    "UA-13087448-1".ToGoogleAnalyticsTracker(
                        pageTracker =>
                        {
                            pageTracker._setDomainName(".jsc-solutions.net");
                            pageTracker._trackPageview(__gapageview);


                        }
                    );
                };

            Analytics(Native.Document.location.hash);


        }
        public MineSweeperDemoPage()
        {
            Native.Document.body.style.background = "#6591cd url(" + Assets.Default.g_6591cd + ") repeat-x";

            Func <string, IHTMLElement> Paragraph =
                text => new IHTMLElement(IHTMLElement.HTMLElementEnum.p, text);

            Func <string, IHTMLElement> AddParagraph =
                text => Paragraph(text).AttachTo(Control);

            Native.Document.title = "Minesweeper";


            new IHTMLElement(IHTMLElement.HTMLElementEnum.h1, "Minesweeper").AttachTo(Control);



            var game = new MineSweeperPanel(8, 8, 0.12, Assets.Default);

            game.Control.AttachTo(Control);
            game.Control.style.Float = ScriptCoreLib.JavaScript.DOM.IStyle.FloatEnum.right;

            AddParagraph("The object of Minesweeper is to locate all the mines as quickly as possible without uncovering any of them. If you uncover a mine, you lose the game.");

            Action <string, Action> AddButton =
                (text, h) => new IHTMLButton(text).AttachTo(Control).onclick += ev => h();

            AddButton("Beginner", delegate
            {
                var n = new MineSweeperPanel(8, 8, 0.12, Assets.Default);

                n.Control.style.Float = ScriptCoreLib.JavaScript.DOM.IStyle.FloatEnum.right;
                game.Control.replaceWith(n.Control);

                game = n;
            });
            AddButton("Intermediate", delegate
            {
                var n = new MineSweeperPanel(16, 8, 0.15, Assets.Default);

                n.Control.style.Float = ScriptCoreLib.JavaScript.DOM.IStyle.FloatEnum.right;
                game.Control.replaceWith(n.Control);

                game = n;
            });
            AddButton("Expert", delegate
            {
                var n = new MineSweeperPanel(32, 8, 0.2, Assets.Default);

                n.Control.style.Float = ScriptCoreLib.JavaScript.DOM.IStyle.FloatEnum.right;
                game.Control.replaceWith(n.Control);

                game = n;
            });

            new IHTMLElement(IHTMLElement.HTMLElementEnum.h3, "Notes").AttachTo(Control);

            AddParagraph("You can uncover a square by clicking it. If you uncover a mine, you lose the game.");
            AddParagraph("If a number appears on a square, it indicates how many mines are in the eight squares that surround the numbered one. ");
            AddParagraph("To mark a square you suspect contains a mine, ctrl-click it. ");
            AddParagraph("The game area consists of the playing field, a mine counter, and a timer. ");

            new IHTMLElement(IHTMLElement.HTMLElementEnum.h3, "Strategies and tips").AttachTo(Control);

            AddParagraph("If you are uncertain about a square, ctrl-click it twice to mark it with a question mark (?). Later, you can either mark the square as a mine or remove the markings by ctrl-clicking the square again once or twice. ");
            AddParagraph("If you have marked all the mines around a numbered square, you can uncover the remaining squares around it by ctrl-clicking the numbered square. If not all mines surrounding the numbered square have been marked, the remaining covered or unmarked squares will appear to be depressed (or flash) when the numbered square is ctrl-clicked. ");
            AddParagraph("Look for common patterns in numbers, which often indicate a corresponding pattern of mines. For example, the pattern 2-3-2 at the edge of a group of uncovered squares indicates a row of three mines next to the three numbers. ");

            new IHTMLElement(IHTMLElement.HTMLElementEnum.h3, "About").AttachTo(Control);

            AddParagraph("").innerHTML = "This is a javascript version of <a href='http://en.wikipedia.org/wiki/Minesweeper_(computer_game)'>the Minesweeper game</a> compiled from a c# project <a href='http://jsc.sourceforge.net/'>by jsc</a>. You can <a href='http://jsc.svn.sourceforge.net/viewvc/jsc/javascript/Examples/MineSweeper/MineSweeper/js/'>view the source</a> at the svn. You can set parameters for the game via xml like in <a href='MineSweeperGame.htm'>this example</a>.";

            var Preview = new IHTMLImage(Assets.Default.Preview).AttachTo(Control);
        }
        static WebGLTexture loadTexture(WebGLRenderingContext gl, string url, Action callback)
        {
            //gl.enable(gl.TEXTURE_2D);

            var texture = gl.createTexture();
            var image = new IHTMLImage();

            Console.WriteLine("loading: " + url);
            image.src = url;

            image.InvokeOnComplete(
                delegate
                {
                    Console.WriteLine("loaded: " + url);

                    gl.bindTexture(gl.TEXTURE_2D, texture);
                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, (int)gl.LINEAR);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, (int)gl.LINEAR);
                    gl.bindTexture(gl.TEXTURE_2D, null);

                    callback();
                }
            );

            return texture;
        }
Exemple #55
0
        public static void InitializeContent()
        {
            #region tutorial step 2
            #region arena
            var map = new Point(2000, 2000);

            var arena = new ArenaControl();

            arena.Layers.Canvas.style.backgroundColor =
                Color.FromGray(0xc0);
            arena.SetLocation(
                Rectangle.Of(0, 0, Native.window.Width, Native.window.Height));

            arena.SetCanvasSize(map);

            arena.Control.AttachToDocument();


            arena.DrawTextToInfo(Title, new Point(8, 8), Color.Blue);

            Native.window.onresize +=
                delegate
            {
                arena.SetLocation(
                    Rectangle.Of(0, 0, Native.window.Width, Native.window.Height));

                arena.SetCanvasPosition(
                    arena.CurrentCanvasPosition
                    );
            };
            #endregion
            #endregion


            var pending = default(Dude2);

            #region arsenal
            var arsenal = new Dictionary <string, DudeAnimationInfo>
            {
                { "Soldier",
                  new DudeAnimationInfo
                  {
                      Frames_Stand = Frames.WolfSoldier,
                      Frames_Walk  = Frames.WolfSoldier_Walk
                  } },
                { "Imp",
                  new DudeAnimationInfo
                  {
                      Frames_Stand = Frames.DoomImp,
                      Frames_Walk  = Frames.DoomImp_Walk
                  } }
            };
            #endregion


            #region tutorial step 3

            Func <DudeAnimationInfo, Point, Dude2> CreateActor =
                (_frames, _coords) =>
            {
                var actor = new Dude2();

                actor.Frames = _frames.Frames_Stand;
                actor.AnimationInfo.Frames_Stand = _frames.Frames_Stand;
                actor.AnimationInfo.Frames_Walk  = _frames.Frames_Walk;
                actor.Zoom.DynamicZoomFunc       = a => 1;
                actor.SetSize(48, 72);
                actor.TeleportTo(_coords.X, _coords.Y);
                actor.Zoom.StaticZoom = DefaultActiorZoom;
                actor.Direction       = Math.PI * 0.5;
                actor.Control.AttachTo(arena.Layers.Canvas);
                //actor.HasShadow = _frames.Frames_Stand.Length > 1;
                if (_frames.Frames_Stand.Length == 1)
                {
                    actor.Shadow.style.Opacity = 0.4;
                }
                actor.AnimationInfo.WalkAnimationInterval = 1000 / 30;
                return(actor);
            };

            var actors = new List <Dude2>
            {
            };

            var selection = from i in actors
                            where i.IsSelected
                            select i;

            arena.ApplySelection +=
                (rect, ev) =>
            {
                if (pending != null)
                {
                    return;
                }

                foreach (var v in actors)
                {
                    v.IsSelected = rect.Contains(v.CurrentLocation.ToInt32());
                }
            };

            var Argh        = new Argh();
            var Affirmative = new Affirmative();
            var ghoullaugh  = new ghoullaugh();
            var sheep       = new sheep();
            var pig         = new pig();
            var click       = new click().AttachToDocument();

            arena.SelectionClick +=
                (p, ev) =>
            {
                if (pending != null)
                {
                    return;
                }

                foreach (var v in selection)
                {
                    if (v.AnimationInfo.Frames_Stand[0].Source == MyFrames.ManWithHorns.Frames_Stand[0].Source)
                    {
                        ghoullaugh.play();
                        ghoullaugh = new ghoullaugh();
                    }
                    else if (v.AnimationInfo.Frames_Stand[0].Source == MyFrames.ThePig.Frames_Stand[0].Source)
                    {
                        pig.play();
                        pig = new pig();
                    }
                    else if (v.AnimationInfo.Frames_Stand[0].Source == MyFrames.TheSheep.Frames_Stand[0].Source)
                    {
                        sheep.play();
                        sheep = new sheep();
                    }
                    else if (v.AnimationInfo.Frames_Stand[0].Source == Frames.WolfSoldier[0].Source)
                    {
                        Affirmative.play();
                        Affirmative = new Affirmative();
                    }
                    else
                    {
                        Argh.play();
                        Argh = new Argh();
                    }



                    v.WalkTo(p.ToDouble());

                    // move in group formation
                    p.X += 16;
                    p.Y += 16;
                }
            };


            #endregion

            #region tutorial step 4



            #region CreateDialogAt
            var CreateDialogAt =
                new
            {
                //Dialog = default(IHTMLDiv),
                Content = default(IHTMLDiv),
                Width   = default(string)
            }
            .ToFunc(
                (Point pos, string width) =>
            {
                var f = new Form();

                f.Show();

                f.SizeTo(200, 200);


                // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151115/audio
                //f.PopupInsteadOfClosing();

                f.MoveTo(pos.X, pos.Y);
                //f.SizeTo(


                //var dialog = new IHTMLDiv();

                //dialog.style.SetLocation(pos.X, pos.Y);

                //dialog.style.backgroundColor = Color.Gray;
                //dialog.style.padding = "1px";

                //var caption = new IHTMLDiv().AttachTo(dialog);

                //caption.style.backgroundColor = Color.Blue;
                //caption.style.width = width;
                //caption.style.height = "0.5em";
                //caption.style.cursor = IStyle.CursorEnum.move;

                //var drag = new DragHelper(caption);

                //drag.Position = pos;
                //drag.Enabled = true;
                //drag.DragMove +=
                //    delegate
                //    {
                //        dialog.style.SetLocation(drag.Position.X, drag.Position.Y);
                //    };

                var _content = new IHTMLDiv().AttachTo(f.GetHTMLTargetContainer());

                _content.style.textAlign       = IStyle.TextAlignEnum.center;
                _content.style.backgroundColor = Color.White;
                _content.style.padding         = "1px";

                //dialog.AttachToDocument();

                return(new
                {     //Dialog = dialog,
                    Content = _content,
                    Width = width
                });
            }
                );
            #endregion

            #region dialog
            var toolbar = CreateDialogAt(new Point(2, 2), "8em");

            var combo = new IHTMLSelect();
            var build = new IHTMLButton();

            build.style.SetSize(72, 72);
            build.style.padding = "0px";

            var avatar = new IHTMLImage().AttachTo(build);
            var remove = new IHTMLButton("Remove");


            combo.AttachTo(toolbar.Content);
            new IHTMLBreak().AttachTo(toolbar.Content);
            build.AttachTo(toolbar.Content);
            new IHTMLBreak().AttachTo(toolbar.Content);
            remove.AttachTo(toolbar.Content);
            new IHTMLBreak().AttachTo(toolbar.Content);
            #endregion


            #region GetSelectedArsenal
            Func <DudeAnimationInfo> GetSelectedArsenal =
                () =>
            {
                if (arsenal.ContainsKey(combo[combo.selectedIndex].value))
                {
                    return(arsenal[combo[combo.selectedIndex].value]);
                }

                return(null);
            };
            #endregion

            Action Refresh =
                delegate
            {
                var i = GetSelectedArsenal();

                if (i != null)
                {
                    avatar.src = i.Images.Random().src;
                }
            };

            combo.Add(arsenal.Keys.ToArray());
            Refresh();

            combo.onchange +=
                delegate
            {
                Refresh();



                click.play();
                click = new click().AttachToDocument();
            };

            #region pending actor

            arena.MouseMove +=
                p =>
            {
                if (pending == null)
                {
                    return;
                }

                pending.TeleportTo(p.X, p.Y);
            };

            arena.Layers.User.oncontextmenu +=
                e =>
            {
                e.preventDefault();

                if (pending != null)
                {
                    pending.Control.Orphanize();
                    pending = null;
                    arena.ShowSelectionRectangle = true;

                    return;
                }

                actors.ForEach(
                    k => k.IsSelected = false
                    );
            };

            arena.SelectionClick +=
                (p, ev) =>
            {
                if (pending == null)
                {
                    return;
                }

                pending.TeleportTo(p.X, p.Y);

                actors.Add(pending);

                pending.IsHot = false;


                var x = GetSelectedArsenal();
                pending = CreateActor(x,
                                      new Point(
                                          Native.window.Width / 2,
                                          Native.window.Height / 2
                                          )
                                      );

                pending.IsHot = true;


                click.play();
                click = new click().AttachToDocument();
            };

            build.onclick +=
                delegate
            {
                if (pending != null)
                {
                    pending.Control.Orphanize();
                    pending = null;

                    return;
                }

                var x = GetSelectedArsenal();

                pending = CreateActor(x,
                                      new Point(
                                          Native.window.Width / 2,
                                          Native.window.Height / 2
                                          )
                                      );

                pending.IsHot = true;
                arena.ShowSelectionRectangle = false;

                click.play();
                click = new click().AttachToDocument();
            };
            #endregion

            remove.onclick +=
                delegate
            {
                foreach (var v in selection.ToArray())
                {
                    v.Control.Orphanize();
                    actors.Remove(v);
                }


                click.play();
                click = new click().AttachToDocument();
            };

            #endregion

            if (FilterToImpAndSoldier)
            {
            }
            else
            {
                #region step 6

                {
                    var n = "NPC";

                    arsenal.Add(n, MyFrames.NPC3);
                    combo.Add(n);
                }

                #endregion


                {
                    var n = "ManWithHorns";

                    arsenal.Add(n, MyFrames.ManWithHorns);
                    combo.Add(n);
                }
                {
                    var n = "TheSheep";

                    arsenal.Add(n, MyFrames.TheSheep);
                    combo.Add(n);
                }
                {
                    var n = "ThePig";

                    arsenal.Add(n, MyFrames.ThePig);
                    combo.Add(n);
                }

                {
                    var n = "TheCactus";

                    arsenal.Add(n, MyFrames.TheCactus);
                    combo.Add(n);
                }
            }


            if (BeforeAddingDebris != null)
            {
                BeforeAddingDebris(arena.Layers.Canvas);
            }

            3.Times(
                delegate()
            {
                new DebrisImages().Images.ForEach(
                    img => img.AttachTo(arena.Layers.Canvas).style.SetLocation(map.X.Random(), map.Y.Random())
                    );
            }
                );

            16.Times(
                delegate()
            {
                actors.Add(
                    CreateActor(arsenal.Random().Value, new Point(map.X.Random(), map.Y.Random()))
                    );
            }
                );
        }
Exemple #56
0
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150812/cssstereo



            // https://www.reddit.com/r/GearVR/comments/35g8w7/real_world_stereoscopic_360_panoramas/
            // https://www.reddit.com/r/oculus/comments/35gcn2/real_world_stereoscopic_panoramas_with_gear_vr/
            // http://stackoverflow.com/questions/9032050/canvas-mask-an-image-and-preserve-its-alpha-channel
            // https://3dwarehouse.sketchup.com/model.html?id=48bcce07b0baf689d9e6f00e848ea18
            // https://www.youtube.com/watch?v=OurzBO1cDto

            Native.body.style.margin   = "0px";
            Native.body.style.overflow = IStyle.OverflowEnum.hidden;
            Native.body.Clear();

            new IHTMLPre {
                "loading stereo... 2MB!"
            }.AttachToDocument();

            // if this is a chrome app
            // would GearVR 360 app be able to request current stereo cubemap?



            // Uncaught TypeError: Cannot read property '0' of undefined
            var keys = new int[0xffff];

            //c = a[0].keys[jAEABqtXvT6n4h6m6ZavdA(b)];
            //d = c[0];
            //c[0] = (((d + 1)));



            Native.document.body.onkeyup +=
                e =>
            {
                var z = keys[e.KeyCode];

                if (z > 0)
                {
                    z++;
                }
                else
                {
                    z = 1;
                }

                // what does it do?
                keys[e.KeyCode] = z;

                // 4333ms {{ KeyCode = 83, S = 83, z = NaN }}
                Console.WriteLine(new { e.KeyCode, System.Windows.Forms.Keys.S, z });
            };


            // skybox cubemap
            var iii = new IHTMLImage[] {
                new px(), new nx(),
                new py(), new ny(),
                new pz(), new nz()
            };


            //var f12 = await new airplane().async.oncomplete;
            //var f12 = new airplane();



            Task.WhenAll(from x in iii select x.async.oncomplete).ContinueWithResult(
                ii =>



                // how can we do an alpha clear on the jpg?
                //new airplane().async.oncomplete.ContinueWithResult(
                //new airplane_leftwindows().async.oncomplete.ContinueWithResult(
                new airplane_mask().async.oncomplete.ContinueWithResult(
                    f12_mask =>
                    new airplane().async.oncomplete.ContinueWithResult(
                        f12 =>
            {
                //Func<int, string, IHTMLImage> xf = (i, globalCompositeOperation) =>
                //{
                //    // we do have a skybox example somewhere...
                //    var f1 = new CanvasRenderingContext2D(w: f12.height, h: f12.height);

                //    f1.drawImage(f12, i * f12.height, 0, sw: f12.height, sh: f12.height, dx: 0, dy: 0, dw: f12.height, dh: f12.height);

                //    // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
                //    f1.globalCompositeOperation = globalCompositeOperation;

                //    f1.drawImage(f12_mask, i * f12.height, 0, sw: f12.height, sh: f12.height, dx: 0, dy: 0, dw: f12.height, dh: f12.height);

                //    return f1;
                //};


                //new[] {
                //    "source-over",
                //    "source-in",
                //    "source-out",
                //    "source-atop",
                //    "destination-over",
                //    "destination-in",
                //    "destination-out",
                //    "destination-atop",
                //    "lighter",
                //    "copy",
                //    "xor",
                //    "multiply",
                //    "screen",
                //    "overlay",
                //    "darken",
                //    "lighten",
                //    "color-dodge",
                //    "color-burn",
                //    "hard-light",
                //    "soft-light",
                //    "difference",
                //    "exclusion",
                //    "hue",
                //    "saturation",
                //    "color",
                //    "luminosity"
                //}.WithEach(globalCompositeOperation =>
                //    {

                //        xf(4, globalCompositeOperation).AttachToDocument().title = globalCompositeOperation;
                //    }
                //);


                Func <int, IHTMLImage> f = i =>
                {
                    // we do have a skybox example somewhere...
                    var f1 = new CanvasRenderingContext2D(w: f12.height, h: f12.height);

                    f1.drawImage(f12, i * f12.height, 0, sw: f12.height, sh: f12.height, dx: 0, dy: 0, dw: f12.height, dh: f12.height);

                    // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
                    f1.globalCompositeOperation = "multiply";

                    f1.drawImage(f12_mask, i * f12.height, 0, sw: f12.height, sh: f12.height, dx: 0, dy: 0, dw: f12.height, dh: f12.height);

                    return(f1);
                };



                var skyScene0 = new THREE.Scene();
                var skyScene1 = new THREE.Scene();
                var skyScene2 = new THREE.Scene {
                };


                #region  createSky
                // gearvr has photos360 app



                //var textureCube = THREE.ImageUtils.loadTextureCube(urls);


                var vertexShader =
                    @"
varying vec3 vWorldPosition;
            "
                    //+ THREE.ShaderChunk["logdepthbuf_pars_vertex"]
                    +
                    @"
void main() {
vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); 
vWorldPosition = worldPosition.xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
"
                    //+ THREE.ShaderChunk["logdepthbuf_vertex"]
                    + @"
}
"

                ;
                // https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/texturing.php

                var fragmentShader =
                    @"
uniform samplerCube tCube; 
uniform float tFlip; 
varying vec3 vWorldPosition;
                   "
                    //+ THREE.ShaderChunk["logdepthbuf_pars_fragment"]
                    + @"
void main() 
{

vec4 c = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );
"

                    // : gl.getShaderInfoLog() ERROR: 0:52: 'assign' :  cannot convert from 'const int' to 'highp float'

                    //+ THREE.ShaderChunk["logdepthbuf_fragment"]
                    + @"

// _mask.png has the bits
if (c.r == 0.0) if (c.g == 0.0) if (c.b == 0.0) discard;

gl_FragColor = c;

}
"
                    // vec4 textureCube(samplerCube s, vec3 coord [, float bias])
                    //
                ;



                var skyMeshmaterial0 = new THREE.ShaderMaterial(new
                {
                    fragmentShader = fragmentShader,
                    vertexShader   = vertexShader,
                    uniforms       = new
                    {
                        tCube = new
                        {
                            type  = "t",
                            value = new THREE.CubeTexture(ii
                                                          )
                            {
                                flipY = false,

                                // !!
                                needsUpdate = true
                            }
                        },
                        tFlip = new { type = "f", value = -1 }
                    },
                    depthWrite = false,
                    side       = THREE.BackSide
                });

                var mesh0 = new THREE.Mesh(new THREE.BoxGeometry(10000, 10000, 10000), skyMeshmaterial0).AttachTo(skyScene0);



                // stereo vs mono skybox
                var skyMeshmaterial1 = new THREE.ShaderMaterial(new
                {
                    fragmentShader = fragmentShader,
                    vertexShader   = vertexShader,
                    uniforms       = new
                    {
                        tCube = new
                        {
                            type  = "t",
                            value = new THREE.CubeTexture(
                                f(0), f(1),
                                f(2), f(3),
                                f(4), f(5)
                                )
                            {
                                flipY = false,

                                // !!
                                needsUpdate = true
                            }
                        },
                        tFlip = new { type = "f", value = -1 }
                    },
                    depthWrite = false,
                    side       = THREE.BackSide,
                });

                var mesh1 = new THREE.Mesh(new THREE.BoxGeometry(10000, 10000, 10000), skyMeshmaterial1).AttachTo(skyScene1);


                var skyMeshmaterial2 = new THREE.ShaderMaterial(new
                {
                    fragmentShader = fragmentShader,
                    vertexShader   = vertexShader,
                    uniforms       = new
                    {
                        tCube = new
                        {
                            type  = "t",
                            value = new THREE.CubeTexture(
                                f(0 + 6), f(1 + 6),
                                f(2 + 6), f(3 + 6),
                                f(4 + 6), f(5 + 6)
                                )
                            {
                                flipY = false,


                                // !!
                                needsUpdate = true
                            }
                        },
                        tFlip = new { type = "f", value = -1 }
                    },
                    depthWrite = false,
                    side       = THREE.BackSide
                });

                var mesh2 = new THREE.Mesh(new THREE.BoxGeometry(10000, 10000, 10000), skyMeshmaterial2).AttachTo(skyScene2);
                #endregion


                Native.body.Clear();

                var skyCamera = new THREE.PerspectiveCamera(90, Native.window.aspect, 1, 20000);
                //var skyCamera = new THREE.PerspectiveCamera(45, Native.window.aspect, 1, 20000);

                // not using css?
                // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150812/cssstereo

                var renderer = new THREE.WebGLRenderer(new { antialias = true, alpha = false })
                {
                    autoClear        = false,
                    shadowMapEnabled = true,
                    shadowMapType    = THREE.PCFSoftShadowMap
                };

                renderer.setSize(Native.window.Width, Native.window.Height);
                renderer.domElement.AttachToDocument();


                #region onresize
                new { }.With(
                    async delegate
                {
                    do
                    {
                        skyCamera.aspect = Native.window.aspect;
                        skyCamera.updateProjectionMatrix();
                        renderer.setSize(Native.window.Width, Native.window.Height);
                    } while (await Native.window.async.onresize);
                }
                    );
                #endregion

                Native.document.body.onmousewheel +=
                    e =>
                {
                    skyCamera.fov -= e.WheelDirection * 5.0;
                    skyCamera.updateProjectionMatrix();
                };



                var target0 = new THREE.Vector3();

                var lon   = 90.0;
                var lat   = 0.0;
                var phi   = 0.0;
                var theta = 0.0;



                var drag = false;

                var sw = Stopwatch.StartNew();

                Native.window.onframe +=
                    delegate
                {
                    var sinfps            = 1 + (int)(((Math.Sin(sw.ElapsedMilliseconds * 0.0001) + 1.0) / 2.0) * 59);
                    Native.document.title = "" + new { sinfps };


                    //var eye = (sw.ElapsedMilliseconds / (200)) % 2;
                    //var eye = (sw.ElapsedMilliseconds / (1000 / 15)) % 2;
                    //var eye = (sw.ElapsedMilliseconds / (1000 / 30)) % 2;
                    //var eye = (sw.ElapsedMilliseconds / (1000 / 45)) % 2;
                    //var eye = (sw.ElapsedMilliseconds / (1000 / 60)) % 2;
                    var eye = (sw.ElapsedMilliseconds / (1000 / sinfps)) % 2;
                    //  if we are a multiprocess renderer, get the volatile eye id


                    // doesnt work?
                    //skyMesh0.visible = eye == 0;

                    //mesh0.rotation = new THREE.Vector3(0, 0, sw.ElapsedMilliseconds);


                    if (Native.document.pointerLockElement == Native.document.body)
                    {
                        lon += 0.00;
                    }
                    else
                    {
                        lon += 0.01;
                    }

                    lat = Math.Max(-85, Math.Min(85, lat));


                    // this is wrong, but gets the idea across.
                    phi   = THREE.Math.degToRad(90 - lat) + Math.Sin(sw.ElapsedMilliseconds * 0.001) * 0.1 - 0.3;
                    theta = THREE.Math.degToRad(lon);

                    target0.x = Math.Sin(phi) * Math.Cos(theta);
                    target0.y = Math.Cos(phi);
                    target0.z = Math.Sin(phi) * Math.Sin(theta);

                    skyCamera.lookAt(target0);


                    renderer.clear();

                    renderer.render(skyScene0, skyCamera);


                    phi   = THREE.Math.degToRad(90 - lat);
                    theta = THREE.Math.degToRad(lon);

                    target0.x = Math.Sin(phi) * Math.Cos(theta);
                    target0.y = Math.Cos(phi);
                    target0.z = Math.Sin(phi) * Math.Sin(theta);

                    skyCamera.lookAt(target0);

                    if ((keys[(int)System.Windows.Forms.Keys.S] % 3) == 0)
                    {
                        if (eye == 0)
                        {
                            renderer.render(skyScene1, skyCamera);
                        }
                        else
                        {
                            renderer.render(skyScene2, skyCamera);
                        }
                    }
                    else if ((keys[(int)System.Windows.Forms.Keys.S] % 3) == 1)
                    {
                        renderer.render(skyScene1, skyCamera);
                    }
                };

                #region ontouchmove
                var touchX = 0;
                var touchY = 0;

                Native.document.body.ontouchstart +=
                    e =>
                {
                    e.preventDefault();

                    var touch = e.touches[0];

                    touchX = touch.screenX;
                    touchY = touch.screenY;
                };


                Native.document.body.ontouchmove +=
                    e =>
                {
                    e.preventDefault();

                    var touch = e.touches[0];

                    lon -= (touch.screenX - touchX) * 0.1;
                    lat += (touch.screenY - touchY) * 0.1;

                    touchX = touch.screenX;
                    touchY = touch.screenY;
                };
                #endregion



                #region camera rotation
                Native.document.body.onmousemove +=
                    e =>
                {
                    e.preventDefault();

                    if (Native.document.pointerLockElement == Native.document.body)
                    {
                        lon += e.movementX * 0.1;
                        lat -= e.movementY * 0.1;

                        //Console.WriteLine(new { lon, lat, e.movementX, e.movementY });
                    }
                };


                Native.document.body.onmouseup +=
                    e =>
                {
                    drag = false;
                    e.preventDefault();
                };

                Native.document.body.onmousedown +=
                    e =>
                {
                    //e.CaptureMouse();

                    drag = true;
                    e.preventDefault();
                    Native.document.body.requestPointerLock();
                };


                Native.document.body.ondblclick +=
                    e =>
                {
                    e.preventDefault();

                    Console.WriteLine("requestPointerLock");
                };

                #endregion
            }
                        )
                    )
                );
        }
        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150912/x360mountains




        //  ls sdcard/oculus/360photos/
        // "X:\vr\0000.png"
        // R:\util\android-sdk-windows\platform-tools\adb.exe push "X:\vr\0000.png" /sdcard/oculus/360photos/
        // 2649 KB/s (1085134 bytes in 0.400s)

        // "X:\vr\tr.png"
        // R:\util\android-sdk-windows\platform-tools\adb.exe push "X:\vr\tr.png" /sdcard/oculus/360photos/


        // R:\util\android-sdk-windows\platform-tools\adb.exe push  "X:\vr\code.png" /sdcard/oculus/360photos/
        // R:\util\android-sdk-windows\platform-tools\adb.exe push  "X:\vr\cone2.png" /sdcard/oculus/360photos/
        // "X:\vr\code.png"

        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150906/roomscanningeffectbyrosme

        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150816/iss

        // https://www.youtube.com/watch?v=UWiq-qgedws
        // https://www.youtube.com/watch?v=TwRSOEG-Gx4
        // http://youtu.be/Lo1IU8UAutE
        // 60hz 2160 4K!

        // The equirectangular projection was used in map creation since it was invented around 100 A.D. by Marinus of Tyre. 

        //        C:\Users\Arvo> "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\hzsky.png" "/sdcard/oculus/360photos/"
        //1533 KB/s(3865902 bytes in 2.461s)

        //C:\Users\Arvo> "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\tape360globe1\0000.png" "/sdcard/oculus/360photos/tape360globe1.png"
        //1556 KB/s(2714294 bytes in 1.703s)

        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\hz2048c3840x2160.png" "/sdcard/oculus/360photos/"
        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push   "X:\vr\tape360globe1\0000.png" "/sdcard/oculus/360photos/tape360globe2.png"
        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push   "X:\vr\tape360globe1\0000.png" "/sdcard/oculus/360photos/tape360globenight.png"
        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push   "R:\vr\tape360iss\0000.png" "/sdcard/oculus/360photos/tape360iss.png"
        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push   "R:\vr\tape360iss\0230.png" "/sdcard/oculus/360photos/tape360iss0230.png"

        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push    "X:\vr\sh1\0000.png" "/sdcard/oculus/360photos/sh1.png"
        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push     "R:\vr\tape360columns\0000.png" "/sdcard/oculus/360photos/tape360columns.png"
        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push    "X:\vr\edge.png" "/sdcard/oculus/360photos/tape360columns.png"
        // 4041 KB/s (3248448 bytes in 0.785s)

        //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push      "X:\vr\terrain.png" "/sdcard/oculus/360photos/"

        // could we udp our 360 image from webgl to vr yet?

        // "R:\vr\tape360iss\0230.png"

        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150809/chrome360hz

        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150809

        // the eye nor the display will be able to do any stereo
        // until tech is near matrix capability. 2019?

        // cubemap can be used for all long range scenes
        // http://www.imdb.com/title/tt0112111/?ref_=nv_sr_1


        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150808/cubemapcamera
        // subst /D b:
        // subst b: s:\jsc.svn\examples\javascript\chrome\apps\WebGL\x360mountains\x360mountains\bin\Debug\staging\x360mountains.Application\web
        // subst a: z:\jsc.svn\examples\javascript\chrome\apps\WebGL\x360mountains\x360mountains\bin\Debug\staging\x360mountains.Application\web
        // Z:\jsc.svn\examples\javascript\chrome\apps\WebGL\x360mountains\x360mountains\bin\Debug\staging\x360mountains.Application\web
        // what if we want to do subst in another winstat or session?

        // ColladaLoader: Empty or non-existing file (assets/x360mountains/S6Edge.dae)

        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IApp page)
        {
            //FormStyler.AtFormCreated =
            //s =>
            //{
            //    s.Context.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

            //    //var x = new ChromeTCPServerWithFrameNone.HTML.Pages.AppWindowDrag().AttachTo(s.Context.GetHTMLTarget());
            //    var x = new ChromeTCPServerWithFrameNone.HTML.Pages.AppWindowDragWithShadow().AttachTo(s.Context.GetHTMLTarget());



            //    s.Context.GetHTMLTarget().style.backgroundColor = "#efefef";
            //    //s.Context.GetHTMLTarget().style.backgroundColor = "#A26D41";

            //};

#if AsWEBSERVER
            #region += Launched chrome.app.window
            // X:\jsc.svn\examples\javascript\chrome\apps\ChromeTCPServerAppWindow\ChromeTCPServerAppWindow\Application.cs
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                // if we run as a server. we can open up on android.

                //chrome.Notification.DefaultTitle = "Nexus7";
                //chrome.Notification.DefaultIconUrl = new x128().src;
                ChromeTCPServer.TheServerWithStyledForm.Invoke(
                     AppSource.Text
                //, AtFormCreated: FormStyler.AtFormCreated

                //AtFormConstructor:
                //    f =>
                //    {
                //        //arg[0] is typeof System.Int32
                //        //script: error JSC1000: No implementation found for this native method, please implement [static System.Drawing.Color.FromArgb(System.Int32)]

                //        // X:\jsc.svn\examples\javascript\forms\Test\TestFromArgb\TestFromArgb\ApplicationControl.cs

                //        f.BackColor = System.Drawing.Color.FromArgb(0xA26D41);
                //    }
                );
                return;
            }
            #endregion
#else

            #region += Launched chrome.app.window
            dynamic self = Native.self;
            dynamic self_chrome = self.chrome;
            object self_chrome_socket = self_chrome.socket;

            if (self_chrome_socket != null)
            {
                if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
                {
                    Console.WriteLine("chrome.app.window.create, is that you?");

                    // pass thru
                }
                else
                {
                    // should jsc send a copresence udp message?
                    //chrome.runtime.UpdateAvailable += delegate
                    //{
                    //    new chrome.Notification(title: "UpdateAvailable");

                    //};

                    chrome.app.runtime.Launched += async delegate
                    {
                        // 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
                        Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

                        new chrome.Notification(title: "x360mountains");

                        // https://developer.chrome.com/apps/app_window#type-CreateWindowOptions
                        var xappwindow = await chrome.app.window.create(
                               Native.document.location.pathname, options: new
                               {
                                   alwaysOnTop = true,
                                   visibleOnAllWorkspaces = true
                               }
                        );

                        //xappwindow.setAlwaysOnTop

                        xappwindow.show();

                        await xappwindow.contentWindow.async.onload;

                        Console.WriteLine("chrome.app.window loaded!");
                    };


                    return;
                }
            }
            #endregion


#endif


            //var vs0 = new TraceConeWithCRTByKlk.Shaders.Program360FragmentShader();
            //var vs0 = new FaceEdgeVertexByPaniq.Shaders.Program360FragmentShader();
            var vs0 = new ChromeShaderToyMountainsByHoskins.Shaders.Program360FragmentShader();


            // onframe need syncs to enable GC!
            var vsync = default(TaskCompletionSource<object>);
            Func<bool> vsyncReady = delegate
            {

                if (vsync != null)
                    if (vsync.Task.IsCompleted)
                        return true;


                return false;
            };



            // crash
            //int cubefacesizeMAX = 2048 * 2; // 6 faces, ?

            // not responding...
            //int cubefacesizeMAX = 2048 * 2; // 6 faces, ?
            int cubefacesizeMAX = 2048; // 6 faces, ?
            //int cubefacesizeMAX = 1024; // 6 faces, ?
            int cubefacesize = cubefacesizeMAX; // 6 faces, ?
                                                //int cubefacesize = 1024; // 6 faces, ?
                                                // "X:\vr\tape1\0000x2048.png"
                                                // for 60hz render we may want to use float camera percision, not available for ui.
                                                //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\tape1\0000x2048.png" "/sdcard/oculus/360photos/"
                                                //  "x:\util\android-sdk-windows\platform-tools\adb.exe" push "X:\vr\tape1\0000x128.png" "/sdcard/oculus/360photos/"

            // force laptop into preview. when can we have a button for it?
            //if (Environment.ProcessorCount < 8)
            //    cubefacesize = 64; // 6 faces, ?

            // fast gif?
            //cubefacesize = 128; // 6 faces, ?
            //cubefacesize = 512; // 6 faces, ?
            //    [GroupMarkerNotSet(crbug.com / 242999)!:247F0809]
            //RENDER WARNING: texture bound to texture unit 0 is not renderable.It maybe non-power-of-2 and have incompatible texture filtering.

            // can we keep fast fps yet highp?

            // can we choose this on runtime? designtime wants fast fps, yet for end product we want highdef on our render farm?
            //const int cubefacesize = 128; // 6 faces, ?

            //var cubecameraoffsetx = 256;
            var cubecameraoffsetx = 400;


            //var uizoom = 0.1;
            //var uizoom = cubefacesize / 128f;
            var uizoom = 128f / cubefacesize;


            Native.css.style.backgroundColor = "blue";
            Native.css.style.overflow = IStyle.OverflowEnum.hidden;

            Native.body.Clear();
            (Native.body.style as dynamic).webkitUserSelect = "text";





            //return;

            // Earth params
            //var radius = 0.5;
            //var radius = 1024;
            //var radius = 2048;
            //var radius = 512;
            //var radius = 256;
            //var radius = 400;

            // can we have not fly beyond moon too much?
            //var radius = 500;
            var radius = 480;

            //var segments = 32;
            var segments = 128 * 2;
            //var rotation = 6;


            //const int size = 128;
            //const int size = 256; // 6 faces, 12KB
            //const int size = 512; // 6 faces, ?

            // WebGL: drawArrays: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'. Or the texture is Float or Half Float type with linear filtering while OES_float_linear or OES_half_float_linear extension is not enabled.

            //const int size = 720; // 6 faces, ?
            //const int size = 1024; // 6 faces, ?
            //const int cubefacesize = 1024; // 6 faces, ?

            // THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter is set to THREE.LinearFilter or THREE.NearestFilter. ( chrome-extension://aemlnmcokphbneegoefdckonejmknohh/assets/x360mountains/anvil___spherical_hdri_panorama_skybox_by_macsix_d6vv4hs.jpg )


            var far = 0xffffff;

            new IHTMLPre { new { Environment.ProcessorCount, cubefacesize } }.AttachToDocument();

            //new IHTMLPre { "can we stream it into VR, shadertoy, youtube 360, youtube stereo yet?" }.AttachToDocument();


            var sw = Stopwatch.StartNew();



            var oo = new List<THREE.Object3D>();

            var window = Native.window;


            // what about physics and that portal rendering?

            // if we are running as a chrome web server, we may also be opened as android ndk webview app
            //var cameraPX = new THREE.PerspectiveCamera(fov: 90, aspect: window.aspect, near: 1, far: 2000);
            // once we update source
            // save the source
            // manually recompile 
            //cameraPX.position.z = 400;

            //// the camera should be close enough for the object to float off the FOV of PX
            //cameraPX.position.z = 200;

            // scene
            // can we make the 3D object orbit around us ?
            // and
            // stream it to vr?
            var scene = new THREE.Scene();



            // since our cube camera is somewhat a fixed thing
            // would it be easier to move mountains to come to us?
            // once we change code would chrome app be able to let VR know that a new view is available?
            var sceneg = new THREE.Group();
            sceneg.AttachTo(scene);


            // fly up?
            //sceneg.translateZ(-1024);
            // rotate the world, as the skybox then matches what we have on filesystem
            scene.rotateOnAxis(new THREE.Vector3(0, 1, 0), -Math.PI / 2);
            // yet for headtracking we shall rotate camera


            //sceneg.position.set(0, 0, -1024);
            //sceneg.position.set(0, -1024, 0);

            //scene.add(new THREE.AmbientLight(0x333333));
            //scene.add(new THREE.AmbientLight(0xffffff));
            //scene.add(new THREE.AmbientLight(0xaaaaaa));
            //scene.add(new THREE.AmbientLight(0xcccccc));
            //scene.add(new THREE.AmbientLight(0xeeeeee));
            scene.add(new THREE.AmbientLight(0xffffff));




            //var light = new THREE.DirectionalLight(0xffffff, 1);
            //// sun should be beyond moon
            ////light.position.set(-5 * virtualDistance, -3 * virtualDistance, -5 * virtualDistance);
            ////light.position.set(-15 * virtualDistance, -1 * virtualDistance, -15 * virtualDistance);

            //// where shall the light source be to see half planet?
            //light.position.set(-1 * virtualDistance, -1 * virtualDistance, -15 * virtualDistance);
            //scene.add(light);



            //var lightX = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -60, max = 60, valueAsNumber = 0, title = "lightX" }.AttachToDocument();
            //var lightY = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -60, max = 60, valueAsNumber = 0, title = "lightY" }.AttachToDocument();
            //var lightZ = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -60, max = 60, valueAsNumber = 0, title = "lightZ" }.AttachToDocument();

            //new IHTMLHorizontalRule { }.AttachToDocument();

            // whats WebGLRenderTargetCube do?

            // WebGLRenderer preserveDrawingBuffer 



            var renderer0 = new THREE.WebGLRenderer(

                new
                {
                    //antialias = true,
                    //alpha = true,
                    preserveDrawingBuffer = true
                }
            );

            // https://github.com/mrdoob/three.js/issues/3836

            // the construct. white bg
            //renderer0.setClearColor(0xfffff, 1);
            renderer0.setClearColor(0x0, 1);

            //renderer.setSize(window.Width, window.Height);
            renderer0.setSize(cubefacesize, cubefacesize);

            //renderer0.domElement.AttachToDocument();
            //rendererPX.domElement.style.SetLocation(0, 0);
            //renderer0.domElement.style.SetLocation(4, 4);


            // top

            // http://stackoverflow.com/questions/27612524/can-multiple-webglrenderers-render-the-same-scene


            // need a place to show the cubemap face to GUI 
            // how does the stereo OTOY do it?
            // https://www.opengl.org/wiki/Sampler_(GLSL)

            // http://www.richardssoftware.net/Home/Post/25

            // [+X, –X, +Y, –Y, +Z, –Z] fa



            // move up
            //camera.position.set(-1200, 800, 1200);
            //var cameraoffset = new THREE.Vector3(0, 15, 0);

            // can we aniamte it?
            //var cameraoffset = new THREE.Vector3(0, 800, 1200);
            // can we have linear animation fromcenter of the map to the edge and back?
            // then do the flat earth sun orbit?
            var cameraoffset = new THREE.Vector3(
                // left?
                -512,
                // height?
                //0,
                //1600,
                //1024,

                // if the camera is in the center, would we need to move the scene?
                // we have to move the camera. as we move the scene the lights are messed up
                //2014,
                1024,

                //1200
                0
                // can we hover top of the map?
                );

            // original vieworigin
            //var cameraoffset = new THREE.Vector3(-1200, 800, 1200);













            var bottomRotate100 = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = -314, max = 314, valueAsNumber = 0, title = "bottomRotate" }.AttachToDocument();


            var maxfps = 60;
            //var maxlengthseconds = 60;
            var maxlengthseconds = 120;

            var maxframes = maxlengthseconds * maxfps;

            // whatif we want more than 30sec video? 2min animation? more frames to render? 2gb disk?
            var frameIDslider = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = 0, max = maxframes, valueAsNumber = 137, title = "frameIDslider" }.AttachToDocument();
            frameIDslider.onchange += delegate { frameIDslider.title = "frameIDslider " + frameIDslider.valueAsNumber; };




            //var vs0 = new ChromeShaderToyRelentlessBySrtuss.Shaders.ProgramFragmentShader();
            //var vs0 = new TraceConeWithCRTByKlk.Shaders.ProgramFragmentShader();








            // left
            IHTMLCanvas shader0canvasPZ = null;

            // locCameraTargetOffset to look left?
            #region shader0canvasPZ
            new { }.With(
              async delegate
              {
                  //return;

                  Native.body.style.margin = "0px";
                  (Native.body.style as dynamic).webkitUserSelect = "auto";

                  // https://sites.google.com/a/jsc-solutions.net/work/x3
                  //var vs0 = new ChromeShaderToyColumns.Shaders.ProgramFragmentShader();
                  //var vs0 = new x2001SpaceStationByOtavio.Shaders.ProgramFragmentShader();
                  //var vs0 = new Xor3DAlienLandByXor.Shaders.ProgramFragmentShader();
                  //var vs0 = new RoomScanningEffectByRosme.Shaders.ProgramFragmentShader();
                  // now we have an empty shell
                  // which tostrings to the glsl code for gpu
                  // and if we were to initialize 



                  // enable intellisense
                  //var vs0i = (RoomScanningEffectByRosme.Shaders.__ProgramFragmentUniforms)(object)vs0;


                  // script: error JSC1000: No implementation found for this native method, please implement [static ScriptCoreLib.GLSL.Shader.vec3(System.Single, System.Single, System.Single)]

                  //     b.__this._vs0i_5__2.uCameraTargetOffset = new ctor$aQ8ABjj5gzW_aEh4Cmq2oMg(1, 0, 0);

                  // 270ms ReferenceError: ctor$aQ8ABjj5gzW_aEh4Cmq2oMg is not defined

                  // wishful thinking eh
                  //vec3 uCameraTargetOffset = vec3(0.0f, 0.0f, -1.0f);
                  //vs0i.uCameraTargetOffset = new ScriptCoreLib.GLSL.vec3(1.0f, 0.0f, 0.0f);
                  // this would mean the program was selected and uniform was uploaded to gpu




                  var gl0 = new WebGLRenderingContext(alpha: true);
                  shader0canvasPZ = gl0.canvas;

                  var c0 = gl0.canvas.AttachToDocument();

                  //c0.style.SetSize(460, 237);
                  //c0.width = 460;
                  //c0.height = 237;

                  //c0.style.SetSize((int)uizoom * 3, (int)uizoom * 3);
                  c0.style.SetSize(128, 128);
                  c0.width = cubefacesize;
                  c0.height = cubefacesize;

                  //c0.style.SetLocation(720, 8);
                  c0.style.SetLocation(800, 360);

                  var mMouseOriX = 0;
                  var mMouseOriY = 0;
                  var mMousePosX = 0;
                  var mMousePosY = 0;


                  var pass0 = new ChromeShaderToyColumns.Library.ShaderToy.EffectPass(
                    null,
                    gl0,
                    precission: ChromeShaderToyColumns.Library.ShaderToy.DetermineShaderPrecission(gl0),
                    supportDerivatives: gl0.getExtension("OES_standard_derivatives") != null,
                    callback: null,
                    obj: null,
                    forceMuted: false,
                    forcePaused: false,
                    //quadVBO: Library.ShaderToy.createQuadVBO(gl, right: 0, top: 0),
                    outputGainNode: null
                );
                  pass0.MakeHeader_Image();
                  pass0.NewShader_Image(vs0);

                  var sw0 = Stopwatch.StartNew();

                  pass0.ProgramSelected += mProgram =>
                  {
                      // ldflda?
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, -1.0f, 0, 0.0f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0.0f, 0, 1.0f);
                      var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0.0f, 0, -1.0f);

                      // left?
                      //forward=normalize(float3(0.0 , 0.0 ,1.0));
                  };


                  Native.window.onframe += delegate
                  {
                      // let render man know..
                      if (vsyncReady())
                          return;

                      // 1800 is 30sec is 30 000
                      // frameIDslider?

                      //var fps60 = frameIDslider * 1000 / 60.0f;
                      var fps60 = frameIDslider * (1 / 60.0f);

                      pass0.Paint_Image(
                        fps60,

                        mMouseOriX,
                        mMouseOriY,
                        mMousePosX,
                        mMousePosY
                    //,

                    // gl_FragCoord
                    // cannot be scaled, and can be referenced directly.
                    // need another way to scale
                    //zoom: 0.3f
                    );

                      // what does it do?
                      // need redux build..
                      gl0.flush();

                      //await u.animate.async.@checked;
                  };



              }
          );
            #endregion





            // front
            IHTMLCanvas shader1canvasPX = null;

            #region shader1canvasPX
            new { }.With(
              async delegate
              {
                  Native.body.style.margin = "0px";
                  (Native.body.style as dynamic).webkitUserSelect = "auto";

                  // https://sites.google.com/a/jsc-solutions.net/work/x3
                  //var vs0 = new ChromeShaderToyColumns.Shaders.ProgramFragmentShader();
                  //var vs0 = new x2001SpaceStationByOtavio.Shaders.ProgramFragmentShader();
                  //var vs0 = new RoomScanningEffectByRosme.Shaders.ProgramFragmentShader();

                  var gl0 = new WebGLRenderingContext(alpha: true);
                  shader1canvasPX = gl0.canvas;

                  var c0 = gl0.canvas.AttachToDocument();

                  //c0.style.SetSize(460, 237);
                  //c0.width = 460;
                  //c0.height = 237;

                  //c0.style.SetSize((int)uizoom * 3, (int)uizoom * 3);
                  c0.style.SetSize(128, 128);
                  c0.width = cubefacesize;
                  c0.height = cubefacesize;

                  c0.style.SetLocation(720, 8);

                  var mMouseOriX = 0;
                  var mMouseOriY = 0;
                  var mMousePosX = 0;
                  var mMousePosY = 0;


                  var pass0 = new ChromeShaderToyColumns.Library.ShaderToy.EffectPass(
                    null,
                    gl0,
                    precission: ChromeShaderToyColumns.Library.ShaderToy.DetermineShaderPrecission(gl0),
                    supportDerivatives: gl0.getExtension("OES_standard_derivatives") != null,
                    callback: null,
                    obj: null,
                    forceMuted: false,
                    forcePaused: false,
                    //quadVBO: Library.ShaderToy.createQuadVBO(gl, right: 0, top: 0),
                    outputGainNode: null
                );
                  pass0.MakeHeader_Image();
                  pass0.NewShader_Image(vs0);


                  pass0.ProgramSelected += mProgram =>
                  {
                      // off by 45deg__

                      // ldflda?
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0.0f, 0, -1.0f);

                      // fixup
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 1.0f, 0, -1.0f);
                      var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 1.0f, 0, 0.0f);


                      // front
                      //forward=normalize(float3(1.0 , 0.0 ,0.0));
                  };

                  var sw0 = Stopwatch.StartNew();

                  Native.window.onframe += delegate
                  {
                      // let render man know..
                      // let render man know..
                      if (vsyncReady())
                          return;

                      // 1800 is 30sec is 30 000
                      // frameIDslider?

                      //var fps60 = frameIDslider * 1000 / 60.0f;
                      var fps60 = frameIDslider * (1 / 60.0f);

                      pass0.Paint_Image(
                        fps60,

                        mMouseOriX,
                        mMouseOriY,
                        mMousePosX,
                        mMousePosY
                    //,

                    // gl_FragCoord
                    // cannot be scaled, and can be referenced directly.
                    // need another way to scale
                    //zoom: 0.3f
                    );

                      // what does it do?
                      // need redux build..
                      gl0.flush();

                      //await u.animate.async.@checked;
                  };

              }
          );
            #endregion



            // back
            IHTMLCanvas shader1canvasNX = null;

            #region shader1canvasNX
            new { }.With(
              async delegate
              {
                  Native.body.style.margin = "0px";
                  (Native.body.style as dynamic).webkitUserSelect = "auto";

                  // https://sites.google.com/a/jsc-solutions.net/work/x3
                  //var vs0 = new ChromeShaderToyColumns.Shaders.ProgramFragmentShader();
                  //var vs0 = new x2001SpaceStationByOtavio.Shaders.ProgramFragmentShader();
                  //var vs0 = new RoomScanningEffectByRosme.Shaders.ProgramFragmentShader();

                  var gl0 = new WebGLRenderingContext(alpha: true);
                  shader1canvasNX = gl0.canvas;

                  var c0 = gl0.canvas.AttachToDocument();

                  //c0.style.SetSize(460, 237);
                  //c0.width = 460;
                  //c0.height = 237;

                  //c0.style.SetSize((int)uizoom * 3, (int)uizoom * 3);
                  c0.style.SetSize(128, 128);
                  c0.width = cubefacesize;
                  c0.height = cubefacesize;

                  c0.style.SetLocation(720, 8);

                  var mMouseOriX = 0;
                  var mMouseOriY = 0;
                  var mMousePosX = 0;
                  var mMousePosY = 0;


                  var pass0 = new ChromeShaderToyColumns.Library.ShaderToy.EffectPass(
                    null,
                    gl0,
                    precission: ChromeShaderToyColumns.Library.ShaderToy.DetermineShaderPrecission(gl0),
                    supportDerivatives: gl0.getExtension("OES_standard_derivatives") != null,
                    callback: null,
                    obj: null,
                    forceMuted: false,
                    forcePaused: false,
                    //quadVBO: Library.ShaderToy.createQuadVBO(gl, right: 0, top: 0),
                    outputGainNode: null
                );
                  pass0.MakeHeader_Image();
                  pass0.NewShader_Image(vs0);


                  pass0.ProgramSelected += mProgram =>
                  {
                      // ldflda?
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, 0, 1.0f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, -1.0f, 0, 1.0f);
                      var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, -1.0f, 0, 0.0f);

                      // back
                      //forward=normalize(float3(-1.0 , 0.0 ,0.0));

                  };

                  var sw0 = Stopwatch.StartNew();

                  Native.window.onframe += delegate
                  {
                      // let render man know..
                      // let render man know..
                      if (vsyncReady())
                          return;

                      // 1800 is 30sec is 30 000
                      // frameIDslider?

                      //var fps60 = frameIDslider * 1000 / 60.0f;
                      var fps60 = frameIDslider * (1 / 60.0f);

                      pass0.Paint_Image(
                        fps60,

                        mMouseOriX,
                        mMouseOriY,
                        mMousePosX,
                        mMousePosY
                    //,

                    // gl_FragCoord
                    // cannot be scaled, and can be referenced directly.
                    // need another way to scale
                    //zoom: 0.3f
                    );

                      // what does it do?
                      // need redux build..
                      gl0.flush();

                      //await u.animate.async.@checked;
                  };

              }
          );
            #endregion






            // right
            IHTMLCanvas shader2canvasNZ = null;

            // locCameraTargetOffset to look right?
            #region shader2canvasNZ
            new { }.With(
              async delegate
              {
                  //return;

                  Native.body.style.margin = "0px";
                  (Native.body.style as dynamic).webkitUserSelect = "auto";

                  // https://sites.google.com/a/jsc-solutions.net/work/x3
                  //var vs0 = new ChromeShaderToyColumns.Shaders.ProgramFragmentShader();
                  //var vs0 = new x2001SpaceStationByOtavio.Shaders.ProgramFragmentShader();
                  //var vs0 = new Xor3DAlienLandByXor.Shaders.ProgramFragmentShader();
                  //var vs0 = new RoomScanningEffectByRosme.Shaders.ProgramFragmentShader();
                  // now we have an empty shell
                  // which tostrings to the glsl code for gpu
                  // and if we were to initialize 



                  // enable intellisense
                  //var vs0i = (RoomScanningEffectByRosme.Shaders.__ProgramFragmentUniforms)(object)vs0;


                  // script: error JSC1000: No implementation found for this native method, please implement [static ScriptCoreLib.GLSL.Shader.vec3(System.Single, System.Single, System.Single)]

                  //     b.__this._vs0i_5__2.uCameraTargetOffset = new ctor$aQ8ABjj5gzW_aEh4Cmq2oMg(1, 0, 0);

                  // 270ms ReferenceError: ctor$aQ8ABjj5gzW_aEh4Cmq2oMg is not defined

                  // wishful thinking eh
                  //vec3 uCameraTargetOffset = vec3(0.0f, 0.0f, -1.0f);
                  //vs0i.uCameraTargetOffset = new ScriptCoreLib.GLSL.vec3(1.0f, 0.0f, 0.0f);
                  // this would mean the program was selected and uniform was uploaded to gpu




                  var gl0 = new WebGLRenderingContext(alpha: true);
                  shader2canvasNZ = gl0.canvas;

                  var c0 = gl0.canvas.AttachToDocument();

                  //c0.style.SetSize(460, 237);
                  //c0.width = 460;
                  //c0.height = 237;

                  //c0.style.SetSize((int)uizoom * 3, (int)uizoom * 3);
                  c0.style.SetSize(128, 128);
                  c0.width = cubefacesize;
                  c0.height = cubefacesize;

                  //c0.style.SetLocation(720, 8);
                  c0.style.SetLocation(800, 360);

                  var mMouseOriX = 0;
                  var mMouseOriY = 0;
                  var mMousePosX = 0;
                  var mMousePosY = 0;


                  var pass0 = new ChromeShaderToyColumns.Library.ShaderToy.EffectPass(
                    null,
                    gl0,
                    precission: ChromeShaderToyColumns.Library.ShaderToy.DetermineShaderPrecission(gl0),
                    supportDerivatives: gl0.getExtension("OES_standard_derivatives") != null,
                    callback: null,
                    obj: null,
                    forceMuted: false,
                    forcePaused: false,
                    //quadVBO: Library.ShaderToy.createQuadVBO(gl, right: 0, top: 0),
                    outputGainNode: null
                );
                  pass0.MakeHeader_Image();
                  pass0.NewShader_Image(vs0);

                  var sw0 = Stopwatch.StartNew();

                  pass0.ProgramSelected += mProgram =>
                  {
                      // ldflda?
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 1.0f, 0, 1.0f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0.0f, 0, -1.0f);
                      var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0.0f, 0, 1.0f);

                      // right
                      //forward=normalize(float3(0.0 , 0.0 ,-1.0));

                  };

                  Native.window.onframe += delegate
                  {
                      // let render man know..
                      // let render man know..
                      if (vsyncReady())
                          return;
                      // 1800 is 30sec is 30 000
                      // frameIDslider?

                      //var fps60 = frameIDslider * 1000 / 60.0f;
                      var fps60 = frameIDslider * (1 / 60.0f);

                      pass0.Paint_Image(
                        fps60,

                        mMouseOriX,
                        mMouseOriY,
                        mMousePosX,
                        mMousePosY
                    //,

                    // gl_FragCoord
                    // cannot be scaled, and can be referenced directly.
                    // need another way to scale
                    //zoom: 0.3f
                    );

                      // what does it do?
                      // need redux build..
                      gl0.flush();

                      //await u.animate.async.@checked;
                  };

              }
          );
            #endregion












            // bottom
            IHTMLCanvas shader2canvasNY = null;

            // locCameraTargetOffset to look bottom?
            #region shader2canvasNY
            new { }.With(
              async delegate
              {
                  //return;

                  Native.body.style.margin = "0px";
                  (Native.body.style as dynamic).webkitUserSelect = "auto";

                  // https://sites.google.com/a/jsc-solutions.net/work/x3
                  //var vs0 = new ChromeShaderToyColumns.Shaders.ProgramFragmentShader();
                  //var vs0 = new x2001SpaceStationByOtavio.Shaders.ProgramFragmentShader();
                  //var vs0 = new Xor3DAlienLandByXor.Shaders.ProgramFragmentShader();
                  //var vs0 = new RoomScanningEffectByRosme.Shaders.ProgramFragmentShader();
                  // now we have an empty shell
                  // which tostrings to the glsl code for gpu
                  // and if we were to initialize 



                  // enable intellisense
                  //var vs0i = (RoomScanningEffectByRosme.Shaders.__ProgramFragmentUniforms)(object)vs0;


                  // script: error JSC1000: No implementation found for this native method, please implement [static ScriptCoreLib.GLSL.Shader.vec3(System.Single, System.Single, System.Single)]

                  //     b.__this._vs0i_5__2.uCameraTargetOffset = new ctor$aQ8ABjj5gzW_aEh4Cmq2oMg(1, 0, 0);

                  // 270ms ReferenceError: ctor$aQ8ABjj5gzW_aEh4Cmq2oMg is not defined

                  // wishful thinking eh
                  //vec3 uCameraTargetOffset = vec3(0.0f, 0.0f, -1.0f);
                  //vs0i.uCameraTargetOffset = new ScriptCoreLib.GLSL.vec3(1.0f, 0.0f, 0.0f);
                  // this would mean the program was selected and uniform was uploaded to gpu




                  var gl0 = new WebGLRenderingContext(alpha: true);
                  shader2canvasNY = gl0.canvas;

                  var c0 = gl0.canvas.AttachToDocument();

                  //c0.style.SetSize(460, 237);
                  //c0.width = 460;
                  //c0.height = 237;

                  //c0.style.SetSize((int)uizoom * 3, (int)uizoom * 3);
                  c0.style.SetSize(128, 128);
                  c0.width = cubefacesize;
                  c0.height = cubefacesize;

                  //c0.style.SetLocation(720, 8);
                  c0.style.SetLocation(800, 360);

                  var mMouseOriX = 0;
                  var mMouseOriY = 0;
                  var mMousePosX = 0;
                  var mMousePosY = 0;


                  var pass0 = new ChromeShaderToyColumns.Library.ShaderToy.EffectPass(
                    null,
                    gl0,
                    precission: ChromeShaderToyColumns.Library.ShaderToy.DetermineShaderPrecission(gl0),
                    supportDerivatives: gl0.getExtension("OES_standard_derivatives") != null,
                    callback: null,
                    obj: null,
                    forceMuted: false,
                    forcePaused: false,
                    //quadVBO: Library.ShaderToy.createQuadVBO(gl, right: 0, top: 0),
                    outputGainNode: null
                );
                  pass0.MakeHeader_Image();
                  pass0.NewShader_Image(vs0);

                  var sw0 = Stopwatch.StartNew();

                  pass0.ProgramSelected += mProgram =>
                  {
                      // ldflda?

                      // 45deg off??


                      // front
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, 0, -1.0f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, -.0001f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, .1f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, 0f);

                      // left
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, -1.0f, 0, 0);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, -.0001f, -1, 0);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, -1f, -1, 0);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, 0);

                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0.01f, -1, 0.01f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0.001f, -1, 0f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, -0.0001f);
                      var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, 1, -0.0001f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, .0001f, -1, 0);

                  };

                  Native.window.onframe += delegate
                  {
                      // let render man know..
                      // let render man know..
                      if (vsyncReady())
                          return;

                      // 1800 is 30sec is 30 000
                      // frameIDslider?

                      //var fps60 = frameIDslider * 1000 / 60.0f;
                      var fps60 = frameIDslider * (1 / 60.0f);

                      pass0.Paint_Image(
                        fps60,

                        mMouseOriX,
                        mMouseOriY,
                        mMousePosX,
                        mMousePosY
                    //,

                    // gl_FragCoord
                    // cannot be scaled, and can be referenced directly.
                    // need another way to scale
                    //zoom: 0.3f
                    );

                      // what does it do?
                      // need redux build..
                      gl0.flush();

                      //await u.animate.async.@checked;
                  };

              }
          );
            #endregion











            // top
            IHTMLCanvas shader2canvasPY = null;

            // locCameraTargetOffset to look right?
            #region shader2canvasPY
            new { }.With(
              async delegate
              {
                  //return;

                  Native.body.style.margin = "0px";
                  (Native.body.style as dynamic).webkitUserSelect = "auto";

                  // https://sites.google.com/a/jsc-solutions.net/work/x3
                  //var vs0 = new ChromeShaderToyColumns.Shaders.ProgramFragmentShader();
                  //var vs0 = new x2001SpaceStationByOtavio.Shaders.ProgramFragmentShader();
                  //var vs0 = new Xor3DAlienLandByXor.Shaders.ProgramFragmentShader();
                  //var vs0 = new RoomScanningEffectByRosme.Shaders.ProgramFragmentShader();
                  // now we have an empty shell
                  // which tostrings to the glsl code for gpu
                  // and if we were to initialize 



                  // enable intellisense
                  //var vs0i = (RoomScanningEffectByRosme.Shaders.__ProgramFragmentUniforms)(object)vs0;


                  // script: error JSC1000: No implementation found for this native method, please implement [static ScriptCoreLib.GLSL.Shader.vec3(System.Single, System.Single, System.Single)]

                  //     b.__this._vs0i_5__2.uCameraTargetOffset = new ctor$aQ8ABjj5gzW_aEh4Cmq2oMg(1, 0, 0);

                  // 270ms ReferenceError: ctor$aQ8ABjj5gzW_aEh4Cmq2oMg is not defined

                  // wishful thinking eh
                  //vec3 uCameraTargetOffset = vec3(0.0f, 0.0f, -1.0f);
                  //vs0i.uCameraTargetOffset = new ScriptCoreLib.GLSL.vec3(1.0f, 0.0f, 0.0f);
                  // this would mean the program was selected and uniform was uploaded to gpu




                  var gl0 = new WebGLRenderingContext(alpha: true);
                  shader2canvasPY = gl0.canvas;

                  var c0 = gl0.canvas.AttachToDocument();

                  //c0.style.SetSize(460, 237);
                  //c0.width = 460;
                  //c0.height = 237;

                  //c0.style.SetSize((int)uizoom * 3, (int)uizoom * 3);
                  c0.style.SetSize(128, 128);
                  c0.width = cubefacesize;
                  c0.height = cubefacesize;

                  //c0.style.SetLocation(720, 8);
                  c0.style.SetLocation(800, 360);

                  var mMouseOriX = 0;
                  var mMouseOriY = 0;
                  var mMousePosX = 0;
                  var mMousePosY = 0;


                  var pass0 = new ChromeShaderToyColumns.Library.ShaderToy.EffectPass(
                    null,
                    gl0,
                    precission: ChromeShaderToyColumns.Library.ShaderToy.DetermineShaderPrecission(gl0),
                    supportDerivatives: gl0.getExtension("OES_standard_derivatives") != null,
                    callback: null,
                    obj: null,
                    forceMuted: false,
                    forcePaused: false,
                    //quadVBO: Library.ShaderToy.createQuadVBO(gl, right: 0, top: 0),
                    outputGainNode: null
                );
                  pass0.MakeHeader_Image();
                  pass0.NewShader_Image(vs0);

                  var sw0 = Stopwatch.StartNew();

                  pass0.ProgramSelected += mProgram =>
                  {
                      // ldflda?

                      // 45deg off??


                      // front
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, 0, -1.0f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, -.0001f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, .1f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, 0f);

                      // left
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, -1.0f, 0, 0);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, -.0001f, -1, 0);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, -1f, -1, 0);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, 0);

                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0.01f, -1, 0.01f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0.001f, 1, 0f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, 1, -0.0001f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, -0.0001f);
                      var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, 0, -1, 0.0001f);
                      //var l3 = gl0.getUniformLocation(mProgram, "uCameraTargetOffset"); if (l3 != null) gl0.uniform3f(l3, .0001f, -1, 0);

                  };

                  Native.window.onframe += delegate
                  {
                      //d = a[0].CS___8__locals1.vsync != null;
                      //e = a[0].CS___8__locals1.vsync.kAcABp_b1ITCbIktNs3el5Q().dgQABqwxMjO1zVAJb5WXKA();


                      // let render man know..
                      // let render man know..
                      if (vsyncReady())
                          return;

                      // 1800 is 30sec is 30 000
                      // frameIDslider?

                      //var fps60 = frameIDslider * 1000 / 60.0f;
                      var fps60 = frameIDslider * (1 / 60.0f);

                      pass0.Paint_Image(
                        fps60,

                        mMouseOriX,
                        mMouseOriY,
                        mMousePosX,
                        mMousePosY
                    //,

                    // gl_FragCoord
                    // cannot be scaled, and can be referenced directly.
                    // need another way to scale
                    //zoom: 0.3f
                    );

                      // what does it do?
                      // need redux build..
                      gl0.flush();

                      //await u.animate.async.@checked;
                  };

              }
          );
            #endregion






            new IHTMLHorizontalRule { }.AttachToDocument();

            var camerax = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = 0 - 2048 * 4, max = 0 + 2048 * 4, valueAsNumber = 0, title = "camerax" }.AttachToDocument();
            // up. whats the most high a rocket can go 120km?
            new IHTMLHorizontalRule { }.AttachToDocument();


            // how high is the bunker?
            var cameray = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = 0 - 2048 * 4, max = 2048 * 4, valueAsNumber = 0, title = "cameray" }.AttachToDocument();
            new IHTMLBreak { }.AttachToDocument();
            var camerayHigh = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = cameray.max, max = 1024 * 256, valueAsNumber = cameray.max, title = "cameray" }.AttachToDocument();
            new IHTMLHorizontalRule { }.AttachToDocument();
            var cameraz = new IHTMLInput { type = ScriptCoreLib.Shared.HTMLInputTypeEnum.range, min = 0 - 2048 * 4, max = 0 + 2048 * 4, valueAsNumber = 0, title = "cameraz" }.AttachToDocument();

            // for render server
            var fcamerax = 0.0;
            var fcameray = 0.0;
            var fcameraz = 0.0;

            //while (await camerax.async.onchange)

            //cameray.onchange += delegate
            //{
            //    if (cameray.valueAsNumber < cameray.max)
            //        camerayHigh.valueAsNumber = camerayHigh.min;
            //};

            camerayHigh.onmousedown += delegate
            {
                //if (camerayHigh.valueAsNumber > camerayHigh.min)
                cameray.valueAsNumber = cameray.max;
            };


            Action applycameraoffset = delegate
            {
                // make sure UI and gpu sync up

                var cy = cameray;

                if (cameray.valueAsNumber < cameray.max)
                    camerayHigh.valueAsNumber = camerayHigh.min;

                if (camerayHigh.valueAsNumber > camerayHigh.min)
                    cameray.valueAsNumber = cameray.max;

                if (cameray.valueAsNumber == cameray.max)
                    cy = camerayHigh;



                cameraoffset = new THREE.Vector3(
                  // left?
                  1.0 * (camerax + fcamerax),
                   // height?
                   //0,
                   //1600,
                   //1024,

                   // if the camera is in the center, would we need to move the scene?
                   // we have to move the camera. as we move the scene the lights are messed up
                   //2014,
                   1.0 * (cy + fcameray),

                 //1200
                 1.0 * (cameraz + fcameraz)
                   // can we hover top of the map?
                   );
            };


            #region y
            // need to rotate90?
            var cameraNY = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            applycameraoffset += delegate
            {
                cameraNY.position.copy(new THREE.Vector3(0, 0, 0));
                cameraNY.lookAt(new THREE.Vector3(0, -1, 0));
                cameraNY.position.add(cameraoffset);
            };

            //cameraNY.lookAt(new THREE.Vector3(0, 1, 0));
            var canvasNY = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasNY.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 1, 8 + (int)(uizoom * cubefacesize + 8) * 2);
            canvasNY.canvas.title = "NY";
            canvasNY.canvas.AttachToDocument();
            canvasNY.canvas.style.transformOrigin = "0 0";
            // roslyn!
            canvasNY.canvas.style.transform = $"scale({uizoom})";

            var cameraPY = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            applycameraoffset += delegate
            {
                cameraPY.position.copy(new THREE.Vector3(0, 0, 0));
                cameraPY.lookAt(new THREE.Vector3(0, 1, 0));
                cameraPY.position.add(cameraoffset);
            };
            //cameraPY.lookAt(new THREE.Vector3(0, -1, 0));
            var canvasPY = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPY.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 1, 8 + (int)(uizoom * cubefacesize + 8) * 0);
            canvasPY.canvas.title = "PY";
            canvasPY.canvas.AttachToDocument();
            canvasPY.canvas.style.transformOrigin = "0 0";
            canvasPY.canvas.style.transform = $"scale({uizoom})";
            #endregion

            // transpose xz?

            #region x
            var cameraNX = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            applycameraoffset += delegate
            {
                cameraNX.position.copy(new THREE.Vector3(0, 0, 0));
                cameraNX.lookAt(new THREE.Vector3(0, 0, 1));
                cameraNX.position.add(cameraoffset);
            };
            //cameraNX.lookAt(new THREE.Vector3(0, 0, -1));
            //cameraNX.lookAt(new THREE.Vector3(-1, 0, 0));
            //cameraNX.lookAt(new THREE.Vector3(1, 0, 0));
            var canvasNX = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasNX.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 2, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasNX.canvas.title = "NX";
            canvasNX.canvas.AttachToDocument();
            canvasNX.canvas.style.transformOrigin = "0 0";
            canvasNX.canvas.style.transform = $"scale({uizoom})";

            var cameraPX = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            applycameraoffset += delegate
            {
                cameraPX.position.copy(new THREE.Vector3(0, 0, 0));
                cameraPX.lookAt(new THREE.Vector3(0, 0, -1));
                cameraPX.position.add(cameraoffset);
            };
            //cameraPX.lookAt(new THREE.Vector3(0, 0, 1));
            //cameraPX.lookAt(new THREE.Vector3(1, 0, 0));
            //cameraPX.lookAt(new THREE.Vector3(-1, 0, 0));
            var canvasPX = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPX.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 0, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasPX.canvas.title = "PX";
            canvasPX.canvas.AttachToDocument();
            canvasPX.canvas.style.transformOrigin = "0 0";
            canvasPX.canvas.style.transform = $"scale({uizoom})";
            #endregion



            #region z
            var cameraNZ = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            //cameraNZ.lookAt(new THREE.Vector3(0, 0, -1));
            applycameraoffset += delegate
            {
                cameraNZ.position.copy(new THREE.Vector3(0, 0, 0));
                cameraNZ.lookAt(new THREE.Vector3(1, 0, 0));
                cameraNZ.position.add(cameraoffset);
            };
            //cameraNX.lookAt(new THREE.Vector3(-1, 0, 0));
            //cameraNZ.lookAt(new THREE.Vector3(0, 0, 1));
            var canvasNZ = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasNZ.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 3, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasNZ.canvas.title = "NZ";
            canvasNZ.canvas.AttachToDocument();
            canvasNZ.canvas.style.transformOrigin = "0 0";
            canvasNZ.canvas.style.transform = $"scale({uizoom})";

            var cameraPZ = new THREE.PerspectiveCamera(fov: 90, aspect: 1.0, near: 1, far: far);
            //cameraPZ.lookAt(new THREE.Vector3(1, 0, 0));
            applycameraoffset += delegate
            {
                cameraPZ.position.copy(new THREE.Vector3(0, 0, 0));
                cameraPZ.lookAt(new THREE.Vector3(-1, 0, 0));
                cameraPZ.position.add(cameraoffset);
            };
            //cameraPZ.lookAt(new THREE.Vector3(0, 0, 1));
            //cameraPZ.lookAt(new THREE.Vector3(0, 0, -1));
            var canvasPZ = new CanvasRenderingContext2D(cubefacesize, cubefacesize);
            canvasPZ.canvas.style.SetLocation(cubecameraoffsetx + (int)(uizoom * cubefacesize + 8) * 1, 8 + (int)(uizoom * cubefacesize + 8) * 1);
            canvasPZ.canvas.title = "PZ";
            canvasPZ.canvas.AttachToDocument();
            canvasPZ.canvas.style.transformOrigin = "0 0";
            canvasPZ.canvas.style.transform = $"scale({uizoom})";
            #endregion




            // c++ alias locals would be nice..
            var canvas0 = (IHTMLCanvas)renderer0.domElement;


            var old = new
            {



                CursorX = 0,
                CursorY = 0
            };


            var st = new Stopwatch();
            st.Start();

            //canvas0.css.active.style.cursor = IStyle.CursorEnum.move;




            // X:\jsc.svn\examples\javascript\Test\TestMouseMovement\TestMouseMovement\Application.cs


            // THREE.WebGLProgram: gl.getProgramInfoLog() C:\fakepath(78,3-98): warning X3557: loop only executes for 1 iteration(s), forcing loop to unroll
            // THREE.WebGLProgram: gl.getProgramInfoLog() (79,3-98): warning X3557: loop only executes for 1 iteration(s), forcing loop to unroll

            // http://www.roadtovr.com/youtube-confirms-stereo-3d-360-video-support-coming-soon/
            // https://www.youtube.com/watch?v=D-Wl9jAB45Q



            #region spherical
            var gl = new WebGLRenderingContext(alpha: true, preserveDrawingBuffer: true);
            var c = gl.canvas.AttachToDocument();

            //  3840x2160

            //c.style.SetSize(3840, 2160);

            // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150722/360-youtube


            c.width = 3840;
            c.height = 2160;


            //c.width = 3840 * 2;
            //c.height = 2160 * 2;


            //c.width = 3840;
            //c.height = 2160;
            // 1,777777777777778

            // https://www.youtube.com/watch?v=fTfJwzRsE-w
            //c.width = 7580;
            //c.height = 3840;
            //1,973958333333333

            //7580
            //    3840

            // wont work
            //c.width = 8192;
            //c.height = 4096;


            // this has the wrong aspect?
            //c.width = 6466;
            //c.height = 3232;

            new IHTMLPre { new { c.width, c.height } }.AttachToDocument();

            //6466x3232

            //var suizoom = 720f / c.height;
            //var suizoom = 360f / c.height;
            var suizoom = 480f / c.width;

            c.style.transformOrigin = "0 0";
            c.style.transform = $"scale({suizoom})";
            //c.style.backgroundColor = "yellow";
            c.style.position = IStyle.PositionEnum.absolute;

            c.style.SetLocation(8 + (int)(uizoom * cubefacesize + 8) * 0, 8 + (int)(uizoom * cubefacesize + 8) * 3);

            var pass = new CubeToEquirectangular.Library.ShaderToy.EffectPass(
                       null,
                       gl,
                       precission: CubeToEquirectangular.Library.ShaderToy.DetermineShaderPrecission(gl),
                       supportDerivatives: gl.getExtension("OES_standard_derivatives") != null,
                       callback: null,
                       obj: null,
                       forceMuted: false,
                       forcePaused: false,
                       //quadVBO: Library.ShaderToy.createQuadVBO(gl, right: 0, top: 0),
                       outputGainNode: null
                   );

            // how shall we upload our textures?
            // can we reference GLSL.samplerCube yet?
            //pass.mInputs[0] = new samplerCube { };
            pass.mInputs[0] = new CubeToEquirectangular.Library.ShaderToy.samplerCube { };

            pass.MakeHeader_Image();
            var vs = new Shaders.ProgramFragmentShader();
            pass.NewShader_Image(vs);

            #endregion




            //var frame0 = new HTML.Images.FromAssets.tiles_regrid().AttachToDocument();
            var frame0 = new HTML.Images.FromAssets.galaxy_starfield().AttachToDocument();
            //var frame0 = new HTML.Images.FromAssets.galaxy_starfield150FOV().AttachToDocument();
            //var xor = new HTML.Images.FromAssets.Orion360_test_image_8192x4096().AttachToDocument();
            //var xor = new HTML.Images.FromAssets._2_no_clouds_4k().AttachToDocument();
            //var frame0 = new HTML.Images.FromAssets._2294472375_24a3b8ef46_o().AttachToDocument();


            // 270px
            //xor.style.height = "";
            frame0.style.height = "270px";
            frame0.style.width = "480px";
            frame0.style.SetLocation(
                8 + (int)(uizoom * cubefacesize + 8) * 0 + 480 + 16, 8 + (int)(uizoom * cubefacesize + 8) * 3);




            #region DirectoryEntry
            var dir = default(DirectoryEntry);
            int files2count = 0;

            new IHTMLButton { "openDirectory" }.AttachToDocument().onclick += async delegate
            {
                dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });

                var dir2r = dir.createReader();

                var files2 = await dir2r.readFileEntries();

                files2count = files2.Count();

                if (files2count > 0)
                {
                    new IHTMLPre { new { files2count } }.AttachToDocument();

                }
            };
            frame0.style.cursor = IStyle.CursorEnum.pointer;
            frame0.title = "save frame";


            frame0.onclick += delegate
            {
                // http://paulbourke.net/papers/vsmm2006/vsmm2006.pdf
                //            A method of creating synthetic stereoscopic panoramic images that can be implemented
                //in most rendering packages has been presented. If single panoramic pairs can be created
                //then stereoscopic panoramic movies are equally possible giving rise to the prospect of
                //movies where the viewer can interact with, at least with regard to what they choose to look
                //at.These images can be projected so as to engage the two features of the human visual
                //system that assist is giving us a sense of immersion, the feeling of “being there”. That is,
                //imagery that contains parallax information as captured from two horizontally separated eye
                //positions (stereopsis)and imagery that fills our peripheral vision.The details that define
                //how the two panoramic images should be created in rendering packages are provided, in
                //particular, how to precisely configure the virtual cameras and control the distance to zero
                //parallax.

                // grab a frame

                if (dir == null)
                {
                    // not exporting to file system?
                    var f0 = new IHTMLImage { src = gl.canvas.toDataURL() };

                    //var f0 = (IHTMLImage)gl.canvas;
                    //var f0 = (IHTMLImage)gl.canvas;
                    //var base64 = gl.canvas.toDataURL();


                    //frame0.src = base64;
                    frame0.src = f0.src;

                    // 7MB!

                    return;
                }

                //                // ---------------------------
                //IrfanView
                //---------------------------
                //Warning !
                //The file: "X:\vr\tape1\0001.jpg" is a PNG file with incorrect extension !
                //Rename ?
                //---------------------------
                //Yes   No   
                //---------------------------

                // haha this will render the thumbnail.
                //dir.WriteAllBytes("0000.png", frame0);

                //dir.WriteAllBytes("0000.png", gl.canvas);

                var glsw = Stopwatch.StartNew();
                dir.WriteAllBytes("0000.png", gl);

                new IHTMLPre { new { glsw.ElapsedMilliseconds } }.AttachToDocument();

                // {{ ElapsedMilliseconds = 1548 }}

                // 3.7MB
                // 3840x2160

            };

            #endregion


            #region render 60hz 30sec
            new IHTMLButton {
                $"render {maxfps}hz {maxlengthseconds}sec"
            }.AttachToDocument().onclick += async e =>
            {
                e.Element.disabled = true;


                var total = Stopwatch.StartNew();
                var status = "rendering... " + new { dir };

                new IHTMLPre { () => status }.AttachToDocument();

                if (dir == null)
                {
                    //dir = (DirectoryEntry)await chrome.fileSystem.chooseEntry(new { type = "openDirectory" });
                }

                total.Restart();



                vsync = new TaskCompletionSource<object>();
                await vsync.Task;

                status = "rendering... vsync";

                //var frameid = 0;


                //frameIDslider.valueAsNumber = -1;
                frameIDslider.valueAsNumber = files2count - 1;

                goto beforeframe;


                // parallax offset?

                await_nextframe:


                var filename = frameIDslider.valueAsNumber.ToString().PadLeft(5, '0') + ".png";
                status = "rendering... " + new { filename };


                vsync = new TaskCompletionSource<object>();
                await vsync.Task;

                // frame0 has been rendered

                var swcapture = Stopwatch.StartNew();
                status = "WriteAllBytes... " + new { filename };
                //await Native.window.async.onframe;

                // https://code.google.com/p/chromium/issues/detail?id=404301
                if (dir != null)
                    await dir.WriteAllBytes(filename, gl);
                //await dir.WriteAllBytes(filename, gl.canvas);

                status = "WriteAllBytes... done " + new { fcamerax, filename, swcapture.ElapsedMilliseconds };
                status = "rdy " + new { filename, fcamerax };
                //await Native.window.async.onframe;





                // design mode v render mode
                if (cubefacesize < cubefacesizeMAX)
                    frameIDslider.valueAsNumber += 15;
                else
                    frameIDslider.valueAsNumber++;




                beforeframe:

                // speed? S6 slow motion?
                // this is really slow. if we do x4x2 =x8 
                // https://www.youtube.com/watch?v=r76ULW16Ib8
                //fcamerax += 16 * (1.0 / 60.0);
                // fcamerax = radius * Math.Cos(Math.PI * (frameid - (60 * 30 / 2f)) / (60 * 30 / 2f));

                // speed? S6 slow motion?
                // this is really slow. if we do x4x2 =x8 
                // https://www.youtube.com/watch?v=r76ULW16Ib8
                //fcamerax += 16 * (1.0 / 60.0);

                // some shaders need to know where the camera is looking from. can we tell them?

                //fcamerax = 2.2 * Math.Sin(Math.PI * (frameIDslider.valueAsNumber - (60 * 30 / 2f)) / (60 * 30 / 2f));
                //fcameraz = 4.4 * Math.Cos(Math.PI * (frameIDslider.valueAsNumber - (60 * 30 / 2f)) / (60 * 30 / 2f));


                //// up
                //fcameray = 4.4 * Math.Cos(Math.PI * (frameIDslider.valueAsNumber - (60 * 30 / 2f)) / (60 * 30 / 2f));

                // cameraz.valueAsNumber = (int)(cameraz.max * Math.Sin(Math.PI * (frameid - (60 * 30 / 2f)) / (60 * 30 / 2f)));


                // up
                //fcameray = 128 * Math.Cos(Math.PI * (frameid - (60 * 30 / 2f)) / (60 * 30 / 2f));

                //fcamerax += (1.0 / 60.0);

                //fcamerax += (1.0 / 60.0) * 120;



                // 60hz 30sec
                if (frameIDslider.valueAsNumber < maxframes)
                {
                    // Blob GC? either this helms or the that we made a Blob static. 
                    //await Task.Delay(11);
                    await Task.Delay(33);
                    // gc at 260 happened twice?
                    goto await_nextframe;
                }

                total.Stop();
                status = "all done " + new { frameid = frameIDslider.valueAsNumber, total.ElapsedMilliseconds };
                vsync = default(TaskCompletionSource<object>);
                // http://stackoverflow.com/questions/22899333/delete-javascript-blobs

                e.Element.disabled = false;
            };
            #endregion


            // "Z:\jsc.svn\examples\javascript\WebGL\WebGLColladaExperiment\WebGLColladaExperiment\WebGLColladaExperiment.csproj"






            // asus will hang
            // https://3dwarehouse.sketchup.com/model.html?id=fb7a0448d940e575edc01389f336fb0a
            // can we get one frame into vr?

            // cube: mesh to cast shadows



            //{
            //    var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
            //    var floor2 = new THREE.Mesh(planeGeometry0,
            //        //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
            //        //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
            //        //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
            //        new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000 })

            //    );
            //    floor2.position.set(0, 0, -cubefacesize / 2);
            //    floor2.AttachTo(scene);
            //}
            //{
            //    var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
            //    var floor2 = new THREE.Mesh(planeGeometry0,
            //        //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
            //        //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
            //        //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
            //        new THREE.MeshPhongMaterial(new { ambient = 0x0000ff, color = 0x0000ff })

            //    );
            //    floor2.position.set(-cubefacesize / 2, 0, 0);
            //    floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI / 2);

            //    floor2.AttachTo(scene);
            //}

            // front?
            {
                //var tex0 = new THREE.Texture { image = new moon(), needsUpdate = true };
                //var tex0 = new THREE.Texture(new moon());
                //var tex0 = new THREE.Texture(new moon()) { needsUpdate = true };
                var tex0 = new THREE.Texture(shader1canvasPX) { needsUpdate = true };

                applycameraoffset += delegate { tex0.needsUpdate = true; };

                var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
                var floor2 = new THREE.Mesh(planeGeometry0,
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
                    new THREE.MeshPhongMaterial(
                        new
                        {

                            map = tex0,


                            //ambient = 0x00ff00,
                            //color = 0x00ff00
                        })

                );
                //floor2.position.set(0, 0, -cubefacesize  * 0.55);
                floor2.position.set(-cubefacesize * 0.5, 0, 0);
                floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI / 2);
                floor2.AttachTo(scene);
            }



            // left?
            {
                //var tex0 = new THREE.Texture { image = new moon(), needsUpdate = true };
                //var tex0 = new THREE.Texture(new moon());
                //var tex0 = new THREE.Texture(new moon()) { needsUpdate = true };
                var tex0 = new THREE.Texture(shader0canvasPZ) { needsUpdate = true };

                applycameraoffset += delegate { tex0.needsUpdate = true; };

                var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
                var floor2 = new THREE.Mesh(planeGeometry0,
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
                    new THREE.MeshPhongMaterial(
                        new
                        {

                            map = tex0,


                            //ambient = 0xff0000,

                            // can we color mark it?
                            //color = 0x00ff00
                        })

                );
                //floor2.position.set(0, -cubefacesize * 0.5, 0);
                floor2.position.set(0, 0, cubefacesize * 0.5);
                //floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), -Math.PI / 2);
                floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI);

                floor2.AttachTo(scene);
            }





            // right?
            {
                //var tex0 = new THREE.Texture { image = new moon(), needsUpdate = true };
                //var tex0 = new THREE.Texture(new moon());
                //var tex0 = new THREE.Texture(new moon()) { needsUpdate = true };
                var tex0 = new THREE.Texture(shader2canvasNZ) { needsUpdate = true };

                applycameraoffset += delegate { tex0.needsUpdate = true; };

                var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
                var floor2 = new THREE.Mesh(planeGeometry0,
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
                    new THREE.MeshPhongMaterial(
                        new
                        {

                            map = tex0,


                            //ambient = 0x00ff00,

                            // can we color mark it?
                            //color = 0x00ff00
                        })

                );
                //floor2.position.set(0, -cubefacesize * 0.5, 0);
                floor2.position.set(0, 0, -cubefacesize * 0.5);
                //floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), -Math.PI / 2);
                //floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI);

                floor2.AttachTo(scene);
            }


            // back?
            {
                //var tex0 = new THREE.Texture { image = new moon(), needsUpdate = true };
                //var tex0 = new THREE.Texture(new moon());
                //var tex0 = new THREE.Texture(new moon()) { needsUpdate = true };
                var tex0 = new THREE.Texture(shader1canvasNX) { needsUpdate = true };

                applycameraoffset += delegate { tex0.needsUpdate = true; };

                var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
                var floor2 = new THREE.Mesh(planeGeometry0,
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
                    new THREE.MeshPhongMaterial(
                        new
                        {

                            map = tex0,


                            //ambient = 0x00ff00,
                            //color = 0x00ff00
                        })

                );
                floor2.position.set(cubefacesize * 0.5, 0, 0);
                floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), -Math.PI / 2);


                floor2.AttachTo(scene);
            }









            // bottom?
            {
                //var tex0 = new THREE.Texture { image = new moon(), needsUpdate = true };
                //var tex0 = new THREE.Texture(new moon());
                //var tex0 = new THREE.Texture(new moon()) { needsUpdate = true };
                var tex0 = new THREE.Texture(shader2canvasNY) { needsUpdate = true };

                applycameraoffset += delegate { tex0.needsUpdate = true; };

                var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
                var floor2 = new THREE.Mesh(planeGeometry0,
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
                    new THREE.MeshPhongMaterial(
                        new
                        {

                            map = tex0,


                            //ambient = 0x00ff00,

                            // can we color mark it?
                            //color = 0x00ff00
                        })

                );
                //floor2.position.set(0, -cubefacesize * 0.5, 0);
                //floor2.position.set(cubefacesize * 0.5, 0, 0);
                //floor2.position.set(-cubefacesize * 0.5, 0, 0);
                floor2.position.set(0, -cubefacesize * 0.5, 0);


                //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), Math.PI / 2);

                applycameraoffset += delegate
                {
                    floor2.rotation.set(0, 0, 0);

                    //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), -Math.PI / 2);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI / 2);
                    floor2.rotateOnAxis(new THREE.Vector3(1, 0, 0), -Math.PI / 2);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), -Math.PI / 2);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), Math.PI / 2);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), Math.PI );
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), Math.PI);
                    floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), -Math.PI + bottomRotate100 * 0.01f);

                };

                floor2.AttachTo(scene);
            }



            // top?
            {
                //var tex0 = new THREE.Texture { image = new moon(), needsUpdate = true };
                //var tex0 = new THREE.Texture(new moon());
                //var tex0 = new THREE.Texture(new moon()) { needsUpdate = true };
                var tex0 = new THREE.Texture(shader2canvasPY) { needsUpdate = true };

                applycameraoffset += delegate { tex0.needsUpdate = true; };

                var planeGeometry0 = new THREE.PlaneGeometry(cubefacesize, cubefacesize, 8, 8);
                var floor2 = new THREE.Mesh(planeGeometry0,
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xA26D41, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0x101010, color = 0xff0000, specular = 0xA26D41, shininess = 1 })
                    //new THREE.MeshPhongMaterial(new { ambient = 0xff0000, color = 0xff0000, specular = 0xff0000 })
                    new THREE.MeshPhongMaterial(
                        new
                        {

                            map = tex0,


                            //ambient = 0x00ff00,

                            // can we color mark it?
                            //color = 0x00ff00
                        })

                );
                //floor2.position.set(0, -cubefacesize * 0.5, 0);
                //floor2.position.set(cubefacesize * 0.5, 0, 0);
                //floor2.position.set(-cubefacesize * 0.5, 0, 0);
                floor2.position.set(0, cubefacesize * 0.5, 0);


                //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), Math.PI / 2);

                applycameraoffset += delegate
                {
                    floor2.rotation.set(0, 0, 0);

                    //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), -Math.PI / 2);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI / 2);
                    floor2.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI / 2);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), -Math.PI / 2);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 1, 0), Math.PI);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), Math.PI / 2);
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), Math.PI );
                    //floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), Math.PI);
                    floor2.rotateOnAxis(new THREE.Vector3(0, 0, 1), bottomRotate100 * 0.01f);

                };

                floor2.AttachTo(scene);
            }




            // X:\jsc.svn\examples\javascript\chrome\apps\ChromeEarth\ChromeEarth\Application.cs
            // X:\jsc.svn\examples\javascript\canvas\ConvertBlackToAlpha\ConvertBlackToAlpha\Application.cs
            // hidden for alpha AppWindows
            //#if FBACKGROUND

            #region galaxy_starfield
            new THREE.Texture().With(
                async s =>
                {
                    var i = new HTML.Images.FromAssets.galaxy_starfield();
                    //var i = new HTML.Images.FromAssets.galaxy_starfield150FOV();

                    var bytes = await i.async.bytes;

                    //for (int ii = 0; ii < bytes.Length; ii += 4)
                    //{

                    //    bytes[ii + 3] = (byte)(bytes[ii + 0]);

                    //    bytes[ii + 0] = 0xff;
                    //    bytes[ii + 1] = 0xff;
                    //    bytes[ii + 2] = 0xff;
                    //}

                    var cc = new CanvasRenderingContext2D(i.width, i.height);

                    cc.bytes = bytes;

                    s.image = cc;
                    s.needsUpdate = true;

                    var stars_material = new THREE.MeshBasicMaterial(
                            new
                            {
                                //map = THREE.ImageUtils.loadTexture(new galaxy_starfield().src),
                                map = s,
                                side = THREE.BackSide,
                                transparent = true
                            });


                    var stars = new THREE.Mesh(
                            new THREE.SphereGeometry(far * 0.9, 64, 64),
                           stars_material
                        );

                    // http://stackoverflow.com/questions/8502150/three-js-how-can-i-dynamically-change-objects-opacity
                    //(stars_material as dynamic).opacity = 0.5;


                    scene.add(stars);
                }
           );
            #endregion




            new { }.With(
                   delegate
                   {



                       //dae.position.y = -80;

                       //dae.AttachTo(sceneg);
                       //scene.add(dae);
                       //oo.Add(dae);


                       //var rdysw = Stopwatch.StartNew();

                       //Console.WriteLine()

                       // view-source:http://threejs.org/examples/webgl_multiple_canvases_circle.html
                       // https://threejsdoc.appspot.com/doc/three.js/src.source/extras/cameras/CubeCamera.js.html
                       Native.window.onframe +=
                           e =>
                           {



                               // let render man know..
                               // let render man know..
                               if (vsyncReady())
                                   return;


                               //if (pause) return;
                               //if (pause.@checked)
                               //    return;


                               // can we float out of frame?
                               // haha. a bit too flickery.
                               //dae.position.x = Math.Sin(e.delay.ElapsedMilliseconds * 0.01) * 50.0;
                               //dae.position.x = Math.Sin(e.delay.ElapsedMilliseconds * 0.001) * 190.0;
                               //globesphere.position.y = Math.Sin(fcamerax * 0.001) * 90.0;
                               //clouds.position.y = Math.Cos(fcamerax * 0.001) * 90.0;

                               //sphere.rotation.y += speed;
                               //clouds.rotation.y += speed;

                               // manual rebuild?
                               // red compiler notifies laptop chrome of pending update
                               // app reloads

                               applycameraoffset();
                               renderer0.clear();
                               //rendererPY.clear();

                               //cameraPX.aspect = canvasPX.aspect;
                               //cameraPX.updateProjectionMatrix();

                               // um what does this do?
                               //cameraPX.position.z += (z - cameraPX.position.z) * e.delay.ElapsedMilliseconds / 200.0;
                               // mousewheel allos the camera to move closer
                               // once we see the frame in vr, can we udp sync vr tracking back to laptop?


                               //this.targetPX.x += 1;
                               //this.targetNX.x -= 1;

                               //this.targetPY.y += 1;
                               //this.targetNY.y -= 1;

                               //this.targetPZ.z += 1;
                               //this.targetNZ.z -= 1;

                               // how does the 360 or shadertoy want our cubemaps?


                               // and then rotate right?

                               // how can we render cubemap?



                               #region x
                               // upside down?
                               // are we ready?
                               renderer0.render(scene, cameraPX);
                               canvasPX.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);

                               renderer0.render(scene, cameraNX);
                               canvasNX.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                               #endregion

                               #region z
                               renderer0.render(scene, cameraPZ);
                               canvasPZ.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);

                               renderer0.render(scene, cameraNZ);
                               canvasNZ.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                               #endregion



                               #region y
                               renderer0.render(scene, cameraPY);

                               //canvasPY.save();
                               //canvasPY.translate(0, size);
                               //canvasPY.rotate((float)(-Math.PI / 2));
                               canvasPY.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                               //canvasPY.restore();


                               renderer0.render(scene, cameraNY);
                               //canvasNY.save();
                               //canvasNY.translate(size, 0);
                               //canvasNY.rotate((float)(Math.PI / 2));
                               canvasNY.drawImage((IHTMLCanvas)renderer0.domElement, 0, 0, cubefacesize, cubefacesize);
                               //canvasNY.restore();
                               // ?
                               #endregion


                               //renderer0.render(scene, cameraPX);


                               //rendererPY.render(scene, cameraPY);

                               // at this point we should be able to render the sphere texture

                               //public const uint TEXTURE_CUBE_MAP_POSITIVE_X = 34069;
                               //public const uint TEXTURE_CUBE_MAP_NEGATIVE_X = 34070;
                               //public const uint TEXTURE_CUBE_MAP_POSITIVE_Y = 34071;
                               //public const uint TEXTURE_CUBE_MAP_NEGATIVE_Y = 34072;
                               //public const uint TEXTURE_CUBE_MAP_POSITIVE_Z = 34073;
                               //public const uint TEXTURE_CUBE_MAP_NEGATIVE_Z = 34074;


                               //var cube0 = new IHTMLImage[] {
                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_px(),
                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_nx(),

                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_py(),
                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_ny(),


                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_pz(),
                               //        new CSS3DPanoramaByHumus.HTML.Images.FromAssets.humus_nz()
                               //};

                               new[] {
                                   canvasPX, canvasNX,
                                   canvasPY, canvasNY,
                                   canvasPZ, canvasNZ
                               }.WithEachIndex(
                                   (img, index) =>
                                   {
                                       gl.bindTexture(gl.TEXTURE_CUBE_MAP, pass.tex);

                                       //gl.pixelStorei(gl.UNPACK_FLIP_X_WEBGL, false);
                                       gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);

                                       // http://stackoverflow.com/questions/15364517/pixelstoreigl-unpack-flip-y-webgl-true

                                       // https://msdn.microsoft.com/en-us/library/dn302429(v=vs.85).aspx
                                       //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
                                       //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);

                                       gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + (uint)index, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img.canvas);

                                   }
                                );

                               // could do dynamic resolution- fog of war or fog of FOV. where up to 150deg field of vision is encouragedm, not 360
                               pass.Paint_Image(
                                     0,

                                     0,
                                     0,
                                     0,
                                     0
                                //,

                                // gl_FragCoord
                                // cannot be scaled, and can be referenced directly.
                                // need another way to scale
                                //zoom: 0.3f
                                );

                               //paintsw.Stop();


                               // what does it do?
                               gl.flush();

                               // let render man know..
                               if (vsync != null)
                                   if (!vsync.Task.IsCompleted)
                                       vsync.SetResult(null);
                           };


                   }
               );





            Console.WriteLine("do you see it?");
        }
        private void Initialize(IDefault page = null)
        {
			#region += Launched chrome.app.window
			dynamic self = Native.self;
			dynamic self_chrome = self.chrome;
			object self_chrome_socket = self_chrome.socket;

			if (self_chrome_socket != null)
			{
				if (!(Native.window.opener == null && Native.window.parent == Native.window.self))
				{
					Console.WriteLine("chrome.app.window.create, is that you?");

					// pass thru
				}
				else
				{
					// should jsc send a copresence udp message?
					chrome.runtime.UpdateAvailable += delegate
					{
						new chrome.Notification(title: "UpdateAvailable");

					};

					chrome.app.runtime.Launched += async delegate
					{
						// 0:12094ms chrome.app.window.create {{ href = chrome-extension://aemlnmcokphbneegoefdckonejmknohh/_generated_background_page.html }}
						Console.WriteLine("chrome.app.window.create " + new { Native.document.location.href });

						new chrome.Notification(title: "ChromeUDPSendAsync");

						var xappwindow = await chrome.app.window.create(
							   Native.document.location.pathname, options: null
						);

						//xappwindow.setAlwaysOnTop

						xappwindow.show();

						await xappwindow.contentWindow.async.onload;

						Console.WriteLine("chrome.app.window loaded!");
					};


					return;
				}
			}
			#endregion


			int w = Native.window.Width;
            int h = Native.window.Height;



            var gl = new WebGLRenderingContext(preserveDrawingBuffer: true);

            var canvas = gl.canvas.AttachToDocument();
            canvas.style.backgroundColor = JSColor.Black;
            Native.document.body.style.overflow = IStyle.OverflowEnum.hidden;
            canvas.style.SetLocation(0, 0);


            #region Dispose
            var IsDisposed = false;

            Dispose = delegate
            {
                if (IsDisposed)
                    return;

                IsDisposed = true;

                canvas.Orphanize();
            };
            #endregion


            // http://cs.helsinki.fi/u/ilmarihe/metatunnel.html


            var p = gl.createProgram(
                new ChocoluxVertexShader(),
                new ChocoluxFragmentShader()
            );


            gl.bindAttribLocation(p, 0, "position");
            gl.linkProgram(p);

            gl.useProgram(p);

            var uniforms = p.Uniforms(gl);

            gl.viewport(0, 0, w, h);

            gl.enableVertexAttribArray(0);


            var verts = gl.createBuffer();

            gl.bindBuffer(gl.ARRAY_BUFFER, verts);
            gl.bufferData(gl.ARRAY_BUFFER,
              new[] { -1f, -1f, -1f, 1f, 1f, -1f, 1f, 1f }
            , gl.STATIC_DRAW);
            gl.vertexAttribPointer((uint)0, 2, gl.FLOAT, false, 0, 0);

            var indicies = gl.createBuffer();

            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicies);

            var q = new Uint16Array(0, 1, 2, 3);



            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, q, gl.STATIC_DRAW);

            var start = new IDate().getTime();

            Native.window.onframe += delegate
            {
                var timestamp = new IDate().getTime();
                var t = (timestamp - start) / 1000.0f * 30f;


                uniforms.t = t * 100;
                //gl.uniform1f(gl.getUniformLocation(p, "t"), t * 100);
                gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_SHORT, 0);
                gl.flush();



            };




            #region AtResize
            Action AtResize = delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                canvas.width = Native.window.Width;
                canvas.height = Native.window.Height;


                gl.viewport(0, 0, canvas.width, canvas.height);
            };

            AtResize();

            Native.window.onresize += delegate
            {
                AtResize();
            };
            #endregion


            #region requestFullscreen
            Native.Document.body.ondblclick +=
                delegate
                {
                    if (IsDisposed)
                        return;

                    // http://tutorialzine.com/2012/02/enhance-your-website-fullscreen-api/

                    Native.Document.body.requestFullscreen();


                };
            #endregion


            Func<string> newicon = delegate
            {
                var icon = canvas.toDataURL("image/png");

                Native.Document.getElementsByTagName("link").AsEnumerable().ToList().WithEach(
                    e =>
                    {
                        var link = (IHTMLLink)e;

                        if (link.rel == "icon")
                        {
                            if (link.type == "image/png")
                            {

                                link.href = icon;
                            }
                            else
                            {
                                link.Orphanize();
                            }
                        }
                    }
                );

                return icon;
            };

            Native.Document.body.onclick +=
                  delegate
                  {
                      if (IsDisposed)
                          return;

                      newicon();
                  };

#if PackageAsApplication
            @"Spiral".ToDocumentTitle();

            Native.Window.requestAnimationFrame +=
              delegate
              {
                  var icon = newicon();
                  var img = new IHTMLImage { src = icon };

                  //img.width = Native.Window.Width / 2;
                  //img.height = Native.Window.Height / 2;

                  Native.Document.getElementsByTagName("script")
                      .Select(k => (IHTMLScript)k)
                      .FirstOrDefault(k => k.src.EndsWith("/view-source"))
                      .With(
                          source =>
                          {
            #region PackageAsApplication
                              Action<IHTMLScript, XElement, Action<string>> PackageAsApplication =
                                  (source0, xml, yield) =>
                                  {
                                      new IXMLHttpRequest(
                                          ScriptCoreLib.Shared.HTTPMethodEnum.GET, source0.src,
                                          (IXMLHttpRequest r) =>
                                          {
                                              // store hash
                                              xml.Add(new XElement("link", new XAttribute("rel", "location"), new XAttribute("href", Native.Document.location.hash)));

            #region script
                                              xml.Add(
                                                  new XElement("script",
                                                      "/* source */"
                                                 )
                                              );

                                              var data = "";


                                              Action later = delegate
                                              {

                                                  data = data.Replace("/* source */", r.responseText);

                                              };
            #endregion


                                              //Native.Document.getElementsByTagName("link").AsEnumerable().ToList().ForEach(

                                              xml.Elements("link").ToList().ForEach(
                                                  (XElement link, Action next) =>
                                                  {
            #region style
                                                      var rel = link.Attribute("rel");
                                                      if (rel.Value != "stylesheet")
                                                      {
                                                          next();
                                                          return;
                                                      }

                                                      var href = link.Attribute("href");

                                                      var placeholder = "/* " + href.Value + " */";

                                                      //page.DragHTM.innerText += " " + placeholder;


                                                      xml.Add(new XElement("style", placeholder));

                                                      new IXMLHttpRequest(ScriptCoreLib.Shared.HTTPMethodEnum.GET, href.Value,
                                                          rr =>
                                                          {

                                                              later += delegate
                                                              {


                                                                  data = data.Replace(placeholder, rr.responseText);

                                                              };

                                                              Console.WriteLine("link Remove");
                                                              link.Remove();

                                                              next();
                                                          }
                                                      );

            #endregion
                                                  }
                                              )(
                                                  delegate
                                                  {


                                                      data = xml.ToString();
                                                      Console.WriteLine("data: " + data);
                                                      later();

                                                      yield(data);
                                                  }
                                              );
                                          }
                                      );

                                  };
            #endregion


                              PackageAsApplication(
                                   source,
                                   XElement.Parse(new XDefaultPage.XMLSourceSource().Text),
                                   data =>
                                   {
                                       var bytes = Encoding.ASCII.GetBytes(data);
                                       var data64 = System.Convert.ToBase64String(bytes);


                                       Native.Document.body.title = "Drag me!";

                                       Native.Document.body.ondragstart +=
                                               e =>
                                               {
                                                   //e.dataTransfer.setData("text/plain", "Sphere");

                                                   // http://codebits.glennjones.net/downloadurl/virtualdownloadurl.htm
                                                   //e.dataTransfer.setData("DownloadURL", "image/png:Sphere.png:" + icon);

                                                   e.dataTransfer.setData("DownloadURL", "application/octet-stream:Chocolux.htm:data:application/octet-stream;base64," + data64);
                                                   e.dataTransfer.setData("text/html", data);
                                                   e.dataTransfer.setData("text/uri-list", Native.Document.location + "");
                                                   e.dataTransfer.setDragImage(img, img.width / 2, img.height / 2);
                                               };


                                   }
                               );
                          }
                  );




              };
#endif

        }
		/// <summary>
		/// This is a javascript application.
		/// </summary>
		/// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
		public Application(IApp page)
		{
			new { }.With(
				async delegate
				{
					var vid = "TXExg6Xj3aA";



					var thumbnail = $"https://img.youtube.com/vi/{vid}/0.jpg";

					var thumbnailImage = new IHTMLImage
					{
						// 0 pixels? useless. will extension be able to bypass?
						crossOrigin = "anonymous",

						src = thumbnail


					};

					//					naturalHeight:
					//					90
					//naturalWidth:
					//					120

					// {{ thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, width = 0, height = 0 }}
					new IHTMLPre {
						new { thumbnail, thumbnailImage.complete,  thumbnailImage.naturalWidth, thumbnailImage.naturalHeight}
					}.AttachToDocument();

					await thumbnailImage.async.oncomplete;

					//thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = false, naturalWidth = 0, naturalHeight = 0 }}
					//		thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = true, naturalWidth = 120, naturalHeight = 90 }}


					//thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = true, naturalWidth = 0, naturalHeight = 0 }}
					thumbnailImage.style.SetSize(
						thumbnailImage.naturalWidth, thumbnailImage.naturalHeight
					);

					new IHTMLPre {
						new { thumbnail, thumbnailImage.complete,  thumbnailImage.width, thumbnailImage.naturalWidth, thumbnailImage.naturalHeight }
					}.AttachToDocument();

					//				{
					//					{
					//						thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = false, width = 0, height = 0 }}
					//{
					//							{
					//								thumbnail = https://img.youtube.com/vi/TXExg6Xj3aA/0.jpg, complete = true, width = 0, height = 0 }}

					thumbnailImage.AttachToDocument();

					new IHTMLPre {
						new { thumbnail, thumbnailImage.complete, thumbnailImage.naturalWidth, thumbnailImage.naturalHeight }
					}.AttachToDocument();

					var div = new IHTMLDiv
					{

					}.AttachToDocument();

					// 404 image does show as a background, can we copy it?
					new IStyle(div)
					{
						width = 120 + "px",
						height = 90 + "px",
						//overflow = IStyle.OverflowEnum.hidden,
						//position = IStyle.PositionEnum.relative,
						backgroundImage = $"url('{thumbnail}')",

					};

					//Image from origin 'https://img.youtube.com' has been blocked from loading by Cross - Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://192.168.1.12:15367' is therefore not allowed access.The response had HTTP status code 404.

					var idiv = (IHTMLImage)div;

					idiv.AttachToDocument();

					new IHTMLPre {
						new {  idiv.complete,  idiv.width, idiv.naturalWidth, idiv.naturalHeight }
					}.AttachToDocument();
				}
			);

			//			Severity Code    Description Project File Line
			//Error CS7069  Reference to type 'TaskAwaiter<>' claims it is defined in 'mscorlib', but it could not be found TestCRCYTImage X:\jsc.svn\examples\javascript\test\TestCRCYTImage\TestCRCYTImage\Application.cs    56


		}
        public void InitializeContent()
        {
     

            // Initialise WebGL

            // if canvas object makes use of toDataUrl then this arg is required!
            var gl = new WebGLRenderingContext(preserveDrawingBuffer: true, alpha: false);

            var canvas = gl.canvas;

            Native.document.body.style.overflow = IStyle.OverflowEnum.hidden;

            canvas.AttachToDocument();
            canvas.style.SetLocation(0, 0);
            canvas.style.backgroundColor = "black";

            var s = new RaySurface(this);

            this.onsurface(gl);



            #region Dispose
            var IsDisposed = false;

            Dispose = delegate
            {
                if (IsDisposed)
                    return;

                IsDisposed = true;

                canvas.Orphanize();
            };
            #endregion

            #region AtResize
            Action AtResize = delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                canvas.width = Native.window.Width;
                canvas.height = Native.window.Height;

                this.onresize(Native.window.Width, Native.window.Height);
            };

            AtResize();

            Native.window.onresize += delegate
            {
                AtResize();
            };
            #endregion

            Func<string> newicon = delegate
            {
                var icon = canvas.toDataURL("image/png");

                Native.document.getElementsByTagName("link").AsEnumerable().ToList().WithEach(
                    e =>
                    {
                        var link = (IHTMLLink)e;

                        if (link.rel == "icon")
                        {
                            if (link.type == "image/png")
                            {

                                link.href = icon;
                            }
                            else
                            {
                                link.Orphanize();
                            }
                        }
                    }
                );

                return icon;
            };


            Native.window.onframe += delegate
            {
                if (IsDisposed)
                    return;

                this.onframe();
            };

            Native.document.body.onclick +=
                delegate
                {
                    if (IsDisposed)
                        return;

                    newicon();
                };


            Native.document.body.ondblclick +=
                delegate
                {
                    if (IsDisposed)
                        return;


                    Native.document.body.requestFullscreen();
                };

            #region draggable

            // http://www.thecssninja.com/javascript/gmail-dragout
            // can we drag ourself into crx?
            @"Sphere Ray Trace".ToDocumentTitle();

            Native.window.requestAnimationFrame +=
                delegate
                {
                    var icon = newicon();
                    var img = new IHTMLImage { src = icon };

                    //img.width = Native.Window.Width / 2;
                    //img.height = Native.Window.Height / 2;

#if PackageAsApplication
                    Native.Document.getElementsByTagName("script")
                        .Select(k => (IHTMLScript)k)
                        .FirstOrDefault(k => k.src.EndsWith("/view-source"))
                        .With(
                            source =>
                            {
                    #region PackageAsApplication
                                Action<IHTMLScript, XElement, Action<string>> PackageAsApplication =
                                    (source0, xml, yield) =>
                                    {
                                        new IXMLHttpRequest(
                                            ScriptCoreLib.Shared.HTTPMethodEnum.GET, source0.src,
                                            (IXMLHttpRequest r) =>
                                            {
                                                // store hash
                                                xml.Add(new XElement("link", new XAttribute("rel", "location"), new XAttribute("href", Native.Document.location.hash)));

                    #region script
                                                xml.Add(
                                                    new XElement("script",
                                                        "/* source */"
                                                   )
                                                );

                                                var data = "";


                                                Action later = delegate
                                                {

                                                    data = data.Replace("/* source */", r.responseText);

                                                };
                    #endregion


                                                //Native.Document.getElementsByTagName("link").AsEnumerable().ToList().ForEach(

                                                xml.Elements("link").ToList().ForEach(
                                                    (XElement link, Action next) =>
                                                    {
                    #region style
                                                        var rel = link.Attribute("rel");
                                                        if (rel.Value != "stylesheet")
                                                        {
                                                            next();
                                                            return;
                                                        }

                                                        var href = link.Attribute("href");

                                                        var placeholder = "/* " + href.Value + " */";

                                                        //page.DragHTM.innerText += " " + placeholder;


                                                        xml.Add(new XElement("style", placeholder));

                                                        new IXMLHttpRequest(ScriptCoreLib.Shared.HTTPMethodEnum.GET, href.Value,
                                                            rr =>
                                                            {

                                                                later += delegate
                                                                {


                                                                    data = data.Replace(placeholder, rr.responseText);

                                                                };

                                                                Console.WriteLine("link Remove");
                                                                link.Remove();

                                                                next();
                                                            }
                                                        );

                    #endregion
                                                    }
                                                )(
                                                    delegate
                                                    {


                                                        data = xml.ToString();
                                                        Console.WriteLine("data: " + data);
                                                        later();

                                                        yield(data);
                                                    }
                                                );
                                            }
                                        );

                                    };
                    #endregion


                                PackageAsApplication(
                                     source,
                                     XElement.Parse(new DefaultPage.XMLSourceSource().Text),
                                     data =>
                                     {
                                         var bytes = Encoding.ASCII.GetBytes(data);
                                         var data64 = System.Convert.ToBase64String(bytes);


                                         Native.Document.body.title = "Drag me!";

                                         Native.Document.body.ondragstart +=
                                                 e =>
                                                 {
                                                     //e.dataTransfer.setData("text/plain", "Sphere");

                                                     // http://codebits.glennjones.net/downloadurl/virtualdownloadurl.htm
                                                     //e.dataTransfer.setData("DownloadURL", "image/png:Sphere.png:" + icon);

                                                     e.dataTransfer.setData("DownloadURL", "application/octet-stream:Sphere.htm:data:application/octet-stream;base64," + data64);
                                                     e.dataTransfer.setData("text/html", data);
                                                     e.dataTransfer.setData("text/uri-list", Native.Document.location + "");
                                                     e.dataTransfer.setDragImage(img, img.width / 2, img.height / 2);
                                                 };


                                     }
                                 );
                            }
                    );


#endif


                };


            #endregion

        }