using System; using Chernobyl.Mathematics.Measures; using Chernobyl.Mathematics.Vectors; using Chernobyl.Values; namespace Chernobyl.Mathematics.Movement { /// /// An that can position itself at the center of a /// cell within a regular grid. This positioning is done either by setting the /// property with a position within the /// cell you want this to be in or by parenting /// this and allowing the ancestor /// instances to do the work. /// public class CellTransform : MatrixTransform { /// /// Initializes a new instance of the class. /// /// The width () and /// height () of a single cell within the 2D graph /// that this is moving through. /// Thrown if the width /// () or height () of the /// parameter are 0 or negative. public CellTransform(Vector2 cellSize) { CellSize = cellSize; } /// /// The (X, Y) index location of this within a /// 2D graph. /// public RowColumn Cell { get { // Make sure this property and the position are in sync. Update(); return _cell; } } /// /// The width () and height () /// of a single cell within the 2D graph that this /// is moving through. /// /// Thrown if the width /// () or height () of the /// value set on this property are 0 or negative. public Vector2 CellSize { get { return _cellSize; } private set { if(value.X <= 0) throw new ArgumentOutOfRangeException("value", value.X, "The width of a cell cannot be less than or equal to 0."); if (value.Y <= 0) throw new ArgumentOutOfRangeException("value", value.Y, "The height of a cell cannot be less than or equal to 0."); _cellSize = value; } } /// /// This method is invoked during the update of the /// right before the /// is actually updated. Typically /// you would override this method if you would like to modify the /// prior to the final calculation /// of the . /// /// The value of the . /// It is stored in a so that the calculation can be /// avoided if necessary. Don't call unless /// required. protected override void PreUpdate(Values.LazyValue world) { base.PreUpdate(world); // Grab the position of either this matrix or the parent if we // have one so that we can calculate the row, column of the cell // this ITransform is in. // here. Vector2 position = LocalMatrix.Translation.Xy; if (TransformParent != null) position = TransformParent.Position.Xy; // Update the RowColumn index of the Cell. _cell = RowColumn.FromPosition(CellSize, position); // Now calculate the position of the transform using the new // Cell position and the new position of the parent transform. // The position of this matrix should be at the center of the // Cell. position = _cell.GetCenter(CellSize); // If we have a parent we will need to make sure to take its // position into account as it will effect the position of // this transform. Essentially we are making sure the "position" // is relatively to the parent. if (TransformParent != null) position = position - TransformParent.Position.Xy; // Set the new position. Matrix4 local = LocalMatrix; local.Row3 = new Vector4(position.X, position.Y, local.Row3.Z, local.Row3.W); SetTransformation(ref local); } /// /// The backing field to . /// RowColumn _cell; /// /// The backing field to . /// Vector2 _cellSize; } }