private ArraySpec.Cell GetCellAtPixel(int pixelX, int pixelY) { // find click texture coords int x, y; if (!GetTexCoord(pixelX, pixelY, out x, out y)) return null; Color color = pixels[x, y]; if (ColorUtils.IsGrayscale(color)) return null; // flood fill int w = Array.LayoutTexture.Width, h = Array.LayoutTexture.Height; HashSet<Pair<int>> ffS = new HashSet<Pair<int>>(); Queue<Pair<int>> ffQ = new Queue<Pair<int>>(); ffQ.Enqueue(new Pair<int>(x, y)); while (ffQ.Count > 0) { Pair<int> xy = ffQ.Dequeue(); // skip if redundant if (ffS.Contains(xy)) continue; ffS.Add(xy); // enqueue the neighbors for (int x2 = xy.First - 1; x2 <= xy.First + 1; x2++) { for (int y2 = xy.Second - 1; y2 <= xy.Second + 1; y2++) { if (x2 <= 0 || x2 >= w || y2 <= 0 || y2 >= h) continue; if (pixels[x2, y2] != color) continue; ffQ.Enqueue(new Pair<int>(x2, y2)); } } } // create the new cell ArraySpec.Cell newCell = new ArraySpec.Cell(); newCell.Color = color; newCell.Pixels.AddRange(ffS); newCell.Pixels.Sort(new Comparison<Pair<int>>((a, b) => { if (a.Second < b.Second) return -1; // scan line order if (a.Second > b.Second) return 1; if (a.First < b.First) return -1; if (a.First > b.First) return 1; return 0; })); return newCell; }
protected override void OnMouseMove(MouseEventArgs e) { RecomputeArrayViewModel(); if (EditBypassDiodes) { mouseoverJunction = GetJunctionIxAtPixel(e.X, e.Y); mouseoverCell = null; } else { mouseoverCell = GetCellAtPixel(e.X, e.Y); mouseoverJunction = -1; } if (mouseoverJunction == -1 && mouseoverCell == null) { this.Cursor = Cursors.Arrow; // not clickable } else { this.Cursor = Cursors.Hand; } }