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;
}
}