Begin refactoring Shroud. ShroudRenderer is now internal to WorldRenderer; all traits interact with Shroud directly. Gives soft-edges at the map border for free, but breaks shellmap and observers.
This commit is contained in:
@@ -159,6 +159,9 @@ namespace OpenRA.Graphics
|
|||||||
var map = world.Map;
|
var map = world.Map;
|
||||||
var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
|
||||||
Bitmap bitmap = new Bitmap(size, size);
|
Bitmap bitmap = new Bitmap(size, size);
|
||||||
|
if (world.LocalPlayer == null || world.LocalPlayer.Shroud == null)
|
||||||
|
return bitmap;
|
||||||
|
|
||||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
public readonly World world;
|
public readonly World world;
|
||||||
internal readonly TerrainRenderer terrainRenderer;
|
internal readonly TerrainRenderer terrainRenderer;
|
||||||
|
internal readonly ShroudRenderer shroudRenderer;
|
||||||
|
|
||||||
public readonly UiOverlay uiOverlay;
|
public readonly UiOverlay uiOverlay;
|
||||||
internal readonly HardwarePalette palette;
|
internal readonly HardwarePalette palette;
|
||||||
|
|
||||||
@@ -29,6 +31,7 @@ namespace OpenRA.Graphics
|
|||||||
this.world = world;
|
this.world = world;
|
||||||
|
|
||||||
terrainRenderer = new TerrainRenderer(world, this);
|
terrainRenderer = new TerrainRenderer(world, this);
|
||||||
|
shroudRenderer = new ShroudRenderer(world.WorldActor.Trait<Shroud>(), world.Map);
|
||||||
uiOverlay = new UiOverlay();
|
uiOverlay = new UiOverlay();
|
||||||
palette = new HardwarePalette(world.Map);
|
palette = new HardwarePalette(world.Map);
|
||||||
|
|
||||||
@@ -110,9 +113,7 @@ namespace OpenRA.Graphics
|
|||||||
if (world.OrderGenerator != null)
|
if (world.OrderGenerator != null)
|
||||||
world.OrderGenerator.RenderAfterWorld(this, world);
|
world.OrderGenerator.RenderAfterWorld(this, world);
|
||||||
|
|
||||||
if (world.LocalPlayer != null)
|
shroudRenderer.Draw( this );
|
||||||
world.LocalPlayer.Shroud.Draw( this );
|
|
||||||
|
|
||||||
Game.Renderer.DisableScissor();
|
Game.Renderer.DisableScissor();
|
||||||
|
|
||||||
foreach (var a in world.Selection.Actors)
|
foreach (var a in world.Selection.Actors)
|
||||||
|
|||||||
@@ -40,13 +40,12 @@ namespace OpenRA
|
|||||||
public readonly PlayerReference PlayerRef;
|
public readonly PlayerReference PlayerRef;
|
||||||
public bool IsBot;
|
public bool IsBot;
|
||||||
|
|
||||||
public ShroudRenderer Shroud;
|
public Shroud Shroud { get { return World.WorldActor.Trait<Shroud>(); }}
|
||||||
public World World { get; private set; }
|
public World World { get; private set; }
|
||||||
|
|
||||||
public Player(World world, PlayerReference pr, int index)
|
public Player(World world, PlayerReference pr, int index)
|
||||||
{
|
{
|
||||||
World = world;
|
World = world;
|
||||||
Shroud = new ShroudRenderer(this, world.Map);
|
|
||||||
|
|
||||||
Index = index;
|
Index = index;
|
||||||
Palette = "player" + index;
|
Palette = "player" + index;
|
||||||
@@ -69,8 +68,6 @@ namespace OpenRA
|
|||||||
public Player(World world, Session.Client client, PlayerReference pr, int index)
|
public Player(World world, Session.Client client, PlayerReference pr, int index)
|
||||||
{
|
{
|
||||||
World = world;
|
World = world;
|
||||||
Shroud = new ShroudRenderer(this, world.Map);
|
|
||||||
|
|
||||||
Index = index;
|
Index = index;
|
||||||
Palette = "player" + index;
|
Palette = "player" + index;
|
||||||
Color = client.Color1;
|
Color = client.Color1;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
{
|
{
|
||||||
@@ -20,46 +21,28 @@ namespace OpenRA
|
|||||||
Sprite[,] sprites, fogSprites;
|
Sprite[,] sprites, fogSprites;
|
||||||
|
|
||||||
bool dirty = true;
|
bool dirty = true;
|
||||||
bool disabled = false;
|
|
||||||
Map map;
|
Map map;
|
||||||
|
|
||||||
public Rectangle? Bounds { get { return shroud.exploredBounds; } }
|
public ShroudRenderer(Traits.Shroud shroud, Map map)
|
||||||
|
|
||||||
public ShroudRenderer(Player owner, Map map)
|
|
||||||
{
|
{
|
||||||
this.shroud = owner.World.WorldActor.Trait<Traits.Shroud>();
|
this.shroud = shroud;
|
||||||
this.map = map;
|
this.map = map;
|
||||||
|
|
||||||
sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
|
sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
|
||||||
fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y];
|
fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y];
|
||||||
|
|
||||||
shroud.Dirty += () => dirty = true;
|
shroud.Dirty += () => dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Disabled
|
|
||||||
{
|
|
||||||
get { return disabled; }
|
|
||||||
set { disabled = value; dirty = true;}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsExplored(int2 xy) { return IsExplored(xy.X, xy.Y); }
|
|
||||||
public bool IsExplored(int x, int y)
|
public bool IsExplored(int x, int y)
|
||||||
{
|
{
|
||||||
if (disabled)
|
return (shroud == null) ? true : shroud.IsExplored(x,y);
|
||||||
return true;
|
|
||||||
return shroud.exploredCells[x,y];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsVisible(int2 xy) { return IsVisible(xy.X, xy.Y); }
|
|
||||||
public bool IsVisible(int x, int y)
|
public bool IsVisible(int x, int y)
|
||||||
{
|
{
|
||||||
if (disabled)
|
return (shroud == null) ? true : shroud.IsVisible(x,y);
|
||||||
return true;
|
|
||||||
if (!map.IsInMap(x, y))
|
|
||||||
return false;
|
|
||||||
return shroud.visibleCells[x,y] != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly byte[][] SpecialShroudTiles =
|
static readonly byte[][] SpecialShroudTiles =
|
||||||
{
|
{
|
||||||
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||||
@@ -79,61 +62,58 @@ namespace OpenRA
|
|||||||
new byte[] { 41 },
|
new byte[] { 41 },
|
||||||
new byte[] { 46 },
|
new byte[] { 46 },
|
||||||
};
|
};
|
||||||
|
|
||||||
Sprite ChooseShroud(int i, int j)
|
Sprite ChooseShroud(int i, int j)
|
||||||
{
|
{
|
||||||
if( !shroud.exploredCells[ i, j ] ) return shadowBits[ 0xf ];
|
if( !IsExplored( i, j ) ) return shadowBits[ 0xf ];
|
||||||
|
|
||||||
// bits are for unexploredness: up, right, down, left
|
// bits are for unexploredness: up, right, down, left
|
||||||
var v = 0;
|
var v = 0;
|
||||||
// bits are for unexploredness: TL, TR, BR, BL
|
// bits are for unexploredness: TL, TR, BR, BL
|
||||||
var u = 0;
|
var u = 0;
|
||||||
|
|
||||||
if( !shroud.exploredCells[ i, j - 1 ] ) { v |= 1; u |= 3; }
|
if( !IsExplored( i, j - 1 ) ) { v |= 1; u |= 3; }
|
||||||
if( !shroud.exploredCells[ i + 1, j ] ) { v |= 2; u |= 6; }
|
if( !IsExplored( i + 1, j ) ) { v |= 2; u |= 6; }
|
||||||
if( !shroud.exploredCells[ i, j + 1 ] ) { v |= 4; u |= 12; }
|
if( !IsExplored( i, j + 1 ) ) { v |= 4; u |= 12; }
|
||||||
if( !shroud.exploredCells[ i - 1, j ] ) { v |= 8; u |= 9; }
|
if( !IsExplored( i - 1, j ) ) { v |= 8; u |= 9; }
|
||||||
|
|
||||||
var uSides = u;
|
var uSides = u;
|
||||||
|
|
||||||
if( !shroud.exploredCells[ i - 1, j - 1 ] ) u |= 1;
|
if( !IsExplored( i - 1, j - 1 ) ) u |= 1;
|
||||||
if( !shroud.exploredCells[ i + 1, j - 1 ] ) u |= 2;
|
if( !IsExplored( i + 1, j - 1 ) ) u |= 2;
|
||||||
if( !shroud.exploredCells[ i + 1, j + 1 ] ) u |= 4;
|
if( !IsExplored( i + 1, j + 1 ) ) u |= 4;
|
||||||
if( !shroud.exploredCells[ i - 1, j + 1 ] ) u |= 8;
|
if( !IsExplored( i - 1, j + 1 ) ) u |= 8;
|
||||||
|
|
||||||
return shadowBits[ SpecialShroudTiles[ u ^ uSides ][ v ] ];
|
return shadowBits[ SpecialShroudTiles[ u ^ uSides ][ v ] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite ChooseFog(int i, int j)
|
Sprite ChooseFog(int i, int j)
|
||||||
{
|
{
|
||||||
if (shroud.visibleCells[i, j] == 0) return shadowBits[0xf];
|
if (!IsVisible(i,j)) return shadowBits[0xf];
|
||||||
if (!shroud.exploredCells[i, j]) return shadowBits[0xf];
|
if (!IsExplored(i, j)) return shadowBits[0xf];
|
||||||
|
|
||||||
// bits are for unexploredness: up, right, down, left
|
// bits are for unexploredness: up, right, down, left
|
||||||
var v = 0;
|
var v = 0;
|
||||||
// bits are for unexploredness: TL, TR, BR, BL
|
// bits are for unexploredness: TL, TR, BR, BL
|
||||||
var u = 0;
|
var u = 0;
|
||||||
|
|
||||||
if (shroud.visibleCells[i, j - 1] == 0) { v |= 1; u |= 3; }
|
if (!IsVisible(i, j - 1)) { v |= 1; u |= 3; }
|
||||||
if (shroud.visibleCells[i + 1, j] == 0) { v |= 2; u |= 6; }
|
if (!IsVisible(i + 1, j)) { v |= 2; u |= 6; }
|
||||||
if (shroud.visibleCells[i, j + 1] == 0) { v |= 4; u |= 12; }
|
if (!IsVisible(i, j + 1)) { v |= 4; u |= 12; }
|
||||||
if (shroud.visibleCells[i - 1, j] == 0) { v |= 8; u |= 9; }
|
if (!IsVisible(i - 1, j)) { v |= 8; u |= 9; }
|
||||||
|
|
||||||
var uSides = u;
|
var uSides = u;
|
||||||
|
|
||||||
if (shroud.visibleCells[i - 1, j - 1] == 0) u |= 1;
|
if (!IsVisible(i - 1, j - 1)) u |= 1;
|
||||||
if (shroud.visibleCells[i + 1, j - 1] == 0) u |= 2;
|
if (!IsVisible(i + 1, j - 1)) u |= 2;
|
||||||
if (shroud.visibleCells[i + 1, j + 1] == 0) u |= 4;
|
if (!IsVisible(i + 1, j + 1)) u |= 4;
|
||||||
if (shroud.visibleCells[i - 1, j + 1] == 0) u |= 8;
|
if (!IsVisible(i - 1, j + 1)) u |= 8;
|
||||||
|
|
||||||
return shadowBits[SpecialShroudTiles[u ^ uSides][v]];
|
return shadowBits[SpecialShroudTiles[u ^ uSides][v]];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Draw( WorldRenderer wr )
|
internal void Draw( WorldRenderer wr )
|
||||||
{
|
{
|
||||||
if (disabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (dirty)
|
if (dirty)
|
||||||
{
|
{
|
||||||
dirty = false;
|
dirty = false;
|
||||||
@@ -146,7 +126,7 @@ namespace OpenRA
|
|||||||
fogSprites[i, j] = ChooseFog(i, j);
|
fogSprites[i, j] = ChooseFog(i, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
var clipRect = Bounds.HasValue ? Rectangle.Intersect(Bounds.Value, map.Bounds) : map.Bounds;
|
var clipRect = (shroud != null && shroud.Bounds.HasValue) ? Rectangle.Intersect(shroud.Bounds.Value, map.Bounds) : map.Bounds;
|
||||||
clipRect = Rectangle.Intersect(Game.viewport.ViewBounds(), clipRect);
|
clipRect = Rectangle.Intersect(Game.viewport.ViewBounds(), clipRect);
|
||||||
var miny = clipRect.Top;
|
var miny = clipRect.Top;
|
||||||
var maxy = clipRect.Bottom;
|
var maxy = clipRect.Bottom;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace OpenRA.Traits
|
|||||||
foreach( var rt in world.WorldActor.TraitsImplementing<ResourceType>() )
|
foreach( var rt in world.WorldActor.TraitsImplementing<ResourceType>() )
|
||||||
rt.info.PaletteIndex = wr.GetPaletteIndex(rt.info.Palette);
|
rt.info.PaletteIndex = wr.GetPaletteIndex(rt.info.Palette);
|
||||||
|
|
||||||
ShroudRenderer shroud = null;
|
Shroud shroud = null;
|
||||||
if( world.LocalPlayer != null )
|
if( world.LocalPlayer != null )
|
||||||
shroud = world.LocalPlayer.Shroud;
|
shroud = world.LocalPlayer.Shroud;
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,14 @@ namespace OpenRA.Traits
|
|||||||
public int[,] visibleCells;
|
public int[,] visibleCells;
|
||||||
public bool[,] exploredCells;
|
public bool[,] exploredCells;
|
||||||
public Rectangle? exploredBounds;
|
public Rectangle? exploredBounds;
|
||||||
|
bool disabled = false;
|
||||||
|
public bool Disabled
|
||||||
|
{
|
||||||
|
get { return disabled; }
|
||||||
|
set { disabled = value; Dirty(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle? Bounds { get { return exploredBounds; } }
|
||||||
public event Action Dirty = () => { };
|
public event Action Dirty = () => { };
|
||||||
|
|
||||||
public Shroud(World world)
|
public Shroud(World world)
|
||||||
@@ -181,5 +189,30 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
Dirty();
|
Dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsExplored(int2 xy) { return IsExplored(xy.X, xy.Y); }
|
||||||
|
public bool IsExplored(int x, int y)
|
||||||
|
{
|
||||||
|
if (!map.IsInMap(x, y))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (disabled)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return exploredCells[x,y];
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsVisible(int2 xy) { return IsVisible(xy.X, xy.Y); }
|
||||||
|
public bool IsVisible(int x, int y)
|
||||||
|
{
|
||||||
|
if (!map.IsInMap(x, y))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (disabled)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return visibleCells[x,y] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace OpenRA.Mods.RA
|
|||||||
trailStart.G, trailStart.B);
|
trailStart.G, trailStart.B);
|
||||||
|
|
||||||
// LocalPlayer is null on shellmap
|
// LocalPlayer is null on shellmap
|
||||||
ShroudRenderer shroud = null;
|
Shroud shroud = null;
|
||||||
if (self.World.LocalPlayer != null)
|
if (self.World.LocalPlayer != null)
|
||||||
shroud = self.World.LocalPlayer.Shroud;
|
shroud = self.World.LocalPlayer.Shroud;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user