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); } } }
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); }
/// <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); }
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)); } }
private void slideshowRightButton_Click(object sender, EventArgs e) { automaticSlideshowCheckbox.Checked = false; if (slideshowIndex != generatedLayouts.Count - 1) { layoutToDraw = generatedLayouts[++slideshowIndex]; mainPictureBox.Refresh(); } UpdateSlideshowInfo(); }
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); }
/// <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); }
/// <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); }
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)); }
/// <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); }); } } } } }