0

所以我正在为 XNA 开发一个 GUI 库,我遇到了一个我找不到解决方案的问题。我经常使用渲染目标,这本身很烦人,但我有一个非常奇怪和具体的问题。

在我的 ProgressBar 类中,当元素经过验证并且对象大小已更改时,我正在绘制各个组件。如果对象已验证但对象大小未更改,则我使用填充的渲染目标作为纹理将最终产品绘制到缓冲区纹理(同样是渲染目标)上。现在,每当我最小化应用程序并再次使用 Tab 时,进度条的背景层都会在其上方留下条纹纹理的印记。渲染目标设置为保留内容,我确保设置了正确的渲染目标。还清除 graphicsDevice(就在“实际绘图”行下方)不会做任何事情。为什么?

所以基本上游戏会创建该区域的屏幕截图,并将其绘制到我的纹理中。我勒个去?

这是进度条的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace PixLib
{
    public class ProgressBar : UIElement
    {
        private float stripeThickness = 5;
        private float stripeGapFactor = 3f;
        private float animationSpeed = 1f;
        private float at = 0;
        private RenderTarget2D stripesBg, stripes;
        private Coordinate2 lastSize;
        protected override Coordinate2 InnerArea
        {
            get { return Coordinate2.Zero; }
        }
        protected Color color;
        public Color Color
        {
            get
            {
                return color;
            }
            set
            {
                color = value;
                Invalidate();
            }
        }
        protected float value;
        public float Value
        {
            get
            {
                return value;
            }
            set
            {
                float t = Math.Min(1, Math.Max(0, value));
                if (t != this.value)
                {
                    this.value = t;
                    Invalidate();
                }

            }
        }
        public ProgressBar(string name,Color color, Rectangle elementRect, bool localPos = true)
            : base(name, elementRect, localPos)
        {
            lastSize = new Coordinate2();
            this.color = color;
            value = 0;
            at = 0;
        }
        protected override void OnUpdate(MouseState mouseState, KeyboardState keyboardState)
        {

        }
        protected override void OnInit()
        {

        }
        protected override void Redraw(SpriteBatch spriteBatch)
        {

            if (lastSize.X != Width || lastSize.Y != Height)
            {

                Console.WriteLine("Redrawing Progressbar");
                //redraw textures!
                stripesBg = new RenderTarget2D(graphicsManager.GraphicsDevice, Width, Height, false, graphicsManager.GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24, 1, RenderTargetUsage.PreserveContents);
                stripes = new RenderTarget2D(graphicsManager.GraphicsDevice, Width, Height * 2, false, graphicsManager.GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24, 1, RenderTargetUsage.PreserveContents);

                spriteBatch.Begin();
                spriteBatch.Draw(pixel, new Rectangle(0, 0, Width, Height), Color.White);
                spriteBatch.End();

                SetRenderTarget(stripesBg);
                spriteBatch.Begin();
                spriteBatch.Draw(pixel, new Rectangle(0, 0, Width, Height), Color.White);
                spriteBatch.End();

                /*SetRenderTarget(border);
                spriteBatch.Begin();
                int si = (int)(stripeThickness*0.5f + 0.5f);
                DrawLine(new Coordinate2(si, 0), new Coordinate2(Width, 0), spriteBatch, Color.White, si);
                DrawLine(new Coordinate2(si, Height - si), new Coordinate2(Width, Height - si), spriteBatch, Color.White, si);
                DrawLine(new Coordinate2(si, 0), new Coordinate2(si, Height), spriteBatch, Color.White, si);
                DrawLine(new Coordinate2(Width, 0), new Coordinate2(Width, Height - si), spriteBatch, Color.White, si);
                spriteBatch.End();*/

                SetRenderTarget(stripes);
                spriteBatch.Begin();
                int fy = (int)(stripeThickness +0.5f);
                int s = (Height + fy) * 2;
                int fx = -s;
                at = 0;
                while (fx < Width + stripeThickness * stripeGapFactor)
                {

                    DrawLine(new Coordinate2(fx, -fy), new Coordinate2(fx+s, s-fy), spriteBatch, Color.White, stripeThickness);
                    fx += (int)(stripeThickness * stripeGapFactor);
                }
                spriteBatch.End();


                SetRenderTarget(null);


                lastSize.X = Width;
                lastSize.Y = Height;
            }

            //actual drawing
            spriteBatch.Begin();
            spriteBatch.Draw(pixel, SizeRect, Darken(color, 2));
            int cv = (int)(Value * Width + 0.5f);
            spriteBatch.Draw(stripesBg, new Rectangle(cv - Width, 0, Width, Height), Darken(Color));
            graphicsManager.GraphicsDevice.Clear(Color.Transparent);
            spriteBatch.Draw(stripes, new Rectangle(cv - Width, -(int)(at + 0.5f), Width, Height * 2), color);
            spriteBatch.End();

            at += animationSpeed;
            if (at >= Height)
                at -= Height - (int)(stripeThickness + .5f);
        }
    }
}
4

1 回答 1

0

好吧,看来这个问题的解决方案是让渲染目标不保留它们的内容,并在内容丢失时重新绘制整个该死的东西。

 if (lastSize.X != Width || lastSize.Y != Height || stripesBg.IsContentLost || stripes.IsContentLost)
            {

                Console.WriteLine("Redrawing Progressbar");
                //redraw textures!
                //stripesBg = new RenderTarget2D(graphicsManager.GraphicsDevice, Width, Height, false, graphicsManager.GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24, 1, RenderTargetUsage.PreserveContents);
                //stripes = new RenderTarget2D(graphicsManager.GraphicsDevice, Width, Height * 2, false, graphicsManager.GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24, 1, RenderTargetUsage.PreserveContents);
                stripesBg = new RenderTarget2D(graphicsManager.GraphicsDevice, Width, Height);
                stripes = new RenderTarget2D(graphicsManager.GraphicsDevice, Width, Height * 2);
[...]
于 2013-04-21T18:45:52.273 回答