public override void DrawRectangle(Rectangle area, Brush brush, Thickness thickness, double radius, Rectangle bounds) { SetClipArea(bounds); if (area != Rectangle.Empty) { if (radius > 0) { FillRectangle(area, brush, radius, bounds); } else { var areaXNA = area.ToXNA(); FillRect(new RectangleXNA(areaXNA.X, areaXNA.Top, areaXNA.Width, thickness.Top), brush); FillRect(new RectangleXNA(areaXNA.X, areaXNA.Top + thickness.Top, thickness.Left, areaXNA.Height - thickness.Top - thickness.Bottom), brush); FillRect(new RectangleXNA(areaXNA.Right - thickness.Right, areaXNA.Top + thickness.Top, thickness.Right, areaXNA.Height - thickness.Top - thickness.Bottom), brush); FillRect(new RectangleXNA(areaXNA.X, areaXNA.Bottom - thickness.Bottom, areaXNA.Width, thickness.Bottom), brush); } } ResetClipArea(); }
public bool Equals(Rectangle other) { return X.Equals(other.X) && Y.Equals(other.Y) && Width.Equals(other.Width) && Height.Equals(other.Height); }
private void UseMaskStencil(Rectangle area) { // If the mask area doesn't overlap any previous areas, it is safe to reuse the area without clearing the buffer. if (stencilAreas.Any(x => x.Intersects(area))) { graphics.Clear(ClearOptions.Stencil, ColorXNA.White, 0, 0); stencilAreas.Clear(); stencilAreas.Add(area); } else if (!stencilAreas.Any(x => x.Equals(area))) stencilAreas.Add(area); EndDraw(); manager.SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, maskStencil, manager.SpriteBatch.GraphicsDevice.RasterizerState, alphaTextEffect); }
/// <summary> /// Draw a gradient over the specified area. To draw in a custom area (such as rounded rectangles), use a mask. /// </summary> private void DrawGradient(Rectangle area, GradientBrush gradientBrush) { Texture2D gradientTexture; // Create new gradient texture if it is not cached. if (!gradientCache.TryGetValue(gradientBrush, out gradientTexture)) { var total = 15; gradientTexture = new Texture2D(manager.SpriteBatch.GraphicsDevice, 1, total); var start = gradientBrush.Start.ToXNA(); var end = gradientBrush.End.ToXNA(); var colors = new ColorXNA[total]; // Add the start and end colors to the start and end, then add colors in betweeen. // The default way XNA/Monogame handles just two colors will only make 1/3rd of the result // a gradient, so we need to add some colors in between for better interpolation. colors[0] = start; for (var i = 1; i < total - 1; i++) { colors[i] = ColorXNA.Lerp(start, end, (float) i / (total - 2)); } colors[total - 1] = end; gradientTexture.SetData(colors); gradientCache.Add(gradientBrush, gradientTexture); } manager.SpriteBatch.Draw(gradientTexture, area.ToXNA(), null, ColorXNA.White, 0, Vector2.Zero, SpriteEffects.None, 0); }
public override void FillRectangle(Rectangle area, Brush brush, double radius, Rectangle bounds) { SetClipArea(bounds); if (area != Rectangle.Empty) { if (radius > 0) { var corner = (int) Math.Round(radius); var corner2 = corner * 2; var areaXNA = area.ToXNA(); var gradientBrush = brush as GradientBrush; if (gradientBrush != null) { UseMaskStencil(area); } // Draw 5 rectangles (top, bottom, left, right, center) FillRect(new RectangleXNA(areaXNA.X + corner, areaXNA.Top, areaXNA.Width - corner2, corner), brush); FillRect(new RectangleXNA(areaXNA.X + corner, areaXNA.Bottom - corner, areaXNA.Width - corner2, corner), brush); FillRect(new RectangleXNA(areaXNA.X, areaXNA.Top + corner, corner, areaXNA.Height - corner2), brush); FillRect(new RectangleXNA(areaXNA.Right - corner, areaXNA.Y + corner, corner, areaXNA.Height - corner2), brush); FillRect(new RectangleXNA(areaXNA.X + corner, areaXNA.Y + corner, areaXNA.Width - corner2, areaXNA.Height - corner2), brush); // Draw edge corners. var circle = GetCircleTexture(radius); FillCorner(new RectangleXNA(areaXNA.X, areaXNA.Y, corner, corner), circle, Corner.TopLeft, brush); FillCorner(new RectangleXNA(areaXNA.Right - corner, areaXNA.Y, corner, corner), circle, Corner.TopRight, brush); FillCorner(new RectangleXNA(areaXNA.X, areaXNA.Bottom - corner, corner, corner), circle, Corner.BottomLeft, brush); FillCorner(new RectangleXNA(areaXNA.Right - corner, areaXNA.Bottom - corner, corner, corner), circle, Corner.BottomRight, brush); // If using a gradient brush, draw a gradient over the mask. if (gradientBrush != null) { UseRenderStencil(); DrawGradient(area, gradientBrush); EndStencil(); } } else { var colorBrush = brush as ColorBrush; var gradientBrush = brush as GradientBrush; if (colorBrush != null) { manager.SpriteBatch.Draw(pixel, area.ToXNA(), null, colorBrush.ToXNA(), 0, Vector2.Zero, SpriteEffects.None, 0); } if (gradientBrush != null) { DrawGradient(area, gradientBrush); } } } ResetClipArea(); }
public override void DrawString(string text, Point point, Brush brush, int size, FontStyle style, Rectangle bounds, bool ignoreFormatting = false) { SetClipArea(bounds); var pos = new Vector2((int) Math.Round(point.X), (int) Math.Round(point.Y)); var closest = GetClosestFontSize(size); var colorBrush = brush as ColorBrush; var gradientBrush = brush as GradientBrush; var defaultColor = Color.Black; if (colorBrush != null) defaultColor = colorBrush.Color; if (gradientBrush != null) { UseMaskStencil(bounds); } if (!ignoreFormatting) // If formatting is enabled, parse it and render each part. { var parts = ParseFormattedText(text, defaultColor, style); foreach (var part in parts) { var font = GetFont(Path.Combine(part.Style.ToString(), closest.ToString())); var measure = MeasureTextNoTrim(part.Text, size, part.Style); var col = new ColorXNA(part.Color.R, part.Color.G, part.Color.B, defaultColor.A); manager.SpriteBatch.DrawString(font, part.Text, pos, col * (defaultColor.A / 255f), 0, Vector2.Zero, size / (float) closest, SpriteEffects.None, 0); pos = new Vector2(pos.X + (float) measure.Width, pos.Y); } } else // Draw plain string { var font = GetFont(Path.Combine(style.ToString(), closest.ToString())); var col = new ColorXNA(defaultColor.R, defaultColor.G, defaultColor.B, defaultColor.A); manager.SpriteBatch.DrawString(font, text, pos, col * (defaultColor.A / 255f), 0, Vector2.Zero, size / (float) closest, SpriteEffects.None, 0); } // If using a gradient brush, draw a gradient over the mask. if (gradientBrush != null) { UseRenderStencil(); DrawGradient(bounds, gradientBrush); EndStencil(); } ResetClipArea(); }
public abstract void Render(Rectangle extendedArea, Rectangle contentArea, float delta);
/// <summary> /// Draws a rounded filled rectangle within the specified area. /// </summary> public abstract void FillRectangle(Rectangle area, Brush brush, double cornerRadius, Rectangle bounds);
public override void Render(Rectangle extendedArea, Rectangle contentArea, float delta) { Manager.Renderer.StretchRectangle(contentArea, Color, contentArea.AddBorder(BlurRadius)); }
public Rectangle Min(Rectangle other) => new Rectangle(X, Y, Math.Min(Width, other.Width), Math.Min(Height,other.Height));
/// <summary> /// Determines if the rectangle is equal to another rectangle within margin of error (because of floating point precision). /// </summary> public bool IsClose(Rectangle rectangle) => Point.IsClose(rectangle.Point) && Size.IsClose(rectangle.Size);
/// <summary> /// Limit the area of this rectangle to the specified bounds. /// </summary> public Rectangle FitToBounds(Rectangle bounds) { var x1 = Math.Max(X, bounds.X); var x2 = Math.Min(X + Width, bounds.X + bounds.Width); var y1 = Math.Max(Y, bounds.Y); var y2 = Math.Min(Y + Height, bounds.Y + bounds.Height); return x2 >= x1 && y2 >= y1 ? new Rectangle(x1, y1, x2 - x1, y2 - y1) : Empty; }
/// <summary> /// Offset the rectangle by the specified rectangle coordinates. (Add to the X and Y) /// </summary> public Rectangle Offset(Rectangle rectangle) => new Rectangle(X + rectangle.X, Y + rectangle.Y, Width, Height);
public bool Intersects(Rectangle rect) => (rect.X < X + Width) && (X < (rect.X + rect.Width)) && (rect.Y < Y + Height) && (Y < rect.Y + rect.Height);
public bool Contains(Rectangle rect) => (X <= rect.X) && ((rect.X + rect.Width) <= (X + Width)) && (Y <= rect.Y) && ((rect.Y + rect.Height) <= (Y + Height));
/// <summary> /// Draws a rounded rectangle within the specified area. /// </summary> public abstract void DrawRectangle(Rectangle area, Brush brush, Thickness border, double cornerRadius, Rectangle bounds);
/// <summary> /// Draws a filled rectangle within the specified area. /// </summary> public void FillRectangle(Rectangle area, Brush brush, Rectangle bounds) => FillRectangle(area, brush, 0, bounds);
/// <summary> /// Draws a texture loaded by the skin in the specified region. /// </summary> public void DrawTexture(string name, Rectangle rectangle, Rectangle bounds) => DrawTexture(name, rectangle, Color.White, bounds);
/// <summary> /// Stretches a rectangle to fill the bounds and create a shadow effect. /// </summary> public abstract void StretchRectangle(Rectangle area, Color color, Rectangle bounds);
/// <summary> /// Draws a texture loaded by the skin in the specified region with the specified tint. /// </summary> public abstract void DrawTexture(string name, Rectangle rectangle, ColorBrush color, Rectangle bounds);
public override void Draw(float delta) { // Get text alignment offset. if (textAlignInvalidated || textSizeInvalidated || !lastBorderSize.IsClose(Bounds)) { textAlignOffset = AlignText(textSize); textAlignInvalidated = false; textSizeInvalidated = false; } Manager.Renderer.DrawString(Text, Bounds.Point + textAlignOffset, TextColor, FontSize, FontStyle, LogicalParentBounds.FitToBounds(Bounds)); lastBorderSize = Bounds; base.Draw(delta); }
/// <summary> /// Draws a string at the specified point. /// </summary> public void DrawString(string text, Point point, ColorBrush color, Rectangle bounds, bool ignoreFormatting = false) => DrawString(text, point, color, defaultSize, bounds, ignoreFormatting);
public override void DrawTexture(string name, Rectangle rectangle, ColorBrush brush, Rectangle bounds) { var rect = new RectangleXNA((int) rectangle.X, (int) rectangle.Y, (int) rectangle.Width, (int) rectangle.Height); var texture = GetTexture(name); var col = new ColorXNA(brush.Color.R, brush.Color.G, brush.Color.B, brush.Color.A); manager.SpriteBatch.Draw(texture, rect, col); }
/// <summary> /// Draws a string at the specified point. /// </summary> public void DrawString(string text, Point point, int size, Rectangle bounds,bool ignoreFormatting = false) => DrawString(text, point, Color.Black, size, bounds, ignoreFormatting);
public override void StretchRectangle(Rectangle area, Color color, Rectangle bounds) { var shadow = (Texture2D) manager.Skin.Textures["shadow"]; var a = area.ToXNA(); var b = bounds.ToXNA(); var half = shadow.Width / 2; var col = color.ToXNA(); FillRectangle(area, color, area); manager.SpriteBatch.Draw(shadow, new RectangleXNA(b.X, b.Y, a.X - b.X, a.Y - b.Y), new RectangleXNA(0, 0, half, half), col); manager.SpriteBatch.Draw(shadow, new RectangleXNA(b.X, a.Y + a.Height, a.X - b.X, a.Y - b.Y), new RectangleXNA(0, half, half, half), col); manager.SpriteBatch.Draw(shadow, new RectangleXNA(a.X + a.Width, b.Y, a.X - b.X, a.Y - b.Y), new RectangleXNA(half, 0, half, half), col); manager.SpriteBatch.Draw(shadow, new RectangleXNA(a.X + a.Width, a.Y + a.Height, a.X - b.X, a.Y - b.Y), new RectangleXNA(half, half, half, half), col); manager.SpriteBatch.Draw(shadow, new RectangleXNA(a.X, b.Y, a.Width, a.Y - b.Y), new RectangleXNA(half, 0, 1, half), col); manager.SpriteBatch.Draw(shadow, new RectangleXNA(a.X, a.Y + a.Height, a.Width, a.Y - b.Y), new RectangleXNA(half, half, 1, half), col); manager.SpriteBatch.Draw(shadow, new RectangleXNA(b.X, a.Y, a.X - b.X, a.Height), new RectangleXNA(0, half, half, 1), col); manager.SpriteBatch.Draw(shadow, new RectangleXNA(a.X + a.Width, a.Y, a.X - b.X, a.Height), new RectangleXNA(half, half, half, 1), col); }
/// <summary> /// Draws a string at the specified point. /// </summary> public void DrawString(string text, Point point, Brush brush, int size, Rectangle bounds, bool ignoreFormatting = false) => DrawString(text, point, brush, size, FontStyle.Regular, bounds, ignoreFormatting);
private void SetClipArea(Rectangle bounds) { manager.SpriteBatch.GraphicsDevice.ScissorRectangle = bounds.ToXNA(); }
/// <summary> /// Draws a string at the specified point. /// </summary> public abstract void DrawString(string text, Point point, Brush brush, int size, FontStyle style, Rectangle bounds,bool ignoreFormatting = false);
/// <summary> /// Draws a rectangle within the specified area. /// </summary> public void DrawRectangle(Rectangle area, Brush brush, Thickness border, Rectangle bounds) => DrawRectangle(area, brush, border, 0, bounds);
/// <summary> /// Retuns an offset to the elements position according to its size, container size, and alignment. /// </summary> private Point Align(Rectangle container, Size size) { if (!double.IsInfinity(size.Width)) // Infinite sizes will be handled elsewhere. { switch (HorizontalAlignment) { case HorizontalAlignment.Stretch: case HorizontalAlignment.Center: container.X = container.Left + (container.Width - size.Width) / 2; break; case HorizontalAlignment.Right: container.X = container.Left + container.Width - size.Width; break; } } if (!double.IsInfinity(size.Height)) { switch (VerticalAlignment) { case VerticalAlignment.Stretch: case VerticalAlignment.Center: container.Y = container.Top + (container.Height - size.Height) / 2; break; case VerticalAlignment.Bottom: container.Y = container.Top + container.Height - size.Height; break; } } return container.Point; }