public RadioList addRadioList(UDim2 pos, UDim2 size, string txt, List <RadioListElement> items)
        {
            RadioList rl = new RadioList(pos, size, txt, items);

            this.elements.Add(rl);
            return(rl);
        }
        public static void Update(GameTime gameTime, Leap.Frame frame)
        {
            Leap.Pointable currentPointer = null;
            foreach (Leap.Hand hand in frame.Hands)
            {
                Vector3 furthest = new Vector3(0, 0, 1000);
                foreach (Leap.Pointable p in hand.Pointables)
                {
                    if (p.IsExtended)
                    {
                        Vector3 worldPos = Util.toWorldNoTransform(p.StabilizedTipPosition) - new Vector3(0, Main.handOffset, 0);
                        if (worldPos.Z < furthest.Z)
                        {
                            furthest       = worldPos;
                            currentPointer = p;
                        }
                    }
                }
                Vector3 screenPos = Main.main.GraphicsDevice.Viewport.Project(furthest, Main.main.handCamera.projection, Main.main.handCamera.view, Matrix.Identity);
                screenFingerPos = new Vector2((screenPos.X - Main.screenWidth / 2) * 2f + (Main.screenWidth / 2), screenPos.Y);
                if (screenFingerPos.Y > Main.screenHeight * .5f)
                {
                    screenFingerPos.Y += (screenFingerPos.Y - Main.screenHeight / 2) * 1.5f;
                }
            }

            int   w      = Main.screenWidth;
            int   h      = Main.screenHeight;
            Point finger = new Point((int)screenFingerPos.X, (int)screenFingerPos.Y);

            foreach (Screen screen in screens)
            {
                if (screen.visible)
                {
                    float sw = screen.Size.calc(w, h).X;
                    float sh = screen.Size.calc(w, h).Y;
                    foreach (UIElement e in screen.elements)
                    {
                        if (e is Button)
                        {
                            Button    btn = e as Button;
                            Rectangle r   = new Rectangle((int)btn.Position.calc(sw, sh).X, (int)btn.Position.calc(sw, sh).Y, (int)btn.Size.calc(sw, sh).X + (int)btn.selOffset.X + (int)btn.selOffset.X, (int)btn.Size.calc(sw, sh).Y);
                            if (r.Contains(finger))
                            {
                                btn.hover       = true;
                                btn.selOffset.X = MathHelper.Lerp(btn.selOffset.X, 50, .2f);
                                if (currentPointer != null)
                                {
                                    if (currentPointer.TipVelocity.x > 200 && finger.X > r.Right - 40)
                                    {
                                        if (btn.onClick != null)
                                        {
                                            btn.onClick.Invoke();
                                        }
                                    }
                                }
                            }
                            else
                            {
                                btn.hover       = false;
                                btn.selOffset.X = MathHelper.Lerp(btn.selOffset.X, 0, .2f);
                            }
                        }
                        else if (e is RadioList)
                        {
                            RadioList rl = e as RadioList;
                            for (int i = 0; i < rl.items.Count; i++)
                            {
                                RadioListElement item = rl.items[i];

                                int       yoffset = (int)(i * rl.Size.calc(sw, sh).Y + i * 5);
                                Rectangle r       = new Rectangle((int)rl.Position.calc(sw, sh).X, (int)rl.Position.calc(sw, sh).Y + yoffset, (int)rl.Size.calc(sw, sh).X, (int)rl.Size.calc(sw, sh).Y);
                                if (r.Contains(finger) && !item.disabled)
                                {
                                    item.hover  = true;
                                    item.offset = MathHelper.Lerp(item.offset, i == rl.selected ? 50 : 25, .2f);
                                    if (currentPointer != null)
                                    {
                                        if (currentPointer.TipVelocity.x > 150 && finger.X > r.Center.X)
                                        {
                                            rl.selected = i;
                                            if (item.onSelected != null)
                                            {
                                                item.onSelected.Invoke();
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    item.hover = false;
                                    if (i != rl.selected)
                                    {
                                        item.offset = MathHelper.Lerp(item.offset, 0, .2f);
                                    }
                                    else
                                    {
                                        item.offset = MathHelper.Lerp(item.offset, 50, .2f);
                                        if (item.disabled)
                                        {
                                            rl.selected = -1;
                                        }
                                    }
                                }
                                rl.items[i] = item;
                            }
                        }
                    }
                }
            }
        }
        public static void Draw(SpriteBatch batch, SpriteFont uiFont)
        {
            int w = Main.screenWidth;
            int h = Main.screenHeight;

            foreach (Screen screen in screens)
            {
                if (screen.visible)
                {
                    if (screen.backgroundColor != Color.Transparent)
                    {
                        batch.Draw(Main.main.pixelTexture, new Rectangle((int)screen.Position.calc(w, h).X, (int)screen.Position.calc(w, h).Y, (int)screen.Size.calc(w, h).X, (int)screen.Size.calc(w, h).Y), screen.backgroundColor);
                    }

                    float sw = screen.Size.calc(w, h).X;
                    float sh = screen.Size.calc(w, h).Y;
                    foreach (UIElement e in screen.elements)
                    {
                        Vector2 ePos  = e.Position.calc(sw, sh);
                        Vector2 eSize = e.Size.calc(sw, sh);
                        if (e is Button)
                        {
                            Button btn = e as Button;
                            ePos += btn.selOffset;
                            if (btn.hover)
                            {
                                batch.Draw(Main.main.pixelTexture, new Rectangle((int)ePos.X - 2, (int)ePos.Y - 2, (int)eSize.X + 2, (int)eSize.Y + 2), Color.White);
                            }
                            else
                            {
                                batch.Draw(Main.main.pixelTexture, new Rectangle((int)ePos.X, (int)ePos.Y, (int)eSize.X + 2, (int)eSize.Y + 2), Color.Black);
                            }
                            batch.Draw(Main.main.pixelTexture, new Rectangle((int)ePos.X, (int)ePos.Y, (int)eSize.X, (int)eSize.Y), screen.buttonColor);
                            Vector2 s = uiFont.MeasureString(e.text);
                            batch.DrawString(uiFont, e.text, ePos + eSize / 2, Color.White, 0f, s / 2, 1f, SpriteEffects.None, 0f);
                        }
                        if (e is RadioList)
                        {
                            RadioList rl = e as RadioList;

                            Vector2 lSize = uiFont.MeasureString(e.text);
                            batch.DrawString(uiFont, e.text, ePos + eSize / 2 + new Vector2(0, eSize.Y * -1), Color.White, 0f, lSize / 2, 1f, SpriteEffects.None, 0f);

                            int i = 0;
                            foreach (RadioListElement item in rl.items)
                            {
                                if (item.hover)
                                {
                                    batch.Draw(Main.main.pixelTexture, new Rectangle((int)ePos.X + (int)item.offset - 2, (int)ePos.Y + (int)eSize.Y * i + (i * 5) - 2, (int)eSize.X + 2, (int)eSize.Y + 2), !item.disabled ? screen.buttonColor : Color.White);
                                }
                                else
                                {
                                    batch.Draw(Main.main.pixelTexture, new Rectangle((int)ePos.X + (int)item.offset, (int)ePos.Y + (int)eSize.Y * i + (i * 5), (int)eSize.X + 2, (int)eSize.Y + 2), !item.disabled ? screen.buttonColor : Color.Black);
                                }

                                batch.Draw(Main.main.pixelTexture, new Rectangle((int)ePos.X + (int)item.offset, (int)ePos.Y + (int)eSize.Y * i + (i * 5), (int)eSize.X, (int)eSize.Y), !item.disabled ? screen.buttonColor : Color.Gray);
                                Vector2 s = uiFont.MeasureString(item.name);
                                batch.DrawString(uiFont, item.name, ePos + eSize / 2 + new Vector2((int)item.offset, eSize.Y * i + (i * 5)), Color.White, 0f, s / 2, 1f, SpriteEffects.None, 0f);
                                if (i == rl.selected || item.hover)
                                {
                                    Vector2 ds = uiFont.MeasureString(item.detail);
                                    batch.DrawString(uiFont, item.detail, ePos + new Vector2(item.offset + eSize.X, eSize.Y * i + (i * 5) + eSize.Y / 2), Color.White, 0f, new Vector2(-5, ds.Y / 2), 1f, SpriteEffects.None, 0f);
                                }
                                i++;
                            }
                        }
                    }
                }
            }
            if (Main.main.gameState != GameState.InGame)
            {
                batch.Draw(Main.main.pixelTexture, new Rectangle((int)screenFingerPos.X - 5, (int)screenFingerPos.Y - 5, 10, 10), Color.White * .5f);
            }
        }
        protected override void Initialize()
        {
            leapInput             = new LeapHandler();
            world                 = new Sim.World();
            world.camera.position = new Vector3(0, 0, 0);
            world.camera.offset   = new Vector3(0, 0, 0);
            world.camera.mode     = CameraMode.Orbit;
            handCamera            = new Camera(new Vector2(screenWidth, screenHeight));
            handCamera.mode       = CameraMode.FirstPerson;
            handCamera.position   = new Vector3(0, 1, 10);
            handRenderer          = new Renderer();
            titleRenderer         = new Renderer();

            gameState = GameState.MainMenu;

            #region UI
            UI.Screen mainScreen = new UI.Screen(new UI.UDim2(0, 0, 0, 0), new UI.UDim2(1, 1, 0, 0));
            UI.Button start      = mainScreen.addButton(new UI.UDim2(.5f, 1, -100, -300), new UI.UDim2(0, 0, 200, 60), "Start");
            UI.Button exit       = mainScreen.addButton(new UI.UDim2(.5f, 1, -100, -200), new UI.UDim2(0, 0, 200, 60), "Exit");

            UI.Screen    constructionScreen = new UI.Screen(new UI.UDim2(0, 0, 0, 0), new UI.UDim2(1, 1, 0, 0), false);
            UI.Button    back         = constructionScreen.addButton(new UI.UDim2(.5f, 1, -100, -150), new UI.UDim2(0, 0, 200, 60), "Back");
            UI.RadioList entrymethods = constructionScreen.addRadioList(new UI.UDim2(0, 0f, 20, 125), new UI.UDim2(0, 0, 200, 60), "Entry Method", new List <UI.RadioListElement>()
            {
                new UI.RadioListElement()
                {
                    name = "Trojan Horse", detail = "Target cell unknowingly absorbes virus"
                },
                new UI.RadioListElement()
                {
                    name = "Ingestion", detail = "Target cell ingests virus"
                },
                new UI.RadioListElement()
                {
                    name = "Injection", detail = "Virus injects genetic material directly into target cell"
                }
            });
            UI.RadioList exitmethods = constructionScreen.addRadioList(new UI.UDim2(.5f, 0f, 0, 125), new UI.UDim2(0, 0, 200, 60), "Exit Method", new List <UI.RadioListElement>()
            {
                new UI.RadioListElement()
                {
                    name = "Lysis", detail = "Cell bursts and releases virus"
                },
                new UI.RadioListElement()
                {
                    name = "Pinch/Bud", detail = "Virus penetrates through cell membrane"
                }
            });
            UI.RadioList shapes = constructionScreen.addRadioList(new UI.UDim2(.5f, 0f, 0, 425), new UI.UDim2(0, 0, 200, 60), "Shape", new List <UI.RadioListElement>()
            {
                new UI.RadioListElement()
                {
                    name = "Spherical", detail = "", onSelected = () =>
                    {
                        UI.RadioListElement el = entrymethods.items[2];
                        el.disabled            = true;
                        el.detail             = "Not compatible with injection!";
                        entrymethods.items[2] = el;
                    }
                },
                new UI.RadioListElement()
                {
                    name = "Complex", detail = "", onSelected = () => {
                        UI.RadioListElement el = entrymethods.items[2];
                        el.disabled            = false;
                        el.detail             = "Virus injects genetic material directly into target cell";
                        entrymethods.items[2] = el;
                    }
                }
            });
            UI.RadioList type = constructionScreen.addRadioList(new UI.UDim2(0, 0f, 20, 425), new UI.UDim2(0, 0, 200, 60), "Type", new List <UI.RadioListElement>()
            {
                new UI.RadioListElement()
                {
                    name = "RNA Hijack", detail = "Injection of RNA to hijack nucleus"
                },
                new UI.RadioListElement()
                {
                    name = "Lysogenic Cycle", detail = "RNA fuses with DNA of cell"
                }
            });
            UI.Button begin = constructionScreen.addButton(new UI.UDim2(.5f, 1, -100, -250), new UI.UDim2(0, 0, 200, 60), "Start");

            constructionScreen.buttonColor = Color.CadetBlue;
            mainScreen.buttonColor         = Color.CadetBlue;

            begin.onClick += () =>
            {
                if (shapes.selected + entrymethods.selected + type.selected + exitmethods.selected < 0)
                {
                    //Debug.print("hey, dumbass, you forgot one");
                }
                else
                {
                    mainScreen.visible         = false;
                    constructionScreen.visible = false;
                    gameState = GameState.InGame;

                    Sim.VirusShape vshape = shapes.selected == 0 ? Sim.VirusShape.Icosahedral : Sim.VirusShape.Complex;
                    Sim.EnterType  entype = (Sim.EnterType)entrymethods.selected;
                    Sim.ExitType   extype = (Sim.ExitType)exitmethods.selected;
                    Sim.VirusType  vtype  = (Sim.VirusType)type.selected;
                    Sim.Virus      virus  = new Sim.Virus(vtype, vshape, entype, extype, Vector3.Zero, world);
                    virus.cameraSubject = true;

                    world.generateWorld();
                }
            };

            start.onClick += () =>
            {
                mainScreen.visible         = false;
                constructionScreen.visible = true;
                titleRenderer.setModel(null, Microsoft.Xna.Framework.Matrix.Identity);
            };
            exit.onClick += () =>
            {
                this.Exit();
            };
            back.onClick += () =>
            {
                mainScreen.visible         = true;
                constructionScreen.visible = false;
                titleRenderer.setModel(titletext, Microsoft.Xna.Framework.Matrix.Identity);
            };
            #endregion
            base.Initialize();
        }