Archived
Private
Public Access
1
0

Initial commit

This commit is contained in:
2022-09-04 12:45:01 +02:00
commit f4a01d6a69
11601 changed files with 4206660 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class ButtonInput : Gate {
private bool _powered;
protected override void InternalSetup(Canvas canvas) {
Shape = new Ellipse();
SetOutputs(1);
SetInputs(0);
CreateConnections();
Shape.MouseLeftButtonDown += (sender, args) => {
if (IsAttached) return;
_powered = true;
Update(this);
};
Shape.MouseLeftButtonUp += (sender, args) => {
if (IsAttached) return;
_powered = false;
Update(this);
};
Text = "B";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = _powered;
Shape.Fill = _powered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
UpdateShapes();
UpdateConnectedGates(source);
}
public ButtonInput(double x, double y) : base(x, y, 20, 20) { }
}
}

308
C#/DigiSim/Logic/Gate.cs Normal file
View File

@@ -0,0 +1,308 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public abstract class Gate {
private TextBlock _textBlock;
private MouseEventHandler _onMove;
private MouseEventHandler _onLeave;
private MouseButtonEventHandler _onUp;
private MouseButtonEventHandler _onDown;
private MouseButtonEventHandler _onDelete;
protected bool IsAttached;
public Point Position { get; private set; }
public Size Size { get; protected set; }
protected Shape Shape { get; set; }
protected Tuple<Tuple<Shape, Shape>, Line>[] ConnectorLines { get; set; }
public Ellipse[] InputShapes { get; protected set; }
public Ellipse[] OutputShapes { get; protected set; }
public Wire[] ConnectedInputs { get; protected set; }
public Wire[] ConnectedOutputs { get; protected set; }
protected Dictionary<bool, bool, bool> TruthTable { get; set; }
protected string Text { get; set; }
public bool IsDeleted { get; private set; }
protected Gate(double x, double y, double width, double height) {
Constructor(x, y, width, height);
}
protected Gate() {}
protected void Constructor(double x, double y, double width, double height) {
Position = new Point(x, y);
Size = new Size(width, height);
_textBlock = new TextBlock()
{TextAlignment = TextAlignment.Center, Foreground = Brushes.White, FontSize = 15, IsHitTestVisible = false };
Setup(Window.Board);
Shape.Fill = FromHex(Window.FillColor);
}
private void Setup(Canvas canvas) {
TruthTable = new Dictionary<bool, bool, bool>();
_onMove = (sender, e) => {
if (IsAttached) {
Point mouse = Mouse.GetPosition(canvas);
Position = new Point(
mouse.X - Size.Width / 2,
mouse.Y - Size.Height / 2
);
Update(this);
}
else if (Mouse.LeftButton == MouseButtonState.Pressed && e.OriginalSource.Equals(Shape) && Window.CurrentConnection == null)
AttachToMouse();
};
_onUp = (s, e) => IsAttached = false;
_onLeave = (s, e) => IsAttached = false;
_onDown = (sender, e) => {
if (IsAttached) return;
if (ConnectedOutputs != null) {
for (int i = 0; i < ConnectedOutputs.Length; i++) {
if (IsMouseOver(OutputShapes[i])) {
Window.StartConnectingGates(this, i);
return;
}
}
}
if (ConnectedInputs != null) {
for (int i = 0; i < ConnectedInputs.Length; i++) {
Wire wire = ConnectedInputs[i];
if (IsMouseOver(InputShapes[i])) {
wire.Delete();
return;
}
}
}
};
_onDelete = (sender, e) => {
if (e.OriginalSource.Equals(Shape))
Window.DeleteGate(this);
};
canvas.MouseMove += _onMove;
canvas.MouseLeave += _onLeave;
canvas.MouseUp += _onUp;
canvas.MouseDown += _onDown;
canvas.MouseRightButtonUp += _onDelete;
InternalSetup(canvas);
if (InputShapes != null) ConnectedInputs = Enumerable.Repeat(new Wire(), InputShapes.Length).ToArray();
if (OutputShapes != null) ConnectedOutputs = Enumerable.Repeat(new Wire(), OutputShapes.Length).ToArray();
Update(this);
}
public void AttachToMouse() {
IsAttached = true;
}
protected abstract void InternalSetup(Canvas canvas);
public abstract void Update(Gate source);
protected void UpdateShapes() {
Shape.Width = Size.Width;
Shape.Height = Size.Height;
Canvas.SetLeft(Shape, Position.X);
Canvas.SetTop(Shape, Position.Y);
Canvas.SetZIndex(Shape, 10);
double outSpace = Size.Height / OutputShapes.Length;
for (int i = 0; i < OutputShapes.Length; i++) {
Shape shape = OutputShapes[i];
shape.Width = 10;
shape.Height = 10;
shape.Fill = ConnectedOutputs[i].IsPowered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
Canvas.SetLeft(shape, Position.X + Size.Width + 5);
Canvas.SetTop(shape, Position.Y + outSpace * i + outSpace / 2 - 5);
Canvas.SetZIndex(shape, 2);
}
double inSpace = Size.Height / InputShapes.Length;
for (int i = 0; i < InputShapes.Length; i++) {
Shape shape = InputShapes[i];
shape.Width = 10;
shape.Height = 10;
shape.Fill = ConnectedInputs[i].IsPowered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
Canvas.SetLeft(shape, Position.X - 15);
Canvas.SetTop(shape, Position.Y + inSpace * i + inSpace / 2 - 5);
Canvas.SetZIndex(shape, 2);
}
foreach (var line in ConnectorLines) {
Tuple<Shape, Shape> t = line.Item1;
Point p1 = new Point(Canvas.GetLeft(t.Item1) + t.Item1.Width / 2, 0);
Point p2 = new Point(Canvas.GetLeft(t.Item2) + t.Item2.Width / 2,
Canvas.GetTop(t.Item2) + t.Item2.Height / 2);
line.Item2.Stroke = FromHex(Window.FillColor);
line.Item2.StrokeThickness = 1;
line.Item2.X1 = p1.X;
line.Item2.X2 = p2.X;
line.Item2.Y1 = p2.Y;
line.Item2.Y2 = p2.Y;
Canvas.SetZIndex(line.Item2, 1);
}
_textBlock.Width = Size.Width;
_textBlock.Height = Size.Height;
Canvas.SetLeft(_textBlock, Position.X);
Canvas.SetTop(_textBlock, Position.Y);
Canvas.SetZIndex(_textBlock, 11);
_textBlock.Text = Text;
}
protected void UpdateConnectedGates(Gate source) {
if (ConnectedOutputs != null) {
foreach (var output in ConnectedOutputs) {
if (output != null)
output.Update();
else continue;
if (output.Site2 != null) {
if (output.Site2 != source)
output.Site2.Update(source);
}
}
}
if (ConnectedInputs != null) {
foreach (var input in ConnectedInputs) {
if (input != null)
input.Update();
}
}
}
protected void SetInputs(int count) {
InputShapes = new Ellipse[count];
for (int i = 0; i < count; i++) {
InputShapes[i] = new Ellipse();
}
}
protected void SetOutputs(int count) {
OutputShapes = new Ellipse[count];
for (int i = 0; i < count; i++) {
OutputShapes[i] = new Ellipse();
}
}
protected void CreateConnections() {
List<Tuple<Tuple<Shape, Shape>, Line>> connections = new List<Tuple<Tuple<Shape, Shape>, Line>>();
foreach (var inputShape in InputShapes) {
connections.Add(new Tuple<Tuple<Shape, Shape>, Line>(new Tuple<Shape, Shape>(Shape, inputShape), new Line()));
}
foreach (var outputShape in OutputShapes) {
connections.Add(new Tuple<Tuple<Shape, Shape>, Line>(new Tuple<Shape, Shape>(Shape, outputShape), new Line()));
}
ConnectorLines = connections.ToArray();
}
protected void Instantiate() {
foreach (var connectorLine in ConnectorLines) {
Window.Board.Children.Add(connectorLine.Item2);
}
foreach (var inputShape in InputShapes) {
Window.Board.Children.Add(inputShape);
}
foreach (var outputShape in OutputShapes) {
Window.Board.Children.Add(outputShape);
}
Window.Board.Children.Add(Shape);
Window.Board.Children.Add(_textBlock);
}
public void Delete() {
IsDeleted = true;
Window.Board.MouseMove -= _onMove;
Window.Board.MouseLeave -= _onLeave;
Window.Board.MouseUp -= _onUp;
Window.Board.MouseDown -= _onDown;
Window.Board.MouseRightButtonUp -= _onDelete;
Window.Board.Children.Remove(Shape);
Window.Board.Children.Remove(_textBlock);
foreach (var connectorLine in ConnectorLines) {
Window.Board.Children.Remove(connectorLine.Item2);
}
foreach (var inputShape in InputShapes) {
Window.Board.Children.Remove(inputShape);
}
foreach (var outputShape in OutputShapes) {
Window.Board.Children.Remove(outputShape);
}
foreach (var connectedInput in ConnectedInputs) {
connectedInput.Delete();
}
ConnectedInputs = null;
foreach (var connectedOutput in ConnectedOutputs) {
connectedOutput.Delete();
}
ConnectedOutputs = null;
}
// STATIC UTILITIY METHODS
private static Rect GetBounds(Shape shape) {
return shape.TransformToVisual(Window.Board)
.TransformBounds(new Rect(0, 0, shape.ActualWidth, shape.ActualHeight));
}
public static bool CheckBoundingIntersection(Shape shape1, Shape shape2) {
return GetBounds(shape1).IntersectsWith(GetBounds(shape2));
}
public static bool IsMouseOver(Shape shape) {
return GetBounds(shape).Contains(Mouse.GetPosition(Window.Board));
}
public static SolidColorBrush FromHex(String hex) {
return (SolidColorBrush)new BrushConverter().ConvertFromString(hex);
}
}
public class Dictionary<TKey1,TKey2,TValue> : Dictionary<Tuple<TKey1, TKey2>, TValue>, IDictionary<Tuple<TKey1, TKey2>, TValue>
{
public TValue this[TKey1 key1, TKey2 key2]
{
get { return base[Tuple.Create(key1, key2)]; }
set { base[Tuple.Create(key1, key2)] = value; }
}
public void Add(TKey1 key1, TKey2 key2, TValue value)
{
base.Add(Tuple.Create(key1, key2), value);
}
public bool ContainsKey(TKey1 key1, TKey2 key2)
{
return base.ContainsKey(Tuple.Create(key1, key2));
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class AndGate : Gate {
public AndGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, false);
TruthTable.Add(false, true, false);
TruthTable.Add(true, false, false);
TruthTable.Add(true, true, true);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "&";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class CustomGate : Gate {
public int Inputs { get; }
public int Outputs { get; }
public string Symbol { get; }
public LookupTable Lookup { get; }
public CustomGate(double x, double y) : base(x, y, 50, 50) { }
private CustomGate(string symbol, LookupTable lookup) {
Symbol = symbol;
Lookup = lookup;
Inputs = lookup.InputCount;
Outputs = lookup.OutputCount;
Constructor(0, 0, 0, 0);
}
protected override void InternalSetup(Canvas canvas) {
Shape = new Rectangle();
int connectorCount = Math.Max(Inputs, Outputs);
Size = new Size(50, connectorCount * 25);
SetInputs(Inputs);
SetOutputs(Outputs);
CreateConnections();
Text = Symbol;
Instantiate();
}
public override void Update(Gate source) {
bool[] snapshot = new bool[ConnectedInputs.Length];
for (var i = 0; i < snapshot.Length; i++) {
snapshot[i] = ConnectedInputs[i].IsPowered;
}
bool[] outputs = Lookup.GetOutputs(snapshot);
for (var i = 0; i < ConnectedOutputs.Length; i++) {
ConnectedOutputs[i].IsPowered = outputs[i];
}
UpdateShapes();
UpdateConnectedGates(source);
}
public struct LookupTable {
public bool[,] Inputs { get; }
public bool[,] Outputs { get; }
public int InputCount { get; }
public int OutputCount { get; }
public int Length { get; }
public LookupTable(int inputCount, int outputCount, int length) {
Inputs = new bool[length, inputCount];
Outputs = new bool[length, outputCount];
InputCount = inputCount;
OutputCount = outputCount;
Length = length;
}
public bool[] GetOutputs(bool[] inputs) {
if (inputs.Length != InputCount) throw new ArgumentOutOfRangeException(nameof(inputs));
for (int i = 0; i < Length; i++) {
bool found = true;
for (int j = 0; j < InputCount; j++) {
if (Inputs[i, j] != inputs[j]) {
found = false;
break;
}
}
if (found) {
bool[] output = new bool[OutputCount];
for (int o = 0; o < OutputCount; o++) {
output[o] = Outputs[i, o];
}
return output;
}
}
return new bool[OutputCount];
}
public void SetLookup(bool[] inputs, bool[] outputs, int index) {
if (index >= Length) throw new IndexOutOfRangeException(nameof(index));
for (var i = 0; i < inputs.Length; i++) {
Inputs[index, i] = inputs[i];
}
for (var i = 0; i < outputs.Length; i++) {
Outputs[index, i] = outputs[i];
}
}
}
private static LookupTable CreateLookup(Gate[] gates) {
List<Input> inputs = new List<Input>();
List<Output> outputs = new List<Output>();
foreach (var gate in gates) {
if (gate is Input)
inputs.Add(gate as Input);
if (gate is Output)
outputs.Add(gate as Output);
}
int possibilities = (int) Math.Pow(2, inputs.Count);
LookupTable lookupTable = new LookupTable(inputs.Count, outputs.Count, possibilities);
for (var i = 0; i < possibilities; i++) {
bool[] inputSequenze = new bool[inputs.Count];
bool[] outputSequenze = new bool[outputs.Count];
char[] sequenze = Convert.ToString(i, 2).PadLeft(inputs.Count, '0').ToCharArray();
for (var j = 0; j < sequenze.Length; j++) {
inputSequenze[j] = sequenze[j] == '1';
inputs[j].Powered = sequenze[j] == '1';
inputs[j].Update(inputs[j]);
}
for (var j = 0; j < outputs.Count; j++) {
outputSequenze[j] = outputs[j].ConnectedInputs[0].IsPowered;
}
lookupTable.SetLookup(inputSequenze, outputSequenze, i);
}
return lookupTable;
}
public static CustomGate CreateCustomGateFromBoard(Gate[] gates, string symbol) {
return new CustomGate(symbol, CreateLookup(gates));
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class NandGate : Gate {
public NandGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, true);
TruthTable.Add(false, true, true);
TruthTable.Add(true, false, true);
TruthTable.Add(true, true, false);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "!&";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class NorGate : Gate {
public NorGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, true);
TruthTable.Add(false, true, false);
TruthTable.Add(true, false, false);
TruthTable.Add(true, true, false);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "!>1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class NotGate : Gate {
public NotGate(double x, double y) : base(x, y, 25, 25) { }
protected override void InternalSetup(Canvas canvas) {
Shape = new Rectangle();
SetInputs(1);
SetOutputs(1);
CreateConnections();
Text = "!1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = !ConnectedInputs[0].IsPowered;
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class OrGate : Gate {
public OrGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, false);
TruthTable.Add(false, true, true);
TruthTable.Add(true, false, true);
TruthTable.Add(true, true, true);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = ">1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class XnorGate : Gate {
public XnorGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, true);
TruthTable.Add(false, true, false);
TruthTable.Add(true, false, false);
TruthTable.Add(true, true, true);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "!=1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class XorGate : Gate {
public XorGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, false);
TruthTable.Add(false, true, true);
TruthTable.Add(true, false, true);
TruthTable.Add(true, true, false);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "=1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

34
C#/DigiSim/Logic/Input.cs Normal file
View File

@@ -0,0 +1,34 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class Input : Gate {
public bool Powered;
protected override void InternalSetup(Canvas canvas) {
Shape = new Ellipse();
SetOutputs(1);
SetInputs(0);
CreateConnections();
Shape.MouseLeftButtonUp += (sender, args) => {
if (IsAttached) return;
Powered = !Powered;
Update(this);
};
Text = "I";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = Powered;
Shape.Fill = Powered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
UpdateShapes();
UpdateConnectedGates(source);
}
public Input(double x, double y) : base(x, y, 20, 20) { }
}
}

View File

@@ -0,0 +1,26 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class Output : Gate {
public Output(double x, double y) : base(x, y, 20, 20) { }
protected override void InternalSetup(Canvas canvas) {
Shape = new Ellipse();
SetInputs(1);
SetOutputs(0);
CreateConnections();
Text = "O";
Instantiate();
}
public override void Update(Gate source) {
Shape.Fill = ConnectedInputs[0].IsPowered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,27 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class Splitter : Gate {
public Splitter(double x, double y) : base(x, y, 25, 25) { }
protected override void InternalSetup(Canvas canvas) {
Shape = new Rectangle();
SetOutputs(2);
SetInputs(1);
CreateConnections();
Text = "S";
Instantiate();
}
public override void Update(Gate source) {
bool input = ConnectedInputs[0].IsPowered;
ConnectedOutputs[0].IsPowered = input;
ConnectedOutputs[1].IsPowered = input;
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

74
C#/DigiSim/Logic/Wire.cs Normal file
View File

@@ -0,0 +1,74 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class Wire {
public Gate Site1 { get; set; }
public Gate Site2 { get; set; }
public int OutputIndex { get; set; }
public int InputIndex { get; set; }
public bool IsPowered { get; set; }
public Line Connection { get; }
public Wire() {
Connection = new Line();
Window.Board.Children.Add(Connection);
}
public void Update() {
if (Site1 == null || Site2 == null) return;
Shape site1 = Site1.OutputShapes[OutputIndex];
Shape site2 = Site2.InputShapes[InputIndex];
Point p1 = new Point(Canvas.GetLeft(site1) + site1.Width / 2,
Canvas.GetTop(site1) + site1.Height / 2);
Point p2 = new Point(Canvas.GetLeft(site2) + site2.Width / 2,
Canvas.GetTop(site2) + site2.Height / 2);
Connection.Stroke = IsPowered ? Gate.FromHex(Window.PoweredColor) : Gate.FromHex(Window.FillColor);
Connection.StrokeThickness = 1;
Connection.X1 = p1.X;
Connection.X2 = p2.X;
Connection.Y1 = p1.Y;
Connection.Y2 = p2.Y;
}
public void ConnectShapeToPoint(Shape shape, Point point) {
Point p1 = new Point(Canvas.GetLeft(shape) + shape.Width / 2,
Canvas.GetTop(shape) + shape.Height / 2);
Connection.Stroke = Gate.FromHex(Window.FillColor);
Connection.StrokeThickness = 1;
Connection.X1 = p1.X;
Connection.X2 = point.X;
Connection.Y1 = p1.Y;
Connection.Y2 = point.Y;
}
public void Delete() {
Window.Board.Children.Remove(Connection);
if (Site1 != null) {
if (!Site1.IsDeleted) {
Site1.ConnectedOutputs[OutputIndex] = new Wire();
Site1.Update(Site1);
}
}
if (Site2 != null) {
if (!Site2.IsDeleted) {
Site2.ConnectedInputs[InputIndex] = new Wire();
Site2.Update(Site2);
}
}
}
}
}