Exemple #1
0
        private void automaticSlideshowCheckbox_CheckedChanged(object sender, EventArgs e)
        {
            if (automaticSlideshowCheckbox.Checked)
            {
                var id = ++slideshowTaskId;

                Task.Run(() =>
                {
                    for (var i = slideshowIndex; i < generatedLayouts.Count; i++)
                    {
                        if (slideshowTaskId != id || !automaticSlideshowCheckbox.Checked)
                        {
                            return;
                        }

                        var idToShow = i;

                        Invoke((Action)(() =>
                        {
                            slideshowIndex = idToShow;
                            UpdateSlideshowInfo();
                            layoutToDraw = generatedLayouts[idToShow];
                            mainPictureBox.Refresh();
                        }));

                        Thread.Sleep(3000);
                    }
                });
            }
        }
        /// <summary>
        /// Draws a given layout to an output using a given scale and offset.
        /// </summary>
        /// <remarks>
        /// All points are tranfosmer using the TransformPoint method.
        /// </remarks>
        /// <param name="layout">Layout do be drawn</param>
        /// <param name="scale">Scale factor</param>
        /// <param name="offset"></param>
        /// <param name="withNames">Whether names should be displayed</param>
        /// <param name="fixedFontSize"></param>
        protected void DrawLayout(IMapLayout <TNode> layout, float scale, IntVector2 offset, bool withNames, int?fixedFontSize = null)
        {
            var polygons = layout.Rooms.Select(x => x.Shape + x.Position).ToList();
            var rooms    = layout.Rooms.ToList();
            var minWidth = layout.Rooms.Where(x => !x.IsCorridor).Select(x => x.Shape + x.Position).Min(x => x.BoundingRectangle.Width);

            for (var i = 0; i < rooms.Count; i++)
            {
                var room    = rooms[i];
                var outline = GetOutline(polygons[i], room.Doors?.ToList())
                              .Select(x => Tuple.Create(TransformPoint(x.Item1, scale, offset), x.Item2)).ToList();

                var transformedPoints = polygons[i].GetPoints().Select(point => TransformPoint(point, scale, offset)).ToList();

                if (transformedPoints.All(x => x == new IntVector2(0, 0)))
                {
                    throw new InvalidOperationException("One of the polygons could not be drawn because the canvas size is too small.");
                }

                var polygon = new GridPolygon(transformedPoints);
                DrawRoom(polygon, outline, 2);

                if (withNames && !room.IsCorridor)
                {
                    DrawTextOntoPolygon(polygon, room.Node.ToString(), fixedFontSize ?? 2.5f * minWidth);
                }
            }
        }
Exemple #3
0
        protected Layout <TRoom> TransformLayout(IMapLayout <TRoom> layout, TwoWayDictionary <IRoomDescription, GameObject> roomDescriptionsToRoomTemplates)
        {
            var roomTransformations = new RoomTransformations();

            // Prepare an object to hold instantiated room templates
            var parentGameObject = new GameObject("Room template instances");

            parentGameObject.transform.parent = Payload.GameObject.transform;

            // Initialize rooms
            var layoutData = new Dictionary <TRoom, RoomInfo <TRoom> >();

            foreach (var layoutRoom in layout.Rooms)
            {
                var roomTemplate = roomDescriptionsToRoomTemplates[layoutRoom.RoomDescription];

                // Instatiate room template
                var room = Object.Instantiate(roomTemplate);
                room.SetActive(false);
                room.transform.SetParent(parentGameObject.transform);

                // Transform room template if needed
                var transformation = layoutRoom.Transformation;
                roomTransformations.Transform(room, transformation);

                // Compute correct room position
                // We cannot directly use layoutRoom.Position because the dungeon moves
                // all room shapes in a way that they are in the first plane quadrant
                // and touch the xy axes. So we have to subtract the original lowest
                // x and y coordinates.
                var smallestX       = layoutRoom.RoomDescription.Shape.GetPoints().Min(x => x.X);
                var smallestY       = layoutRoom.RoomDescription.Shape.GetPoints().Min(x => x.Y);
                var correctPosition = layoutRoom.Position.ToUnityIntVector3() - new Vector3Int(smallestX, smallestY, 0);
                room.transform.position = correctPosition;

                var roomInfo = new RoomInfo <TRoom>(roomTemplate, room, correctPosition, TransformDoorInfo(layoutRoom.Doors),
                                                    layoutRoom.IsCorridor, layoutRoom);

                room.transform.position = new Vector3(room.transform.position.x * 32, room.transform.position.y * 16, 0);
                //room.gameObject.SetActive(true);

                foreach (Transform child in room.transform)
                {
                    if (child.gameObject.tag == "object")
                    {
                        var pos = child.transform.localPosition;
                        child.transform.SetParent(room.transform.parent);
                        child.transform.localScale = new Vector3(1, 1, 0);
                        child.transform.position   = new Vector3(room.transform.position.x + pos.x, room.transform.position.y + pos.y, 0);
                    }
                }

                room.transform.localScale = new Vector3(1, 1, 0);

                layoutData.Add(layoutRoom.Node, roomInfo);
            }

            return(new Layout <TRoom>(layoutData));
        }
        /// <summary>
        /// Draws the layout to a given PictureBox.
        /// </summary>
        /// <param name="layout"></param>
        /// <param name="height"></param>
        /// <param name="withNames"></param>
        /// <param name="fixedFontSize"></param>
        /// <param name="width"></param>
        public Bitmap DrawLayout(IMapLayout <TNode> layout, int width, int height, bool withNames = true, int?fixedFontSize = null)
        {
            bitmap   = new Bitmap(width, height);
            graphics = Graphics.FromImage(bitmap);

            base.DrawLayout(layout, width, height, withNames, fixedFontSize);

            return(bitmap);
        }
Exemple #5
0
        /// <summary>
        /// Serializes a given layout to JSON.
        /// </summary>
        /// <param name="layout"></param>
        /// <param name="writer"></param>
        public void Serialize(IMapLayout <TNode> layout, StreamWriter writer)
        {
            var json = JsonConvert.SerializeObject(
                layout.Rooms.Select(x => modelConverter.GetRoomModel(x)),
                Formatting.Indented
                );

            writer.Write(json);
        }
Exemple #6
0
        private void mainPictureBox_Paint(object sender, PaintEventArgs e)
        {
            if (layoutToDraw == null)
            {
                return;
            }

            if (exportShownLayoutsCheckbox.Checked)
            {
                DumpSvg();
            }

            UpdateLayoutType();

            var showNames        = showRoomNamesCheckbox.Checked;
            var useOldPaperStyle = useOldPaperStyleCheckbox.Checked;
            var fixedFontSize    = fixedFontSizeCheckbox.Checked ? (int?)fixedFontSizeValue.Value : null;

            if (firstChainToDraw == null)
            {
                firstChainToDraw = layoutToDraw;
                RecomputeFixedScaleAndOffset();
            }
            else
            {
                var previousRoomsCount = firstChainToDraw.Rooms.Count();
                var currentRoomsCount  = layoutToDraw.Rooms.Count();

                if (previousRoomsCount == currentRoomsCount)
                {
                    firstChainToDraw = layoutToDraw;
                    RecomputeFixedScaleAndOffset();
                }
            }

            if (useOldPaperStyle)
            {
                var bitmap = oldMapDrawer.DrawLayout(layoutToDraw, mainPictureBox.Width, mainPictureBox.Height, showNames, fixedFontSize);
                e.Graphics.DrawImage(bitmap, new Point(0, 0));
            }
            else
            {
                Bitmap bitmap;

                if (fixedPositionsAndScaleCheckbox.Checked)
                {
                    bitmap = wfLayoutDrawer.DrawLayout(layoutToDraw, mainPictureBox.Width, mainPictureBox.Height, showNames, fixedFontSize, fixedScale, fixedOffset);
                }
                else
                {
                    bitmap = wfLayoutDrawer.DrawLayout(layoutToDraw, mainPictureBox.Width, mainPictureBox.Height, showNames, fixedFontSize);
                }

                e.Graphics.DrawImage(bitmap, new Point(0, 0));
            }
        }
Exemple #7
0
        private void slideshowRightButton_Click(object sender, EventArgs e)
        {
            automaticSlideshowCheckbox.Checked = false;

            if (slideshowIndex != generatedLayouts.Count - 1)
            {
                layoutToDraw = generatedLayouts[++slideshowIndex];
                mainPictureBox.Refresh();
            }

            UpdateSlideshowInfo();
        }
Exemple #8
0
        private float GetWidthHeightRatio(IMapLayout <TNode> layout)
        {
            var polygons = layout.Rooms.Select(x => x.Shape + x.Position).ToList();
            var points   = polygons.SelectMany(x => x.GetPoints()).ToList();

            var minx = points.Min(x => x.X);
            var miny = points.Min(x => x.Y);
            var maxx = points.Max(x => x.X);
            var maxy = points.Max(x => x.Y);

            var ratio = (maxx - minx) / (float)(maxy - miny);

            return(ratio);
        }
        /// <summary>
        /// Entry point of the class. Draws a given layout to an output with given dimensions.
        /// </summary>
        /// <param name="layout">Layout do be drawn</param>
        /// <param name="width">Width of the output</param>
        /// <param name="height">Height of the output</param>
        /// <param name="withNames">Whether names should be displayed</param>
        /// <param name="fixedFontSize"></param>
        /// <param name="borderSize"></param>
        protected void DrawLayout(IMapLayout <TNode> layout, int width, int height, bool withNames, int?fixedFontSize = null, float borderSize = 0.2f)
        {
            var polygons = layout.Rooms.Select(x => x.Shape + x.Position).ToList();
            var points   = polygons.SelectMany(x => x.GetPoints()).ToList();

            var minx = points.Min(x => x.X);
            var miny = points.Min(x => x.Y);
            var maxx = points.Max(x => x.X);
            var maxy = points.Max(x => x.Y);

            var scale  = GetScale(minx, miny, maxx, maxy, width, height, borderSize);
            var offset = GetOffset(minx, miny, maxx, maxy, width, height, scale);

            DrawLayout(layout, scale, offset, withNames, fixedFontSize);
        }
        protected IMapLayout <int> GenerateLayout(MapDescription <int> mapDescription)
        {
            if (Config.Timeout <= 0)
            {
                throw new ArgumentException("Timeout must be a positive number.");
            }

            // Setup layout generator
            IBenchmarkableLayoutGenerator <MapDescription <int>, IMapLayout <int> > generator;

            if (mapDescription.IsWithCorridors)
            {
                var gen = UnityLayoutGeneratorFactory.GetChainBasedGeneratorWithCorridors <int>(mapDescription.CorridorsOffsets);
                gen.InjectRandomGenerator(Payload.Random);
                generator = gen;
            }
            else
            {
                var gen = UnityLayoutGeneratorFactory.GetDefaultChainBasedGenerator <int>();
                gen.InjectRandomGenerator(Payload.Random);
                generator = gen;
            }

            // Run generator
            IMapLayout <int> layout = null;
            var task          = Task.Run(() => layout = generator.GetLayouts(mapDescription, 1)[0]);
            var taskCompleted = task.Wait(Config.Timeout);

            if (!taskCompleted)
            {
                throw new DungeonGeneratorException("Timeout was reached when generating the layout");
            }

            if (Config.ShowDebugInfo)
            {
                Debug.Log($"Layout generated in {generator.TimeFirst / 1000f:F} seconds");
                Debug.Log($"{generator.IterationsCount} iterations needed, {(generator.IterationsCount / (generator.TimeFirst / 1000d)):0} iterations per second");
            }

            return(layout);
        }
        /// <summary>
        /// Draws the layout to a given PictureBox.
        /// </summary>
        /// <param name="layout"></param>
        /// <param name="height"></param>
        /// <param name="withNames"></param>
        /// <param name="fixedFontSize"></param>
        /// <param name="width"></param>
        public Bitmap DrawLayout(IMapLayout <TNode> layout, int width, int height, bool withNames = true, int?fixedFontSize = null, float?scale = null, IntVector2?offset = null)
        {
            bitmap   = new Bitmap(width, height);
            graphics = Graphics.FromImage(bitmap);

            if (scale != null || offset != null)
            {
                if (scale == null || offset == null)
                {
                    throw new ArgumentException("Scale and offset must either both be null or not-null");
                }

                base.DrawLayout(layout, scale.Value, offset.Value, withNames, fixedFontSize);
            }
            else
            {
                base.DrawLayout(layout, width, height, withNames, fixedFontSize);
            }

            return(bitmap);
        }
        protected void SetupRoomTemplates(IMapLayout <int> layout)
        {
            var roomTransformations = new RoomTransformations();

            // Prepare an object to hold instantiated room templates
            var parentGameObject = new GameObject("Room template instances");

            parentGameObject.transform.parent = Payload.GameObject.transform;

            // Initialize rooms
            Payload.LayoutData = new Dictionary <int, RoomInfo <int> >();
            foreach (var layoutRoom in layout.Rooms)
            {
                var roomTemplate = Payload.RoomDescriptionsToRoomTemplates[layoutRoom.RoomDescription];

                // Instatiate room template
                var room = Object.Instantiate(roomTemplate);
                room.SetActive(false);
                room.transform.SetParent(parentGameObject.transform);

                // Transform room template if needed
                var transformation = layoutRoom.Transformation;
                roomTransformations.Transform(room, transformation);

                // Compute correct room position
                // We cannot directly use layoutRoom.Position because the dungeon moves
                // all room shapes in a way that they are in the first plane quadrant
                // and touch the xy axes. So we have to subtract the original lowest
                // x and y coordinates.
                var smallestX       = layoutRoom.RoomDescription.Shape.GetPoints().Min(x => x.X);
                var smallestY       = layoutRoom.RoomDescription.Shape.GetPoints().Min(x => x.Y);
                var correctPosition = layoutRoom.Position.ToUnityIntVector3() - new Vector3Int(smallestX, smallestY, 0);
                room.transform.position = correctPosition;

                var roomInfo = new RoomInfo <int>(roomTemplate, room, correctPosition, TransformDoorInfo(layoutRoom.Doors),
                                                  layoutRoom.IsCorridor, layoutRoom);

                Payload.LayoutData.Add(layoutRoom.Node, roomInfo);
            }
        }
        protected IMapLayout <TRoom> GenerateLayout(MapDescription <TRoom> mapDescription, ILayoutGenerator <MapDescription <TRoom>, IMapLayout <TRoom> > generator, int timeout = 0, bool showDebugInfo = false)
        {
            IMapLayout <TRoom> layout = null;
            var task = Task.Run(() => layout = generator.GetLayouts(mapDescription, 1)[0]);

            if (timeout > 0)
            {
                var taskCompleted = task.Wait(timeout);

                if (!taskCompleted)
                {
                    throw new DungeonGeneratorException("Timeout was reached when generating the layout");
                }
            }

            if (showDebugInfo)
            {
                PrintGeneratorStats((IBenchmarkableLayoutGenerator <MapDescription <TRoom>, IMapLayout <TRoom> >)generator);
            }

            return(layout);
        }
Exemple #14
0
        /// <summary>
        /// Draws a given layout and returns a string with SVG data.
        /// </summary>
        /// <param name="layout"></param>
        /// <param name="width">Result will have this width and height will be computed to match the layout.</param>
        /// <param name="showRoomNames"></param>
        /// <param name="fixedFontSize"></param>
        /// <returns></returns>
        public string DrawLayout(IMapLayout <TNode> layout, int width, bool showRoomNames = true, int?fixedFontSize = null, bool forceSquare = false)
        {
            if (width <= 0)
            {
                throw new ArgumentException("Width must be greater than zero.", nameof(width));
            }

            var ratio  = GetWidthHeightRatio(layout);
            var height = forceSquare ? width : (int)(width / ratio);

            data.AppendLine($"<svg width=\"{width}\" height=\"{height}\" xmlns=\"http://www.w3.org/2000/svg\">");

            DrawLayout(layout, width, height, showRoomNames, fixedFontSize, 0.1f);

            data.AppendLine("</svg>");

            var svgData = data.ToString();

            data.Clear();

            return(svgData);
        }
Exemple #15
0
        /// <summary>
        /// Draws a given layout and returns a bitmap.
        /// </summary>
        /// <param name="layout"></param>
        /// <param name="width">Result will have this width and height will be computed to match the layout.</param>
        /// <param name="height"></param>
        /// <param name="withNames"></param>
        /// <param name="fixedFontSize"></param>
        /// <returns></returns>
        public Bitmap DrawLayout(IMapLayout <TNode> layout, int width, int height, bool withNames = true, int?fixedFontSize = null)
        {
            bitmap   = new Bitmap(width, height);
            graphics = Graphics.FromImage(bitmap);

            var textureImgOuter = new Bitmap(TextureOutterPath);

            using (var brush = new TextureBrush(textureImgOuter, WrapMode.Tile))
            {
                graphics.FillRectangle(brush, 0, 0, bitmap.Width, bitmap.Height);
            }

            var textureImgInner = new Bitmap(TextureInnerPath);

            innerBrush = new TextureBrush(textureImgInner, WrapMode.Tile);

            var textureImgOutline = new Bitmap(TexturePenPath);

            outlineBrush = new TextureBrush(textureImgOutline, WrapMode.Tile);

            outlinePen = new Pen(outlineBrush, 2)
            {
                EndCap   = LineCap.Square,
                StartCap = LineCap.Square
            };

            base.DrawLayout(layout, width, height, withNames, fixedFontSize);

            textureImgInner.Dispose();
            innerBrush.Dispose();

            textureImgOutline.Dispose();
            outlineBrush.Dispose();
            outlinePen.Dispose();

            return(bitmap);
        }
Exemple #16
0
 public GeneratedLevel(Dictionary <Room, RoomInstance> roomInstances, IMapLayout <Room> mapLayout, GameObject rootGameObject)
 {
     this.roomInstances = roomInstances;
     this.mapLayout     = mapLayout;
     RootGameObject     = rootGameObject;
 }
 public static GeneratedLevel TransformLayout(IMapLayout <Room> layout, LevelDescription levelDescription, GameObject rootGameObject)
 {
     return(null);
 }
        public static GeneratedLevel TransformLayout(IMapLayout <Room> layout, LevelDescription levelDescription, GameObject rootGameObject)
        {
            // var layoutCenter = GetLayoutCenter(layout);
            var prefabToRoomTemplateMapping = levelDescription.GetPrefabToRoomTemplateMapping();
            var corridorToConnectionMapping = levelDescription.GetCorridorToConnectionMapping();

            var roomTransformations = new RoomTransformations();

            // Prepare an object to hold instantiated room templates
            var roomTemplateInstancesRoot = new GameObject("Room template instances");

            roomTemplateInstancesRoot.transform.parent = rootGameObject.transform;

            // Initialize rooms
            var layoutData  = new Dictionary <Room, RoomInstance>();
            var layoutRooms = layout.Rooms.ToDictionary(x => x.Node, x => x);

            foreach (var layoutRoom in layoutRooms.Values)
            {
                var roomTemplatePrefab = prefabToRoomTemplateMapping.GetByValue(layoutRoom.RoomTemplate);

                // Instantiate room template
                var roomTemplateInstance = Object.Instantiate(roomTemplatePrefab);
                roomTemplateInstance.transform.SetParent(roomTemplateInstancesRoot.transform);

                // Transform room template if needed
                var transformation = layoutRoom.Transformation;
                roomTransformations.Transform(roomTemplateInstance, transformation);

                // Compute correct room position
                var position = layoutRoom.Position.ToUnityIntVector3();
                roomTemplateInstance.transform.position = position;

                // Compute outline polygon
                var polygon = new Polygon2D(layoutRoom.Shape + layoutRoom.Position);

                var connection   = layoutRoom.IsCorridor ? corridorToConnectionMapping[layoutRoom.Node] : null;
                var roomInstance = new RoomInstance(layoutRoom.Node, layoutRoom.IsCorridor, connection, roomTemplatePrefab, roomTemplateInstance, position, polygon);

                // Add room info to the GameObject
                var roomInfo = roomTemplateInstance.GetComponent <RoomInfo>();

                if (roomInfo != null)
                {
                    PostProcessUtils.Destroy(roomInfo);
                }

                roomInfo = roomTemplateInstance.AddComponent <RoomInfo>();
                roomInfo.RoomInstance = roomInstance;

                layoutData.Add(layoutRoom.Node, roomInstance);
            }

            foreach (var roomInstance in layoutData.Values)
            {
                roomInstance.SetDoors(TransformDoorInfo(layoutRooms[roomInstance.Room].Doors, layoutData));
            }

            // Add level info
            var levelInfo = rootGameObject.GetComponent <LevelInfo>();

            if (levelInfo != null)
            {
                PostProcessUtils.Destroy(levelInfo);
            }

            levelInfo = rootGameObject.AddComponent <LevelInfo>();
            levelInfo.RoomInstances = layoutData.Values.ToList();

            return(new GeneratedLevel(layoutData, layout, rootGameObject));
        }
Exemple #19
0
        /// <summary>
        /// Run the generator.
        /// </summary>
        private void Run()
        {
            cancellationTokenSource = new CancellationTokenSource();
            var ct = cancellationTokenSource.Token;

            task = Task.Run(() =>
            {
                try
                {
                    dumpFolder          = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds().ToString();
                    dumpCount           = 0;
                    var layoutGenerator = settings.LayoutGenerator;

                    if (layoutGenerator == null)
                    {
                        if (settings.MapDescription.IsWithCorridors)
                        {
                            var defaultGenerator =
                                LayoutGeneratorFactory.GetChainBasedGeneratorWithCorridors <int>(settings.MapDescription.CorridorsOffsets);
                            defaultGenerator.InjectRandomGenerator(new Random(settings.RandomGeneratorSeed));

                            layoutGenerator = defaultGenerator;
                        }
                        else
                        {
                            var defaultGenerator = LayoutGeneratorFactory.GetDefaultChainBasedGenerator <int>();
                            defaultGenerator.InjectRandomGenerator(new Random(settings.RandomGeneratorSeed));

                            layoutGenerator = defaultGenerator;
                        }
                    }

                    // Set cancellation token
                    if (layoutGenerator is ICancellable cancellable)
                    {
                        cancellable.SetCancellationToken(ct);
                    }

                    infoStopwatch.Start();

                    // Register handler that shows generated layouts OnValid
                    layoutGenerator.OnValid += layout =>
                    {
                        if (!showFinalLayouts.Checked)
                        {
                            return;
                        }

                        lastEvent    = GeneratorEvent.OnValid;
                        layoutToDraw = layout;
                        mainPictureBox.BeginInvoke((Action)(() => mainPictureBox.Refresh()));
                        SleepWithFastCancellation((int)showFinalLayoutsTime.Value, ct);
                    };

                    // Register handler that shows generated layouts OnPartialValid
                    layoutGenerator.OnPartialValid += layout =>
                    {
                        if (!showPartialValidLayouts.Checked)
                        {
                            return;
                        }

                        lastEvent    = GeneratorEvent.OnPartialValid;
                        layoutToDraw = layout;
                        mainPictureBox.BeginInvoke((Action)(() => mainPictureBox.Refresh()));
                        SleepWithFastCancellation((int)showAcceptedLayoutsTime.Value, ct);
                    };

                    // Register handler that shows generated layouts OnPerturbed
                    layoutGenerator.OnPerturbed += layout =>
                    {
                        if (!showPerturbedLayouts.Checked)
                        {
                            return;
                        }

                        lastEvent    = GeneratorEvent.OnPerturbed;
                        layoutToDraw = layout;
                        mainPictureBox.BeginInvoke((Action)(() => mainPictureBox.Refresh()));
                        SleepWithFastCancellation((int)showPerturbedLayoutsTime.Value, ct);
                    };

                    // Register handler that counts iteration count
                    layoutGenerator.OnPerturbed += layout =>
                    {
                        lastEvent = GeneratorEvent.OnPerturbed;
                        iterationsCount++;
                        if (infoStopwatch.ElapsedMilliseconds >= 200)
                        {
                            BeginInvoke((Action)(UpdateInfoPanel));
                            infoStopwatch.Restart();
                        }
                    };

                    // Register handler that resets iteration count
                    layoutGenerator.OnValid += layout =>
                    {
                        lastEvent       = GeneratorEvent.OnValid;
                        iterationsCount = 0;
                        layoutsCount++;
                        BeginInvoke((Action)(UpdateInfoPanel));
                        infoStopwatch.Restart();
                    };

                    generatedLayouts =
                        (List <IMapLayout <int> >)layoutGenerator.GetLayouts(settings.MapDescription, settings.NumberOfLayouts);

                    isRunning = false;
                    BeginInvoke((Action)(UpdateInfoPanel));
                    BeginInvoke((Action)(OnFinished));
                }
                catch (Exception e)
                {
                    ShowExceptionAndClose(e);
                }
            }, ct);
        }
        public override IEnumerator Process()
        {
            var config           = Config.Config;
            var levelDescription = Payload.LevelDescription;

            if (config.Timeout <= 0)
            {
                throw new ArgumentException($"{nameof(config.Timeout)} must be greater than 0", nameof(config.Timeout));
            }

            var rootGameObject = config.RootGameObject;

            if (rootGameObject == null)
            {
                rootGameObject = GameObject.Find("Generated Level");

                if (rootGameObject == null)
                {
                    rootGameObject = new GameObject("Generated Level");
                }
            }

            foreach (var child in rootGameObject.transform.Cast <Transform>().ToList())
            {
                child.transform.parent = null;
                PostProcessUtils.Destroy(child.gameObject);
            }

            var mapDescription = levelDescription.GetMapDescription();
            var configuration  = new DungeonGeneratorConfiguration <Room>(mapDescription)
            {
                RoomsCanTouch           = false,
                RepeatModeOverride      = GeneratorUtils.GetRepeatMode(config.RepeatModeOverride),
                EarlyStopIfTimeExceeded = TimeSpan.FromMilliseconds(config.Timeout),
            };

            var generator = new DungeonGenerator <Room>(mapDescription, configuration);

            generator.InjectRandomGenerator(Payload.Random);

            IMapLayout <Room> layout = null;
            var task = Task.Run(() => layout = generator.GenerateLayout());

            while (!task.IsCompleted)
            {
                yield return(null);
            }

            if (layout == null)
            {
                throw new InvalidOperationException("Timeout was reached when generating level");
            }

            var generatedLevel = GeneratorUtils.TransformLayout(layout, levelDescription, rootGameObject);
            var stats          = new GeneratorStats()
            {
                Iterations = generator.IterationsCount,
                TimeTotal  = generator.TimeTotal,
            };

            Debug.Log($"Layout generated in {stats.TimeTotal / 1000f:F} seconds");
            Debug.Log($"{stats.Iterations} iterations needed, {stats.Iterations / (stats.TimeTotal / 1000d):0} iterations per second");

            ((IGraphBasedGeneratorPayload)Payload).GeneratedLevel = generatedLevel;
            Payload.GeneratorStats = stats;

            yield return(null);
        }
 /// <summary>
 /// If you want to update MapLayout, override it and rewrite this methods
 /// </summary>
 /// <param name="mapLayout"></param>
 /// <returns></returns>
 protected virtual IMapLayout RefreshMapLayout(IMapLayout mapLayout)
 {
     return(mapLayout);
 }
        private void ReloadLayoutInCanvas(IMapLayout map)
        {
            Children.Clear();

            UndoStack.Clear();
            RedoStack.Clear();


            var diagrams = map.Diagrams;

            if (diagrams == null || !diagrams.Any())
            {
                return;
            }

            Dictionary <string, ILineLayout[]> uuidLines = new Dictionary <string, ILineLayout[]>();

            foreach (var diagram in diagrams)
            {
                var clnele = Activator.CreateInstance(diagram.DiagramUIType) as UIElement;

                if (clnele is ContentControl)
                {
                    (clnele as ContentControl).DataContext = diagram.DataContext;
                }

                //add the line by Diagram ActionComment after finish all diagrams
                uuidLines.Add(diagram.DiagramUUID, diagram.DepartureLines);

                Application.Current.Dispatcher.Invoke(() =>
                {
                    Canvas.SetRight(clnele, diagram.X);
                    Canvas.SetLeft(clnele, diagram.X);
                    Canvas.SetBottom(clnele, diagram.Y);
                    Canvas.SetTop(clnele, diagram.Y);


                    Children.Add(clnele);
                });
            }

            //update the canvas.
            UpdateLayout();


            foreach (var dialines in uuidLines)
            {
                ConnectionDiagramBase origindiagram = GetDiagramByUUID(dialines.Key);
                if (origindiagram != null && dialines.Value != null)
                {
                    foreach (var defline in dialines.Value)
                    {
                        var terminaldiagram = GetDiagramByUUID(defline.TerminalDiagramUUID);

                        dynamic conline;

                        if (terminaldiagram != null)
                        {
                            conline = Activator.CreateInstance(defline.LineUIType);

                            Assist.FrameworkElementAssist.SetOriginDiagram(conline, origindiagram);
                            Assist.FrameworkElementAssist.SetTerminalDiagram(conline, terminaldiagram);

                            if (conline is ConnectionLineBase)
                            {
                                //(conline as ConnectionLineBase).OriginDiagram = origindiagram;
                                //(conline as ConnectionLineBase).TerminalDiagram = terminaldiagram;
                                (conline as ConnectionLineBase).DataContext = defline.DataContext;
                                (conline as ConnectionLineBase).LineUUID    = string.IsNullOrWhiteSpace(defline.LineUUID) ? $"{conline.GetType().Name}_{Guid.NewGuid().ToString()}" : defline.LineUUID;


                                //TODOTODOTODO!!!!
                                //TODO: Posistion Recaluter
                                if (conline is ILinePosition)
                                {
                                    (conline as ILinePosition).X1 = (double)origindiagram.GetValue(Canvas.LeftProperty) - (double)terminaldiagram.GetValue(Canvas.LeftProperty) + origindiagram.CenterPosition.X;
                                    (conline as ILinePosition).Y1 = (double)origindiagram.GetValue(Canvas.TopProperty) - (double)terminaldiagram.GetValue(Canvas.TopProperty) + origindiagram.CenterPosition.Y;;
                                    (conline as ILinePosition).X2 = terminaldiagram.CenterPosition.X;
                                    (conline as ILinePosition).Y2 = terminaldiagram.CenterPosition.Y;
                                }

                                origindiagram.DepartureLines.Add(conline);
                                terminaldiagram.ArrivalLines.Add(conline);
                            }
                            Application.Current.Dispatcher.Invoke(() =>
                            {
                                Canvas.SetTop(conline, (double)terminaldiagram.GetValue(Canvas.TopProperty));
                                Canvas.SetLeft(conline, (double)terminaldiagram.GetValue(Canvas.LeftProperty));

                                Children.Add(conline);
                            });
                        }
                    }
                }
            }
        }