CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

CellGrid.cs (5703B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // The Command & Conquer Map Editor and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // The Command & Conquer Map Editor and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 using System;
     16 using System.Collections;
     17 using System.Collections.Generic;
     18 using System.Drawing;
     19 
     20 namespace MobiusEditor.Model
     21 {
     22     public enum FacingType
     23     {
     24         None,
     25         North,
     26         NorthEast,
     27         East,
     28         SouthEast,
     29         South,
     30         SouthWest,
     31         West,
     32         NorthWest
     33     }
     34 
     35     public class CellChangedEventArgs<T> : EventArgs
     36     {
     37         public readonly int Cell;
     38 
     39         public readonly Point Location;
     40 
     41         public readonly T OldValue;
     42 
     43         public readonly T Value;
     44 
     45         public CellChangedEventArgs(CellMetrics metrics, int cell, T oldValue, T value)
     46         {
     47             Cell = cell;
     48             metrics.GetLocation(cell, out Location);
     49             OldValue = oldValue;
     50             Value = value;
     51         }
     52 
     53         public CellChangedEventArgs(CellMetrics metrics, Point location, T oldValue, T value)
     54         {
     55             Location = location;
     56             metrics.GetCell(location, out Cell);
     57             OldValue = oldValue;
     58             Value = value;
     59         }
     60     }
     61 
     62     public class CellGrid<T> : IEnumerable<(int Cell, T Value)>, IEnumerable
     63     {
     64         private readonly CellMetrics metrics;
     65         private readonly T[,] cells;
     66 
     67         public T this[int x, int y]
     68         {
     69             get => cells[y, x];
     70             set
     71             {
     72                 if (!EqualityComparer<T>.Default.Equals(cells[y, x], value))
     73                 {
     74                     var lastValue = cells[y, x];
     75                     cells[y, x] = value;
     76                     OnCellChanged(new CellChangedEventArgs<T>(metrics, new Point(x, y), lastValue, cells[y, x]));
     77                 }
     78             }
     79         }
     80 
     81         public T this[Point location] { get => this[location.X, location.Y]; set => this[location.X, location.Y] = value; }
     82 
     83         public T this[int cell] { get => this[cell % metrics.Width, cell / metrics.Width]; set => this[cell % metrics.Width, cell / metrics.Width] = value; }
     84 
     85         public Size Size => metrics.Size;
     86 
     87         public int Length => metrics.Length;
     88 
     89         public event EventHandler<CellChangedEventArgs<T>> CellChanged;
     90         public event EventHandler<EventArgs> Cleared;
     91 
     92         public CellGrid(CellMetrics metrics)
     93         {
     94             this.metrics = metrics;
     95 
     96             cells = new T[metrics.Height, metrics.Width];
     97         }
     98 
     99         public void Clear()
    100         {
    101             Array.Clear(cells, 0, cells.Length);
    102             OnCleared();
    103         }
    104 
    105         public T Adjacent(Point location, FacingType facing)
    106         {
    107             return metrics.Adjacent(location, facing, out Point adjacent) ? this[adjacent] : default;
    108         }
    109 
    110         public T Adjacent(int cell, FacingType facing)
    111         {
    112             if (!metrics.GetLocation(cell, out Point location))
    113             {
    114                 return default;
    115                 
    116             }
    117             return metrics.Adjacent(location, facing, out Point adjacent) ? this[adjacent] : default;
    118         }
    119 
    120         public bool CopyTo(CellGrid<T> other)
    121         {
    122             if (metrics.Length != other.metrics.Length)
    123             {
    124                 return false;
    125             }
    126 
    127             for (var i = 0; i < metrics.Length; ++i)
    128             {
    129                 other[i] = this[i];
    130             }
    131 
    132             return true;
    133         }
    134 
    135         protected virtual void OnCellChanged(CellChangedEventArgs<T> e)
    136         {
    137             CellChanged?.Invoke(this, e);
    138         }
    139 
    140         protected virtual void OnCleared()
    141         {
    142             Cleared?.Invoke(this, new EventArgs());
    143         }
    144 
    145         public IEnumerable<(int Cell, T Value)> IntersectsWith(ISet<int> cells)
    146         {
    147             foreach (var i in cells)
    148             {
    149                 if (metrics.Contains(i))
    150                 {
    151                     var cell = this[i];
    152                     if (cell != null)
    153                     {
    154                         yield return (i, cell);
    155                     }
    156                 }
    157             }
    158         }
    159 
    160         public IEnumerable<(int Cell, T Value)> IntersectsWith(ISet<Point> locations)
    161         {
    162             foreach (var location in locations)
    163             {
    164                 if (metrics.Contains(location))
    165                 {
    166                     var cell = this[location];
    167                     if (cell != null)
    168                     {
    169                         metrics.GetCell(location, out int i);
    170                         yield return (i, cell);
    171                     }
    172                 }
    173             }
    174         }
    175 
    176         public IEnumerator<(int Cell, T Value)> GetEnumerator()
    177         {
    178             for (var i = 0; i < metrics.Length; ++i)
    179             {
    180                 var cell = this[i];
    181                 if (cell != null)
    182                 {
    183                     yield return (i, cell);
    184                 }
    185             }
    186         }
    187 
    188         IEnumerator IEnumerable.GetEnumerator()
    189         {
    190             return GetEnumerator();
    191         }
    192     }
    193 }