public static World Create(CanvasDevice device, int widthInTiles, int heightInTiles, IProgress<Tuple<string, float>> progress)
        {
            World world = new World();

            ProtoWorld pw = new ProtoWorld(device, widthInTiles, heightInTiles, progress);
            while (pw.Aborted) { pw = new ProtoWorld(device, widthInTiles, heightInTiles, progress); }

            world.Width = pw.Width;
            world.Height = pw.Height;
            foreach (ProtoRegion pr in pw.ProtoRegions)
            {
                world.Regions.Add(Region.FromProtoRegion(pr));
            }

            foreach (ProtoRegion pcr in pw.ProtoCaves)
            {
                world.Caves.Add(Region.FromProtoRegion(pcr));
            }

            world.RenderTargetRegions = pw.RenderTargetRegions;
            world.RenderTargetSubregions = pw.RenderTargetSubregions;
            world.RenderTargetPaths = pw.RenderTargetPaths;
            world.RenderTargetHeightMap = pw.RenderTargetHeightMap;
            world.RenderTargetCaves = pw.RenderTargetCaves;
            world.RenderTargetCavePaths = pw.RenderTargetCavePaths;

            return world;
        }
        public win2d_Map(Vector2 position, int width, int height, World world, bool drawCallout = true, bool drawStretched = false)
            : base(position, width, height)
        {
            World = world;

            _bDrawStretched = drawStretched;
            _bDrawCallout = drawCallout;

            _maxScale = 10;

            // set up scaling
            if (_bDrawStretched)
            {
                _minScale = -1;
                Scale = -1;
            }
            else
            {
                _minScale = world.Width > Width ? 1 : (width / world.Width) + 1;
                Scale = 10;
            }

            RecalculateLayout();
        }
        public static void Initialize(CanvasDevice device, World world)
        {
            _device = device;
            World = world;

            // START PANELS
            int panelLeftWidth = 300;
            int panelLeftHeight = Statics.CanvasHeight - Statics.Padding * 2;
            Vector2 panelLeftPosition = new Vector2(Statics.Padding, Statics.Padding);
            PanelLeft = new win2d_Panel(panelLeftPosition, panelLeftWidth, panelLeftHeight, Colors.Black);

            int panelRightWidth = 300;
            int panelRightHeight = Statics.CanvasHeight - Statics.Padding * 2;
            Vector2 panelRightPosition = new Vector2(Statics.CanvasWidth - panelRightWidth - Statics.Padding, Statics.Padding);
            PanelRight = new win2d_Panel(panelRightPosition, panelRightWidth, panelRightHeight, Colors.Black);

            int panelCenterWidth = Statics.CanvasWidth - panelLeftWidth - panelRightWidth - Statics.Padding * 4;
            int panelCenterHeight = Statics.CanvasHeight - Statics.Padding * 2;
            Vector2 panelCenterPosition = new Vector2(panelLeftWidth + Statics.Padding * 2, Statics.Padding);
            PanelCenter = new win2d_Panel(panelCenterPosition, panelCenterWidth, panelCenterHeight, Colors.Black);
            // END PANELS

            // note: controls in panels have positions relative to the panels

            // START MAP
            int mapWidth = panelRightWidth - Statics.Padding * 2;
            int mapHeight = 200;
            float mapPositionX = Statics.Padding; // panelRightWidth - mapWidth - Statics.Padding) / 2;
            float mapPositionY = Statics.Padding; // panelRightHeight - mapHeight - Statics.Padding;
            Map = new win2d_Map(new Vector2(mapPositionX, mapPositionY), mapWidth, mapHeight, World, drawCallout: true, drawStretched: false);
            PanelRight.AddControl(Map);
            // END MAP

            // START BUTTON
            int buttonSubmitInputWidth = 100;
            int buttonSubmitInputHeight = 36; // TODO: reconcile with height derivation in textbox constructor
            Vector2 buttonSubmitPosition = new Vector2(panelCenterWidth - Statics.Padding - buttonSubmitInputWidth, panelCenterHeight - Statics.Padding - buttonSubmitInputHeight);
            ButtonSubmitInput = new win2d_Button(_device, buttonSubmitPosition, buttonSubmitInputWidth, buttonSubmitInputHeight, "->");
            ButtonSubmitInput.Click += ButtonSubmitInput_Click;
            PanelCenter.AddControl(ButtonSubmitInput);
            // END BUTTON

            // START TEXTBOX
            int textboxInputWidth = panelCenterWidth - Statics.Padding * 3 - buttonSubmitInputWidth;
            int textboxInputHeight = 36; // TODO: reconcile with height derivation in textbox constructor
            Vector2 textboxInputPosition = new Vector2(Statics.Padding, panelCenterHeight - Statics.Padding - textboxInputHeight);
            TextboxInput = new win2d_Textbox(_device, textboxInputPosition, textboxInputWidth);
            TextboxInput.GiveFocus();
            PanelCenter.AddControl(TextboxInput);
            // END TEXTBOX

            // START TEXTBLOCK
            Vector2 textblockMainPosition = new Vector2(Statics.Padding, Statics.Padding);
            int textblockMainWidth = panelCenterWidth - Statics.Padding * 2;
            int textblockMainHeight = panelCenterHeight - textboxInputHeight - Statics.Padding * 3;
            TextblockMain = new win2d_Textblock(_device, textblockMainPosition, textblockMainWidth, textblockMainHeight, scrolltobottomonappend: true);
            PanelCenter.AddControl(TextblockMain);
            // END TEXTBLOCK

            // display initial room
            CurrentRoom = World.GetRandomRoom();
            while (CurrentRoom.DirectionalRoomConnections.Count == 0) { CurrentRoom = World.GetRandomRoom(); }
            Map.CenterOnPoint(CurrentRoom.CoordinatesXY);
            AppendText(CurrentRoom.DisplayString);
        }