using System;
using Chernobyl.Collections.Generic;
using Chernobyl.Collections.Generic.Event;
using Chernobyl.Creation;
using Chernobyl.Dependency;
using Chernobyl.Graphics;
using Chernobyl.Graphics.Drawing;
using Chernobyl.Graphics.Polygon;
using Chernobyl.Graphics.Polygon.Buffers;
using Chernobyl.Mathematics.Collision;
using Chernobyl.Mathematics.Geometry;
using Chernobyl.Mathematics.Movement;
using Chernobyl.Measures;
using Chernobyl.Utility;
namespace Chernobyl.Interface
{
///
/// Used to give borders to various interface widgets such as buttons, edit
/// boxes, etc.
///
public class Borders : DrawableTransformCollidable2D
{
///
/// Initializes a new instance of the class that
/// places borders along all edges (Edge.Top, Edge.Left, Edge.Right,
/// Edge.Bottom) of the bordered item.
///
/// The instance that
/// takes and gives out services.
public Borders(IEventCollection services)
: this(services, Edge.All)
{ }
///
/// Initializes a new instance of the class.
///
/// The instance that
/// takes and gives out services.
/// The edges of the item where the border(s)
/// should be placed.
public Borders(IEventCollection services, Edge edges)
{
_drawableImplementer = new Drawable();
_drawableImplementer.DecoratoringDrawable = this;
_decoratedTransform = new MatrixTransform();
_shapeCollection = new ShapeCollection();
Services = services;
Services.Inject(this);
services.Create, IBuffer>>(
(sender, e) => BorderDrawBuffer = e.CreatedInstance,
new Pair, IBuffer>(services, VertexColor.CreateSquare(Services, ColorRgba.Black)));
Edges = edges;
}
///
/// The edges of the item where the border(s)
/// should be placed.
///
/// By default, the value of this property is
///
public Edge Edges
{
get { return _edges; }
set
{
_edges = value;
if (_borderDrawableParent != null)
RefreshBorders();
}
}
///
/// Recreates the borders on the edges of the object.
///
void RefreshBorders()
{
if ((_edges & Edge.Right) == Edge.Right)
{
// create a TransformRectangle of 1x1. The transform rectangle will
// automatically adjust as we scale the border. Currently, the border
// is using a 1x1 square mesh element to render textures to, therefore,
// a 1x1 TransformRectangle will only work properly with a 1x1 mesh
// element square.
Rectangle rectangle = new Rectangle(-0.5f, -0.5f, 1, 1);
// create the right and attach it to this Border and the draw buffer
RightBorder = new Render(Services, PrimitiveType.TriangleStrip, null, new RemoveScaleTransform(Axis.X | Axis.Z, true), rectangle);
Transform.MakeParentChild(RightBorder, rectangle);
Transform.MakeParentChild(this, RightBorder);
_shapeCollection.Add(RightBorder);
// position along the right of the item
RightBorder.TranslateX(0.5f);
}
else if (RightBorder != null)
RightBorder = RemoveBorder(RightBorder);
if ((_edges & Edge.Left) == Edge.Left)
{
// create a TransformRectangle of 1x1. The transform rectangle will
// automatically adjust as we scale the border. Currently, the border
// is using a 1x1 square mesh element to render textures to, therefore,
// a 1x1 TransformRectangle will only work properly with a 1x1 mesh
// element square.
Rectangle rectangle = new Rectangle(-0.5f, -0.5f, 1, 1);
// create the left and attach it to this Border and the draw buffer
LeftBorder = new Render(Services, PrimitiveType.TriangleStrip, null, new RemoveScaleTransform(Axis.X | Axis.Z, true), rectangle);
Transform.MakeParentChild(RightBorder, rectangle);
Transform.MakeParentChild(this, LeftBorder);
_shapeCollection.Add(LeftBorder);
// position along the left of the item
LeftBorder.TranslateX(-0.5f);
}
else if (LeftBorder != null)
LeftBorder = RemoveBorder(LeftBorder);
if ((_edges & Edge.Top) == Edge.Top)
{
// create a TransformRectangle of 1x1. The transform rectangle will
// automatically adjust as we scale the border. Currently, the border
// is using a 1x1 square mesh element to render textures to, therefore,
// a 1x1 TransformRectangle will only work properly with a 1x1 mesh
// element square.
Rectangle rectangle = new Rectangle(-0.5f, -0.5f, 1, 1);
// create the top and attach it to this Border and the draw buffer
TopBorder = new Render(Services, PrimitiveType.TriangleStrip, null, new RemoveScaleTransform(Axis.Y | Axis.Z, true), rectangle);
Transform.MakeParentChild(RightBorder, rectangle);
Transform.MakeParentChild(this, TopBorder);
_shapeCollection.Add(TopBorder);
// position along the top of the item
TopBorder.Roll((Degree)90.0f);
TopBorder.TranslateY(0.5f);
}
else if (TopBorder != null)
TopBorder = RemoveBorder(TopBorder);
if ((_edges & Edge.Bottom) == Edge.Bottom)
{
// create a TransformRectangle of 1x1. The transform rectangle will
// automatically adjust as we scale the border. Currently, the border
// is using a 1x1 square mesh element to render textures to, therefore,
// a 1x1 TransformRectangle will only work properly with a 1x1 mesh
// element square.
Rectangle rectangle = new Rectangle(-0.5f, -0.5f, 1, 1);
// create the bottom and attach it to this Border and the draw buffer
BottomBorder = new Render(Services, PrimitiveType.TriangleStrip, null, new RemoveScaleTransform(Axis.Y | Axis.Z, true), rectangle);
Transform.MakeParentChild(RightBorder, rectangle);
Transform.MakeParentChild(this, BottomBorder);
_shapeCollection.Add(BottomBorder);
// position along the top of the item
BottomBorder.Roll((Degree)90.0f);
BottomBorder.TranslateY(-0.5f);
}
else if (BottomBorder != null)
BottomBorder = RemoveBorder(BottomBorder);
}
///
/// Removes a border from the item.
///
/// The border to remove from the item.
/// The new value of the
/// passed in.
IRender RemoveBorder(IRender border)
{
// Separate the border from this parent and remove it from the
// draw path
Transform.SeperateParentChild(this, border);
BorderDrawBuffer.DrawableChildren.Remove(border);
_shapeCollection.Remove(border);
return null;
}
///
/// The used for rendering borders. The
/// drawable will be used as the actual
/// parent.
///
[Inject]
public Scene DefaultScene
{
set
{
_borderDrawableParent = value.Draw2D;
RefreshBorders();
}
}
///
/// The used to render the border on the right side
/// of the item.
///
IRender RightBorder { get; set; }
///
/// The used to render the border on the left side
/// of the item.
///
IRender LeftBorder { get; set; }
///
/// The used to render the border on the top of
/// the item.
///
IRender TopBorder { get; set; }
///
/// The used to render the border on the bottom of
/// the item.
///
IRender BottomBorder { get; set; }
///
/// The used to render the mesh element data of
/// the border squares.
///
/// The border draw buffer.
IDrawBuffer BorderDrawBuffer
{
get { return _borderDrawBuffer; }
set
{
value.ThrowIfNull("value");
IDrawBuffer previousValue = _borderDrawBuffer;
_borderDrawBuffer = value;
if (previousValue != null)
{
if (previousValue.DrawableParent == _borderDrawableParent)
previousValue.DrawableParent = null;
}
_borderDrawBuffer.DrawableParent = _borderDrawableParent;
}
}
///
/// The services instance that was given to this class in it's constructor.
/// This instance is used to create borders.
///
IEventCollection Services { get; set; }
///
/// The collidable that implements the collision of this object.
///
protected override ICollidable2D CollidableImplementer
{
get { throw new NotImplementedException(); }
}
///
/// The drawable that implements the drawing of this object.
///
protected override IDrawable DrawableImplementer
{
get { return _drawableImplementer; }
}
///
/// The transform that provides this transforms capabilities.
///
protected override ITransform DecoratedTransform
{
get { return _decoratedTransform; }
}
///
/// The that implements the
/// interface for this object.
///
protected override IShape ShapeImplementer
{
get { return _shapeCollection; }
}
///
/// Backing field to .
///
Edge _edges;
///
/// The that will become the parent of new
/// borders.
///
IDrawable _borderDrawableParent;
///
/// The backing field to .
///
IDrawable _drawableImplementer;
///
/// The backing field to .
///
ITransform _decoratedTransform;
///
/// The that calculates the width and
/// height of the Borders.
///
ShapeCollection _shapeCollection;
///
/// The backing field to .
///
IDrawBuffer _borderDrawBuffer;
}
}