public void Render(RenderOpts opts) { _graphics.Clear(BgColor); DrawGrid(); DrawSiliconAndMetal(opts); if (opts.SelectionState != SelectionState.None) { DrawSelectionBorder(opts.Selection); } }
private void DrawSiliconAndMetal(RenderOpts opts) { var namedCells = new List <ILayerCell>(); var(from, to) = opts.Selection?.ToFieldPositions() ?? default((Position, Position)); for (var i = 0; i < _layer.Height; i++) { for (var j = 0; j < _layer.Width; j++) { if (opts.SelectionState != SelectionState.None) { var isInXRange = j >= from.X && j < to.X; var isInYRange = i >= from.Y && i < to.Y; if (!isInXRange || !isInYRange) { DrawCell(opts, i, j, from, to, namedCells); } } else { DrawCell(opts, i, j, from, to, namedCells); } } } // dragging cells should be rendered over if (opts.SelectionState != SelectionState.None) { for (var i = from.Y; i < to.Y; i++) { for (var j = from.X; j < to.X; j++) { DrawCell(opts, i, j, from, to, namedCells); } } } foreach (var zone in _layer.Template.DeadZones) { var zoneRect = new Rectangle( zone.Origin.X * (CellSize + 1), zone.Origin.Y * (CellSize + 1), zone.Width * (CellSize + 1) + 1, zone.Height * (CellSize + 1) + 1); _graphics.FillRectangle(LockedRegionBrush, zoneRect); } foreach (var cell in namedCells) { var pin = cell.Pin; var bounds = GetCellBounds(cell.Column, cell.Row); bounds.Width += CellSize * (pin.Width - 1); bounds.Height += CellSize * (pin.Height - 1); bounds.X += 1; bounds.Y += 1; var centerX = bounds.Left + bounds.Width / 2; var centerY = bounds.Top + bounds.Height / 2; _graphics.FillRectangle(Brushes.WhiteSmoke, bounds); var name = cell.Pin?.Name ?? "XZ"; var measure = _graphics.MeasureString(name, PinNameFont); if (opts.Assignments != null) { var assignments = opts.Assignments[cell.Row, cell.Column]; if ((assignments.LastAssignedSiliconNode == opts.HoveredNode || assignments.LastAssignedMetalNode == opts.HoveredNode) && opts.HoveredNode != null) { var fillBounds = bounds; fillBounds.Inflate(-1, -1); FillTopologyPlace(fillBounds, assignments.LastAssignedMetalNode == opts.HoveredNode); } } _graphics.DrawString(name, PinNameFont, Brushes.Black, centerX - measure.Width / 2, centerY - measure.Height / 2); } }
private void DrawCell(RenderOpts opts, int i, int j, Position from, Position to, List <ILayerCell> namedCells) { var cell = _layer.Cells[i, j]; var bounds = GetCellBounds(j, i); var isInXRange = j >= from.X && j < to.X; var isInYRange = i >= from.Y && i < to.Y; if (isInXRange && isInYRange) { bounds.Offset(opts.Selection.DragOffsetX, opts.Selection.DragOffsetY); } var isLeftSideDetached = (j == to.X || j == from.X) && isInYRange; var isTopSideDetached = (i == to.Y || i == from.Y) && isInXRange; var isRightSideDetached = (j == to.X - 1 || j == from.X - 1) && isInYRange; var isBottomSideDetached = (i == to.Y - 1 || i == from.Y - 1) && isInXRange; if (cell.HasSilicon()) { var(_, brush, gateBrush) = SelectSiliconBrush(cell); FillMid(cell.HasGate() ? gateBrush : brush, bounds); SiliconCellSide(cell, Side.Top, bounds, isTopSideDetached); SiliconCellSide(cell, Side.Bottom, bounds, isBottomSideDetached); SiliconCellSide(cell, Side.Left, bounds, isLeftSideDetached); SiliconCellSide(cell, Side.Right, bounds, isRightSideDetached); SiliconCellCorner(cell, Corner.Near, bounds, isTopSideDetached, isLeftSideDetached); SiliconCellCorner(cell, Corner.FarX, bounds, isTopSideDetached, isRightSideDetached); SiliconCellCorner(cell, Corner.FarY, bounds, isBottomSideDetached, isLeftSideDetached); SiliconCellCorner(cell, Corner.Far, bounds, isBottomSideDetached, isRightSideDetached); if (!isLeftSideDetached) { SiliconIntercellular(cell, false, cell.Links[0]?.SiliconLink ?? SiliconLink.None, bounds); } if (!isTopSideDetached) { SiliconIntercellular(cell, true, cell.Links[1]?.SiliconLink ?? SiliconLink.None, bounds); } if (cell.HasVia()) // in original game vias displaying under metal layer { var viaX = bounds.X + (bounds.Width - ViaSize) / 2; var viaY = bounds.Y + (bounds.Height - ViaSize) / 2; _graphics.DrawLine(BorderPen, viaX + 1, viaY, viaX + ViaSize - 2, viaY); _graphics.DrawLine(BorderPen, viaX + 1, viaY + ViaSize - 1, viaX + ViaSize - 2, viaY + ViaSize - 1); _graphics.DrawLine(BorderPen, viaX, viaY + 1, viaX, viaY + ViaSize - 2); _graphics.DrawLine(BorderPen, viaX + ViaSize - 1, viaY + 1, viaX + ViaSize - 1, viaY + ViaSize - 2); } } if (cell.HasMetal) { FillMid(MetalBrush, bounds); MetalCellSide(cell, Side.Top, bounds, isTopSideDetached); MetalCellSide(cell, Side.Bottom, bounds, isBottomSideDetached); MetalCellSide(cell, Side.Left, bounds, isLeftSideDetached); MetalCellSide(cell, Side.Right, bounds, isRightSideDetached); MetalCellCorner(cell, Corner.Near, bounds, isTopSideDetached, isLeftSideDetached); MetalCellCorner(cell, Corner.FarX, bounds, isTopSideDetached, isRightSideDetached); MetalCellCorner(cell, Corner.FarY, bounds, isBottomSideDetached, isLeftSideDetached); MetalCellCorner(cell, Corner.Far, bounds, isBottomSideDetached, isRightSideDetached); if (!isLeftSideDetached) { MetalIntercellular(cell, false, bounds); } if (!isTopSideDetached) { MetalIntercellular(cell, true, bounds); } } if (opts.Assignments != null) { var assignments = opts.Assignments[i, j]; if ((assignments.LastAssignedSiliconNode == opts.HoveredNode || assignments.LastAssignedMetalNode == opts.HoveredNode) && opts.HoveredNode != null) { var fillBounds = bounds; fillBounds.Inflate(-1, -1); FillTopologyPlace(fillBounds, assignments.LastAssignedMetalNode == opts.HoveredNode); } } if (cell.Pin != null) { namedCells.Add(cell); } }