所以我正在为XNA开发GUI库,我遇到了一个无法找到解决方案的问题。我正在使用rendertargets,这本身很烦人,但我有一个非常奇怪和具体的问题。
在我的ProgressBar类中,当元素为Validated并且对象大小已更改时,我正在绘制各个组件。如果对象是Validated但对象大小没有改变,我使用填充的rendertargets作为纹理将最终产品绘制到缓冲区纹理(再次是一个rendertarget)。现在,每当我最小化应用程序并再次选项卡时,进度条的背景层将在其上方具有条纹纹理的印记。 rendertargets设置为保留内容,我确保设置了正确的rendertargets。另外清除graphicsDevice(在“实际绘图”行下面)没有做任何事情。为什么呢?
所以基本上游戏会创建该区域的屏幕截图,并将其绘制到我的纹理中。怎么了?
以下是ProgressBar的代码:
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);
}
}
}
答案 0 :(得分: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);
[...]