public void UpdateSubnets(List <Wire> added, List <Wire> removed) { List <Subnet> checkSplitSubnets = new List <Subnet>(); foreach (var old in removed) { var startNet = FindSubnet(old.Pos); var endNet = FindSubnet(old.EndPos); // This is null if there was an error removing the wire Subnet?removedFromSubnet; if (startNet != null && endNet != null) { if (startNet == endNet) { // We are removing a wire from a subnet // So here we want to figure out if we have to split this subnet startNet.RemoveWire(old); // If there are wires left, we need to check if // the deletion led to any splits in the subnet if (startNet.Wires.Count > 0) { if (checkSplitSubnets.Contains(startNet) == false) { checkSplitSubnets.Add(startNet); } } removedFromSubnet = startNet; } else { // This is f***ed in more ways than one... Console.WriteLine($"Error! This should not happen! Trying to remove a wire containing to more than one subnet! (Wire: {old}, Subnet1: {startNet}, Subnet2:{endNet})"); removedFromSubnet = null; } } else if (startNet != null) { // We are removing from one subnet if (startNet.RemoveWire(old)) { Console.WriteLine($"Warn: Tried to remove a wire from a subnet that didn't contain that wire. (Wire: {old}, Subnet: {startNet})"); } removedFromSubnet = startNet; Console.WriteLine($"Removed wire to subnet: {startNet}"); } else if (endNet != null) { // We are removing from one subnet if (endNet.RemoveWire(old)) { Console.WriteLine($"Warn: Tried to remove a wire from a subnet that didn't contain that wire. (Wire: {old}, Subnet: {endNet})"); } removedFromSubnet = endNet; Console.WriteLine($"Removed wire to subnet: {endNet}"); } else { // Here we are removing a wire that didn't belong to any subnet!? Console.WriteLine($"Error! This should not happen! Trying to remove a wire not contained in any subnet! (Wire: {old})"); removedFromSubnet = null; } // If we removed a wire from a subnet, check if we need to deleted that subnet if (removedFromSubnet?.Wires.Count <= 0) { Console.WriteLine($"Removed subnet: {removedFromSubnet}"); LogikUI.Simulation.RemoveSubnet(removedFromSubnet.ID); removedFromSubnet.ID = SubnetID.Invalid; Subnets.Remove(removedFromSubnet); } } List <Subnet> addedSubnets = new List <Subnet>(); List <(Wire, Subnet)> addedWiresAndTheirNewSubnet = new List <(Wire, Subnet)>(); foreach (var @new in added) { var startNet = FindSubnet(@new.Pos); var endNet = FindSubnet(@new.EndPos); Subnet subnetAddedTo; if (startNet != null && endNet != null) { if (startNet == endNet) { // Here they are the same subnet. // So we just add the wire. startNet.AddWire(@new); subnetAddedTo = startNet; } else { // Figure out what subnet to merge into. var(merged, mergee) = startNet.ID != 0 ? (startNet, endNet) : (endNet, startNet); Console.WriteLine($"Merging subnet ({mergee}) into subnet ({merged})."); Subnets.Remove(mergee); merged.Merge(mergee); // Transfer over all of the added wires if there are any for (int i = 0; i < addedWiresAndTheirNewSubnet.Count; i++) { var(wire, subnet) = addedWiresAndTheirNewSubnet[i]; if (subnet == mergee) { addedWiresAndTheirNewSubnet[i] = (wire, merged); } } // Don't forget to add the wire that merged these subnets merged.AddWire(@new); subnetAddedTo = merged; Console.WriteLine($"\tResult: {merged}"); } } else if (startNet != null) { // Here we just add this wire to the subnet, // it's not going to change anything. startNet.AddWire(@new); subnetAddedTo = startNet; Console.WriteLine($"Added wire to subnet: {startNet}"); } else if (endNet != null) { // Here we just add this wire to the subnet, // it's not going to change anything. endNet.AddWire(@new); subnetAddedTo = endNet; Console.WriteLine($"Added wire to subnet: {endNet}"); } else { // This means that this wire should be in it's own subnet. // It might get merged into another subnet later though.. var sub = new Subnet(0); sub.AddWire(@new); addedSubnets.Add(sub); // NOTE: do we want to do this? Subnets.Add(sub); subnetAddedTo = sub; Console.WriteLine($"Added single wire subnet: {sub}"); } addedWiresAndTheirNewSubnet.Add((@new, subnetAddedTo)); } // Because we have figured out all of the merging we know // that all of the subnets in this list will have their own // id. When splitting we can only ever create new subnets // so we don't have to worry about merging so we give those // subnets their id directly when they are created. foreach (var addedNet in addedSubnets) { // Here we should figure out a new subnet id addedNet.ID = (SubnetID)SubnetIDCounter++; LogikUI.Simulation.AddSubnet(addedNet.ID); Console.WriteLine($"Added new subnet: {addedNet}"); } // Here we go though all new wires and their subnet to see if the new wires // connects any new components to the subnet. foreach (var(wire, subnet) in addedWiresAndTheirNewSubnet) { foreach (var comp in Gates.Instances) { // FIXME: This stackalloc is going to blow up... Span <Vector2i> portLocs = stackalloc Vector2i[Gates.GetNumberOfPorts(comp)]; Gates.GetTransformedPorts(comp, portLocs); for (int i = 0; i < portLocs.Length; i++) { var loc = portLocs[i]; if (wire.IsConnectionPoint(loc)) { if (subnet.ComponentPorts.Contains((comp, i)) == false) { subnet.AddComponent(comp, i); Console.WriteLine($"Added component ({comp}, port: {i}) to the subnet: {subnet}."); } } } } } // Here we check all of the splitting that needs to be done. foreach (var split in checkSplitSubnets) { // Here we need to check if this subnet // has to be split into multiple subnets if (split.ID == 0) { Console.WriteLine($"We don't need to check for splits on this subnet because it has been removed! Subnet: {split}"); continue; } if (split.Wires.Count == 0) { Console.WriteLine($"We don't need to try to split a subnet without wires. Subnet: {split}"); continue; } Console.WriteLine($"Checking subnet ({split}) for splits!"); List <Wire> wiresLeft = new List <Wire>(split.Wires); bool assignedOriginal = false; var newSubnets = new List <Subnet>(); while (wiresLeft.Count > 0) {
public void UpdateSubnets(List <Wire> added, List <Wire> removed) { List <Subnet> addedSubnets = new List <Subnet>(); List <Subnet> deletedSubnets = new List <Subnet>(); // FIXME: Implement equality checks and hash function for subnets or // don't use a hashset for this... HashSet <Subnet> checkSplitSubnets = new HashSet <Subnet>(); foreach (var old in removed) { var startNet = FindSubnet(old.Pos); var endNet = FindSubnet(old.EndPos); if (startNet != null && endNet != null) { if (startNet == endNet) { // We are removing a wire from a subnet // So here we want to figure out if we have to split this subnet startNet.RemoveWire(old); // If there are no wires left, delete this subnet // otherwise we need to check if the deletion // led to any splits in the subnet if (startNet.Wires.Count == 0) { deletedSubnets.Add(startNet); } else { checkSplitSubnets.Add(startNet); } } else { // This is f***ed in more ways than one... Console.WriteLine($"Error! This should not happen! Trying to remove a wire containing to more than one subnet! (Wire: {old}, Subnet1: {startNet}, Subnet2:{endNet})"); } } else if (startNet != null) { // We are removing from one subnet if (startNet.RemoveWire(old)) { Console.WriteLine($"Warn: Tried to remove a wire from a subnet that didn't contain that wire. (Wire: {old}, Subnet: {startNet})"); } if (startNet.Wires.Count == 0) { deletedSubnets.Add(startNet); } Console.WriteLine($"Removed wire to subnet: {startNet}"); } else if (endNet != null) { // We are removing from one subnet if (endNet.RemoveWire(old)) { Console.WriteLine($"Warn: Tried to remove a wire from a subnet that didn't contain that wire. (Wire: {old}, Subnet: {endNet})"); } if (endNet.Wires.Count == 0) { deletedSubnets.Add(endNet); } Console.WriteLine($"Removed wire to subnet: {endNet}"); } else { // Here we are removing a wire that didn't belong to any subnet!? Console.WriteLine($"Error! This should not happen! Trying to remove a wire not contained in any subnet! (Wire: {old})"); } } foreach (var @new in added) { var startNet = FindSubnet(@new.Pos); var endNet = FindSubnet(@new.EndPos); if (startNet != null && endNet != null) { if (startNet == endNet) { // Here they are the same subnet. // So we just add the wire. startNet.AddWire(@new); } else { // Here we need to merge the different subnets. // FIXME: Should ID zero subnets even be allowed here? // Should we check for merges later? // Should we make a list? Subnet merged; if (startNet.ID != 0 && endNet.ID != 0) { Console.WriteLine($"Merging subnet ({endNet}) into subnet ({startNet})."); Subnets.Remove(endNet); startNet.Merge(endNet); merged = startNet; } else if (startNet.ID != 0) { Console.WriteLine($"Merging subnet ({endNet}) into subnet ({startNet})."); Subnets.Remove(endNet); startNet.Merge(endNet); merged = startNet; } else if (endNet.ID != 0) { Console.WriteLine($"Merging subnet ({startNet}) into subnet ({endNet})."); Subnets.Remove(startNet); endNet.Merge(startNet); merged = endNet; } else { Console.WriteLine($"Warn? We are merging two subnets that both have ID zero. Subnet1: {startNet}, Subnet2: {endNet}"); Subnets.Remove(endNet); startNet.Merge(endNet); merged = startNet; } // Don't forget to add the wire that merged these subnets merged.AddWire(@new); Console.WriteLine($"\tResult: {startNet}"); } } else if (startNet != null) { // Here we just add this wire to the subnet, // it's not going to change anything. startNet.AddWire(@new); Console.WriteLine($"Added wire to subnet: {startNet}"); } else if (endNet != null) { // Here we just add this wire to the subnet, // it's not going to change anything. endNet.AddWire(@new); Console.WriteLine($"Added wire to subnet: {endNet}"); } else { // This means that this wire should be in it's own subnet. // It might get merged into another subnet later though.. var sub = new Subnet(0); sub.AddWire(@new); addedSubnets.Add(sub); // NOTE: do we want to do this? Subnets.Add(sub); Console.WriteLine($"Added single wire subnet: {sub}"); } } foreach (var split in checkSplitSubnets) { // Here we need to check if this subnet // has to be split into multiple subnets if (split.ID == 0) { Console.WriteLine($"We don't need to check for splits on this subnet because it has been removed! Subnet: {split}"); continue; } Console.WriteLine($"Checking subnet ({split}) for splits!"); List <Wire> wiresLeft = new List <Wire>(split.Wires); bool usedSplitSubnet = false; bool noSplit = false; var unclaimedComponents = new List <(InstanceData, int)>(split.ComponentPorts); while (wiresLeft.Count > 0) {