/// <summary>Empties out and resizes the grid (if it requires it).</summary> public void Clean(float sWidth, float sHeight) { float cellSize = InputGridCell.Size; CellSize = cellSize; // Get the number of cells on x: int width = (int)Math.Ceiling(sWidth / cellSize); int height = (int)Math.Ceiling(sHeight / cellSize); if (Grid == null) { Width = width; Height = height; Grid = new InputGridCell[width * height]; // Create the cells: for (int i = 0; i < Grid.Length; i++) { Grid[i] = new InputGridCell(); } } else if (Width != width || Height != height) { // Pool the nodes: Empty(); Width = width; Height = height; InputGridCell[] newGrid = new InputGridCell[width * height]; // Copy over the cells into the new array, and create any that are required. int max = (newGrid.Length < Grid.Length) ? newGrid.Length : Grid.Length; // Copy that many: Array.Copy(Grid, 0, newGrid, 0, max); // Fill the rest: for (int i = max; i < newGrid.Length; i++) { newGrid[i] = new InputGridCell(); } Grid = newGrid; } }
/// <summary>Empties the grid into the pool.</summary> public void Empty() { if (Grid == null) { return; } // For each grid cell.. for (int i = 0; i < Grid.Length; i++) { InputGridCell cell = Grid[i]; if (cell.Back != null) { // Pool: cell.Back.Previous = PooledCell_; PooledCell_ = cell.Front; // Clear: cell.Back = null; cell.Front = null; } } }
/// <summary>Pushes the given renderable data into the grid now.</summary> public void Push(RenderableData renderData) { // Node must be an element: if (renderData == null || !(renderData.Node is Dom.Element)) { return; } // Get the region: ScreenRegion region = renderData.OnScreenRegion; if (region == null) { return; } // Get the bounds: int minX = (int)(region.ScreenMinX / CellSize); int minY = (int)(region.ScreenMinY / CellSize); if (minX >= Width || minY >= Height) { // ..It's offscreen? return; } if (minX < 0) { minX = 0; } if (minY < 0) { minY = 0; } // Max (inclusive): int maxX = (int)(region.ScreenMaxX / CellSize); int maxY = (int)(region.ScreenMaxY / CellSize); if (maxX < 0 || maxY < 0) { // ..It's offscreen? return; } if (maxX >= Width) { maxX = Width - 1; } if (maxY >= Height) { maxY = Height - 1; } // Generating a bunch of entries now! int cellIndex = minY * Width; // Only having one box means we don't need to do multiline testing. // It also means we can optimise "central" boxes too (see below about that). bool oneBox = (renderData.FirstBox != null && renderData.FirstBox.NextInElement == null); for (int y = minY; y <= maxY; y++) { // Central boxes are on *both* middle X and middle Y // The content in the cell already is being completely overlapped // so we can simply empty it out (and recycle the entries too). bool centralBox = (oneBox && y != minY && y != maxY); for (int x = minX; x <= maxX; x++) { // Get the target cell: InputGridCell cell = Grid[cellIndex + x]; if (centralBox && x != minX && x != maxX) { // Overwrite! Pool the cell: if (cell.Back != null) { // Pool: cell.Back.Previous = PooledCell_; PooledCell_ = cell.Front; // Clear: cell.Back = null; cell.Front = null; } } // Get an entry (typically from the pool): InputGridEntry ige = GetEntry(); // Set it up: ige.RenderData = renderData; if (cell.Front == null) { cell.Back = ige; cell.Front = ige; } else { // Stack on the front: ige.Previous = cell.Front; cell.Front = ige; } } cellIndex += Width; } }