/// <summary> /// RenderCallback for the style "ProgressBar". /// </summary> private void RenderProgressBar(UIControl control, UIRenderContext context) { // See comments of RenderSlider above. ThemeImage indicatorImage = null; ThemeState state = GetState(context); if (state != null) { foreach (var image in state.Images) { if (image.Name == "Indicator") indicatorImage = image; else if (!image.IsOverlay) RenderImage(GetActualBoundsRounded(control), image, context.Opacity, context.RenderTransform); } } ProgressBar bar = control as ProgressBar; if (indicatorImage != null && bar != null) { RectangleF indicatorBounds = GetContentBoundsRounded(bar); // Render indicator. if (!bar.IsIndeterminate) { indicatorBounds.Width = (int)((bar.Value - bar.Minimum) / (bar.Maximum - bar.Minimum) * indicatorBounds.Width); } else { // In indeterminate mode the indicator is 1/4 wide and moves left and right. float width = indicatorBounds.Width / 4.0f; float range = width * 3; float center = indicatorBounds.X + width / 2 + (bar.Value - bar.Minimum) / (bar.Maximum - bar.Minimum) * range; indicatorBounds.X = (int)(center - width / 2); indicatorBounds.Width = (int)(width); } if (indicatorBounds.Width > 0 && indicatorBounds.Height > 0) RenderImage(indicatorBounds, indicatorImage, context.Opacity, context.RenderTransform); } foreach (var child in control.VisualChildren) child.Render(context); RenderImages(control, context, true); }
/// <summary> /// RenderCallback for the style "Slider". /// </summary> private void RenderSlider(UIControl control, UIRenderContext context) { // Special: An image with the name "Indicator" is drawn from the left up to the slider // position. ThemeImage indicatorImage = null; ThemeState state = GetState(context); if (state != null) { // Background images - except the image called "Indicator". foreach (var image in state.Images) { if (image.Name == "Indicator") indicatorImage = image; else if (!image.IsOverlay) RenderImage(GetActualBoundsRounded(control), image, context.Opacity, context.RenderTransform); } } // Render indicator image. Slider slider = control as Slider; if (indicatorImage != null && slider != null) { RectangleF indicatorBounds = GetContentBoundsRounded(slider); // Size of indicator image depends on the slider value. indicatorBounds.Width = (int)((slider.Value - slider.Minimum)/ (slider.Maximum - slider.Minimum) * indicatorBounds.Width); if (indicatorBounds.Width > 0 && indicatorBounds.Height > 0) RenderImage(indicatorBounds, indicatorImage, context.Opacity, context.RenderTransform); } // Visual children. foreach (var child in control.VisualChildren) child.Render(context); // Overlay images. RenderImages(control, context, true); }
/// <summary> /// Renders a <see cref="ThemeImage"/>. /// </summary> /// <param name="bounds">The control's bounding rectangle.</param> /// <param name="image">The image.</param> /// <param name="opacity">The opacity.</param> /// <param name="transform">The render transform.</param> /// <remarks> /// This method uses the <paramref name="image"/> properties (alignment, margin, etc.) and the /// render transformation to render the image into the target (<paramref name="bounds"/>). /// </remarks> public void RenderImage(RectangleF bounds, ThemeImage image, float opacity, RenderTransform transform) { if (image == null) return; // Get the texture atlas containing the image. Texture2D texture = (image.Texture != null) ? image.Texture.Texture : _defaultTexture; // Get bounds without margin. Rectangle source = image.SourceRectangle; Vector4 margin = image.Margin; bounds.X += margin.X; bounds.Y += margin.Y; bounds.Width -= margin.X + margin.Z; bounds.Height -= margin.Y + margin.W; // Get tint color and premultiply alpha. Vector4 colorVector = image.Color.ToVector4(); colorVector.W *= opacity; Color color = Color.FromNonPremultiplied(colorVector); #else Color color = ColorFromNonPremultiplied(colorVector); if (image.HorizontalAlignment == HorizontalAlignment.Stretch || image.VerticalAlignment == VerticalAlignment.Stretch) { // Draw stretched image using a 9-grid layout. RenderStretchedImage(texture, image, bounds, transform, color); } else { // Draw a non-stretched image. RenderImage(texture, bounds, source, image.HorizontalAlignment, image.VerticalAlignment, image.TileMode, transform, color); } }
/// <summary> /// Renders an image with alignment and optional stretching. /// </summary> /// <param name="texture">The UI texture.</param> /// <param name="image">The image.</param> /// <param name="area">The area to fill.</param> /// <param name="transform">The render transform.</param> /// <param name="color">The tint color.</param> private void RenderStretchedImage(Texture2D texture, ThemeImage image, RectangleF area, RenderTransform transform, Color color) { Rectangle source = image.SourceRectangle; int left = (int)image.Border.X; int top = (int)image.Border.Y; int right = (int)image.Border.Z; int bottom = (int)image.Border.W; switch (image.HorizontalAlignment) { case HorizontalAlignment.Center: area.X = (float)Math.Floor(area.X + area.Width / 2.0f - source.Width / 2.0f); // Always round down for consistent results! left = source.Width; right = 0; break; case HorizontalAlignment.Left: left = source.Width; right = 0; break; case HorizontalAlignment.Right: left = 0; right = source.Width; break; } switch (image.VerticalAlignment) { case VerticalAlignment.Center: area.Y = (float)Math.Floor(area.Y + area.Height / 2.0f - source.Height / 2.0f); // Always round down for consistent results! top = source.Height; bottom = 0; break; case VerticalAlignment.Top: top = source.Height; bottom = 0; break; case VerticalAlignment.Bottom: top = 0; bottom = source.Height; break; } // Draw 9-grid layout: // // ----------------------- // | 1 | 2 | 3 | // ----------------------- // | | | | // | 4 | 5 | 6 | // | | | | // ----------------------- // | 7 | 8 | 9 | // ----------------------- Vector2F destinationPosition; RectangleF destinationRectangle; Rectangle sourceRectangle; // Cell #1 (no stretching) destinationPosition = new Vector2F(area.X, area.Y); sourceRectangle = new Rectangle(source.X, source.Y, left, top); transform.Draw(SpriteBatch, texture, destinationPosition, sourceRectangle, color); // Cell #2 (horizontal stretching) destinationRectangle = new RectangleF(area.X + left, area.Y, area.Width - left - right, top); sourceRectangle = new Rectangle(source.X + left, source.Y, source.Width - left - right, top); transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color); // Cell #3 (no stretching) destinationPosition = new Vector2F(area.X + area.Width - right, area.Y); sourceRectangle = new Rectangle(source.X + source.Width - right, source.Y, right, top); transform.Draw(SpriteBatch, texture, destinationPosition, sourceRectangle, color); // Cell #4 (vertical stretching) destinationRectangle = new RectangleF(area.X, area.Y + top, left, area.Height - top - bottom); sourceRectangle = new Rectangle(source.X, source.Y + top, left, source.Height - top - bottom); transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color); // Cell #5 (horizontal and vertical stretching) destinationRectangle = new RectangleF(area.X + left, area.Y + top, area.Width - left - right, area.Height - top - bottom); sourceRectangle = new Rectangle(source.X + left, source.Y + top, source.Width - left - right, source.Height - top - bottom); transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color); // Cell #6 (vertical stretching) destinationRectangle = new RectangleF(area.X + area.Width - right, area.Y + top, right, area.Height - top - bottom); sourceRectangle = new Rectangle(source.X + source.Width - right, source.Y + top, right, source.Height - top - bottom); transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color); // Cell #7 (no stretching) destinationPosition = new Vector2F(area.X, area.Y + area.Height - bottom); sourceRectangle = new Rectangle(source.X, source.Y + source.Height - bottom, left, bottom); transform.Draw(SpriteBatch, texture, destinationPosition, sourceRectangle, color); // Cell #8 (horizontal stretching) destinationRectangle = new RectangleF(area.X + left, area.Y + area.Height - bottom, area.Width - left - right, bottom); sourceRectangle = new Rectangle(source.X + left, source.Y + source.Height - bottom, source.Width - left - right, bottom); transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color); // Cell #9 (no stretching) destinationPosition = new Vector2F(area.X + area.Width - right, area.Y + area.Height - bottom); sourceRectangle = new Rectangle(source.X + source.Width - right, source.Y + source.Height - bottom, right, bottom); transform.Draw(SpriteBatch, texture, destinationPosition, sourceRectangle, color); }