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