Fix IDE0032

This commit is contained in:
RoosterDragon
2023-02-19 11:19:28 +00:00
committed by Pavel Penev
parent e64c0a35c5
commit 98c4eaca83
52 changed files with 460 additions and 567 deletions

View File

@@ -180,6 +180,9 @@ dotnet_diagnostic.IDE0030.severity = warning
# Use null propagation. # Use null propagation.
dotnet_diagnostic.IDE0031.severity = warning dotnet_diagnostic.IDE0031.severity = warning
# Use auto-implemented property.
dotnet_diagnostic.IDE0032.severity = warning
# Use explicitly provided tuple name. # Use explicitly provided tuple name.
dotnet_diagnostic.IDE0033.severity = warning dotnet_diagnostic.IDE0033.severity = warning

View File

@@ -18,24 +18,22 @@ namespace OpenRA.FileSystem
{ {
public sealed class Folder : IReadWritePackage public sealed class Folder : IReadWritePackage
{ {
readonly string path; public string Name { get; }
public Folder(string path) public Folder(string path)
{ {
this.path = path; Name = path;
if (!Directory.Exists(path)) if (!Directory.Exists(path))
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
} }
public string Name => path;
public IEnumerable<string> Contents public IEnumerable<string> Contents
{ {
get get
{ {
// Order may vary on different file systems and it matters for hashing. // Order may vary on different file systems and it matters for hashing.
return Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly) return Directory.GetFiles(Name, "*", SearchOption.TopDirectoryOnly)
.Concat(Directory.GetDirectories(path)) .Concat(Directory.GetDirectories(Name))
.Select(Path.GetFileName) .Select(Path.GetFileName)
.OrderBy(f => f); .OrderBy(f => f);
} }
@@ -43,14 +41,14 @@ namespace OpenRA.FileSystem
public Stream GetStream(string filename) public Stream GetStream(string filename)
{ {
try { return File.OpenRead(Path.Combine(path, filename)); } try { return File.OpenRead(Path.Combine(Name, filename)); }
catch { return null; } catch { return null; }
} }
public bool Contains(string filename) public bool Contains(string filename)
{ {
var combined = Path.Combine(path, filename); var combined = Path.Combine(Name, filename);
return combined.StartsWith(path, StringComparison.Ordinal) && File.Exists(combined); return combined.StartsWith(Name, StringComparison.Ordinal) && File.Exists(combined);
} }
public IReadOnlyPackage OpenPackage(string filename, FileSystem context) public IReadOnlyPackage OpenPackage(string filename, FileSystem context)
@@ -82,7 +80,7 @@ namespace OpenRA.FileSystem
// in FileSystem.OpenPackage. Their internal name therefore contains the // in FileSystem.OpenPackage. Their internal name therefore contains the
// full parent path too. We need to be careful to not add a second path // full parent path too. We need to be careful to not add a second path
// prefix to these hacked packages. // prefix to these hacked packages.
var filePath = filename.StartsWith(path) ? filename : Path.Combine(path, filename); var filePath = filename.StartsWith(Name) ? filename : Path.Combine(Name, filename);
Directory.CreateDirectory(Path.GetDirectoryName(filePath)); Directory.CreateDirectory(Path.GetDirectoryName(filePath));
using (var s = File.Create(filePath)) using (var s = File.Create(filePath))
@@ -96,7 +94,7 @@ namespace OpenRA.FileSystem
// in FileSystem.OpenPackage. Their internal name therefore contains the // in FileSystem.OpenPackage. Their internal name therefore contains the
// full parent path too. We need to be careful to not add a second path // full parent path too. We need to be careful to not add a second path
// prefix to these hacked packages. // prefix to these hacked packages.
var filePath = filename.StartsWith(path) ? filename : Path.Combine(path, filename); var filePath = filename.StartsWith(Name) ? filename : Path.Combine(Name, filename);
if (Directory.Exists(filePath)) if (Directory.Exists(filePath))
Directory.Delete(filePath, true); Directory.Delete(filePath, true);
else if (File.Exists(filePath)) else if (File.Exists(filePath))

View File

@@ -142,23 +142,22 @@ namespace OpenRA.FileSystem
sealed class ZipFolder : IReadOnlyPackage sealed class ZipFolder : IReadOnlyPackage
{ {
public string Name => path; public string Name { get; }
public ReadOnlyZipFile Parent { get; } public ReadOnlyZipFile Parent { get; }
readonly string path;
public ZipFolder(ReadOnlyZipFile parent, string path) public ZipFolder(ReadOnlyZipFile parent, string path)
{ {
if (path.EndsWith("/", StringComparison.Ordinal)) if (path.EndsWith("/", StringComparison.Ordinal))
path = path.Substring(0, path.Length - 1); path = path.Substring(0, path.Length - 1);
Name = path;
Parent = parent; Parent = parent;
this.path = path;
} }
public Stream GetStream(string filename) public Stream GetStream(string filename)
{ {
// Zip files use '/' as a path separator // Zip files use '/' as a path separator
return Parent.GetStream(path + '/' + filename); return Parent.GetStream(Name + '/' + filename);
} }
public IEnumerable<string> Contents public IEnumerable<string> Contents
@@ -167,9 +166,9 @@ namespace OpenRA.FileSystem
{ {
foreach (var entry in Parent.Contents) foreach (var entry in Parent.Contents)
{ {
if (entry.StartsWith(path, StringComparison.Ordinal) && entry != path) if (entry.StartsWith(Name, StringComparison.Ordinal) && entry != Name)
{ {
var filename = entry.Substring(path.Length + 1); var filename = entry.Substring(Name.Length + 1);
var dirLevels = filename.Split('/').Count(c => !string.IsNullOrEmpty(c)); var dirLevels = filename.Split('/').Count(c => !string.IsNullOrEmpty(c));
if (dirLevels == 1) if (dirLevels == 1)
yield return filename; yield return filename;
@@ -180,12 +179,12 @@ namespace OpenRA.FileSystem
public bool Contains(string filename) public bool Contains(string filename)
{ {
return Parent.Contains(path + '/' + filename); return Parent.Contains(Name + '/' + filename);
} }
public IReadOnlyPackage OpenPackage(string filename, FileSystem context) public IReadOnlyPackage OpenPackage(string filename, FileSystem context)
{ {
return Parent.OpenPackage(path + '/' + filename, context); return Parent.OpenPackage(Name + '/' + filename, context);
} }
public void Dispose() { /* nothing to do */ } public void Dispose() { /* nothing to do */ }

View File

@@ -37,12 +37,13 @@ namespace OpenRA.Graphics
readonly List<Sheet> sheets = new List<Sheet>(); readonly List<Sheet> sheets = new List<Sheet>();
readonly Func<Sheet> allocateSheet; readonly Func<Sheet> allocateSheet;
readonly int margin; readonly int margin;
Sheet current;
TextureChannel channel;
int rowHeight = 0; int rowHeight = 0;
int2 p; int2 p;
public Sheet Current { get; private set; }
public TextureChannel CurrentChannel { get; private set; }
public IEnumerable<Sheet> AllSheets => sheets;
public static Sheet AllocateSheet(SheetType type, int sheetSize) public static Sheet AllocateSheet(SheetType type, int sheetSize)
{ {
return new Sheet(type, new Size(sheetSize, sheetSize)); return new Sheet(type, new Size(sheetSize, sheetSize));
@@ -73,10 +74,10 @@ namespace OpenRA.Graphics
public SheetBuilder(SheetType t, Func<Sheet> allocateSheet, int margin = 1) public SheetBuilder(SheetType t, Func<Sheet> allocateSheet, int margin = 1)
{ {
channel = t == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA; CurrentChannel = t == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA;
Type = t; Type = t;
current = allocateSheet(); Current = allocateSheet();
sheets.Add(current); sheets.Add(Current);
this.allocateSheet = allocateSheet; this.allocateSheet = allocateSheet;
this.margin = margin; this.margin = margin;
} }
@@ -87,11 +88,11 @@ namespace OpenRA.Graphics
{ {
// Don't bother allocating empty sprites // Don't bother allocating empty sprites
if (size.Width == 0 || size.Height == 0) if (size.Width == 0 || size.Height == 0)
return new Sprite(current, Rectangle.Empty, 0, spriteOffset, channel, BlendMode.Alpha); return new Sprite(Current, Rectangle.Empty, 0, spriteOffset, CurrentChannel, BlendMode.Alpha);
var rect = Allocate(size, zRamp, spriteOffset); var rect = Allocate(size, zRamp, spriteOffset);
Util.FastCopyIntoChannel(rect, src, type); Util.FastCopyIntoChannel(rect, src, type);
current.CommitBufferedData(); Current.CommitBufferedData();
return rect; return rect;
} }
@@ -99,7 +100,7 @@ namespace OpenRA.Graphics
{ {
var rect = Allocate(new Size(src.Width, src.Height), scale); var rect = Allocate(new Size(src.Width, src.Height), scale);
Util.FastCopyIntoSprite(rect, src); Util.FastCopyIntoSprite(rect, src);
current.CommitBufferedData(); Current.CommitBufferedData();
return rect; return rect;
} }
@@ -115,7 +116,7 @@ namespace OpenRA.Graphics
public Sprite Allocate(Size imageSize, float scale = 1f) { return Allocate(imageSize, 0, float3.Zero, scale); } public Sprite Allocate(Size imageSize, float scale = 1f) { return Allocate(imageSize, 0, float3.Zero, scale); }
public Sprite Allocate(Size imageSize, float zRamp, in float3 spriteOffset, float scale = 1f) public Sprite Allocate(Size imageSize, float zRamp, in float3 spriteOffset, float scale = 1f)
{ {
if (imageSize.Width + p.X + margin > current.Size.Width) if (imageSize.Width + p.X + margin > Current.Size.Width)
{ {
p = new int2(0, p.Y + rowHeight + margin); p = new int2(0, p.Y + rowHeight + margin);
rowHeight = imageSize.Height; rowHeight = imageSize.Height;
@@ -124,33 +125,29 @@ namespace OpenRA.Graphics
if (imageSize.Height > rowHeight) if (imageSize.Height > rowHeight)
rowHeight = imageSize.Height; rowHeight = imageSize.Height;
if (p.Y + imageSize.Height + margin > current.Size.Height) if (p.Y + imageSize.Height + margin > Current.Size.Height)
{ {
var next = NextChannel(channel); var next = NextChannel(CurrentChannel);
if (next == null) if (next == null)
{ {
current.ReleaseBuffer(); Current.ReleaseBuffer();
current = allocateSheet(); Current = allocateSheet();
sheets.Add(current); sheets.Add(Current);
channel = Type == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA; CurrentChannel = Type == SheetType.Indexed ? TextureChannel.Red : TextureChannel.RGBA;
} }
else else
channel = next.Value; CurrentChannel = next.Value;
rowHeight = imageSize.Height; rowHeight = imageSize.Height;
p = int2.Zero; p = int2.Zero;
} }
var rect = new Sprite(current, new Rectangle(p.X + margin, p.Y + margin, imageSize.Width, imageSize.Height), zRamp, spriteOffset, channel, BlendMode.Alpha, scale); var rect = new Sprite(Current, new Rectangle(p.X + margin, p.Y + margin, imageSize.Width, imageSize.Height), zRamp, spriteOffset, CurrentChannel, BlendMode.Alpha, scale);
p += new int2(imageSize.Width + margin, 0); p += new int2(imageSize.Width + margin, 0);
return rect; return rect;
} }
public Sheet Current => current;
public TextureChannel CurrentChannel => channel;
public IEnumerable<Sheet> AllSheets => sheets;
public void Dispose() public void Dispose()
{ {
foreach (var sheet in sheets) foreach (var sheet in sheets)

View File

@@ -21,102 +21,95 @@ namespace OpenRA.Graphics
readonly Sprite sprite; readonly Sprite sprite;
readonly WPos pos; readonly WPos pos;
readonly WVec offset;
readonly int zOffset;
readonly PaletteReference palette;
readonly float scale; readonly float scale;
readonly WAngle rotation = WAngle.Zero; readonly WAngle rotation = WAngle.Zero;
readonly float3 tint;
readonly TintModifiers tintModifiers;
readonly float alpha;
readonly bool isDecoration;
public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, float alpha, public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, float alpha,
float3 tint, TintModifiers tintModifiers, bool isDecoration, WAngle rotation) float3 tint, TintModifiers tintModifiers, bool isDecoration, WAngle rotation)
{ {
this.sprite = sprite; this.sprite = sprite;
this.pos = pos; this.pos = pos;
this.offset = offset; Offset = offset;
this.zOffset = zOffset; ZOffset = zOffset;
this.palette = palette; Palette = palette;
this.scale = scale; this.scale = scale;
this.rotation = rotation; this.rotation = rotation;
this.tint = tint; Tint = tint;
this.isDecoration = isDecoration; IsDecoration = isDecoration;
this.tintModifiers = tintModifiers; TintModifiers = tintModifiers;
this.alpha = alpha; Alpha = alpha;
// PERF: Remove useless palette assignments for RGBA sprites // PERF: Remove useless palette assignments for RGBA sprites
// HACK: This is working around the fact that palettes are defined on traits rather than sequences // HACK: This is working around the fact that palettes are defined on traits rather than sequences
// and can be removed once this has been fixed // and can be removed once this has been fixed
if (sprite.Channel == TextureChannel.RGBA && !(palette?.HasColorShift ?? false)) if (sprite.Channel == TextureChannel.RGBA && !(palette?.HasColorShift ?? false))
this.palette = null; Palette = null;
} }
public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, float alpha, public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, float alpha,
float3 tint, TintModifiers tintModifiers, bool isDecoration) float3 tint, TintModifiers tintModifiers, bool isDecoration)
: this(sprite, pos, offset, zOffset, palette, scale, alpha, tint, tintModifiers, isDecoration, WAngle.Zero) { } : this(sprite, pos, offset, zOffset, palette, scale, alpha, tint, tintModifiers, isDecoration, WAngle.Zero) { }
public WPos Pos => pos + offset; public WPos Pos => pos + Offset;
public WVec Offset => offset; public WVec Offset { get; }
public PaletteReference Palette => palette; public PaletteReference Palette { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => isDecoration; public bool IsDecoration { get; }
public float Alpha => alpha; public float Alpha { get; }
public float3 Tint => tint; public float3 Tint { get; }
public TintModifiers TintModifiers => tintModifiers; public TintModifiers TintModifiers { get; }
public IPalettedRenderable WithPalette(PaletteReference newPalette) public IPalettedRenderable WithPalette(PaletteReference newPalette)
{ {
return new SpriteRenderable(sprite, pos, offset, zOffset, newPalette, scale, alpha, tint, tintModifiers, isDecoration, rotation); return new SpriteRenderable(sprite, pos, Offset, ZOffset, newPalette, scale, Alpha, Tint, TintModifiers, IsDecoration, rotation);
} }
public IRenderable WithZOffset(int newOffset) public IRenderable WithZOffset(int newOffset)
{ {
return new SpriteRenderable(sprite, pos, offset, newOffset, palette, scale, alpha, tint, tintModifiers, isDecoration, rotation); return new SpriteRenderable(sprite, pos, Offset, newOffset, Palette, scale, Alpha, Tint, TintModifiers, IsDecoration, rotation);
} }
public IRenderable OffsetBy(in WVec vec) public IRenderable OffsetBy(in WVec vec)
{ {
return new SpriteRenderable(sprite, pos + vec, offset, zOffset, palette, scale, alpha, tint, tintModifiers, isDecoration, rotation); return new SpriteRenderable(sprite, pos + vec, Offset, ZOffset, Palette, scale, Alpha, Tint, TintModifiers, IsDecoration, rotation);
} }
public IRenderable AsDecoration() public IRenderable AsDecoration()
{ {
return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, alpha, tint, tintModifiers, true, rotation); return new SpriteRenderable(sprite, pos, Offset, ZOffset, Palette, scale, Alpha, Tint, TintModifiers, true, rotation);
} }
public IModifyableRenderable WithAlpha(float newAlpha) public IModifyableRenderable WithAlpha(float newAlpha)
{ {
return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, newAlpha, tint, tintModifiers, isDecoration, rotation); return new SpriteRenderable(sprite, pos, Offset, ZOffset, Palette, scale, newAlpha, Tint, TintModifiers, IsDecoration, rotation);
} }
public IModifyableRenderable WithTint(in float3 newTint, TintModifiers newTintModifiers) public IModifyableRenderable WithTint(in float3 newTint, TintModifiers newTintModifiers)
{ {
return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, alpha, newTint, newTintModifiers, isDecoration, rotation); return new SpriteRenderable(sprite, pos, Offset, ZOffset, Palette, scale, Alpha, newTint, newTintModifiers, IsDecoration, rotation);
} }
float3 ScreenPosition(WorldRenderer wr) float3 ScreenPosition(WorldRenderer wr)
{ {
var s = 0.5f * scale * sprite.Size; var s = 0.5f * scale * sprite.Size;
return wr.Screen3DPxPosition(pos) + wr.ScreenPxOffset(offset) - new float3((int)s.X, (int)s.Y, s.Z); return wr.Screen3DPxPosition(pos) + wr.ScreenPxOffset(Offset) - new float3((int)s.X, (int)s.Y, s.Z);
} }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
var wsr = Game.Renderer.WorldSpriteRenderer; var wsr = Game.Renderer.WorldSpriteRenderer;
var t = alpha * tint; var t = Alpha * Tint;
if (wr.TerrainLighting != null && (tintModifiers & TintModifiers.IgnoreWorldTint) == 0) if (wr.TerrainLighting != null && (TintModifiers & TintModifiers.IgnoreWorldTint) == 0)
t *= wr.TerrainLighting.TintAt(pos); t *= wr.TerrainLighting.TintAt(pos);
// Shader interprets negative alpha as a flag to use the tint colour directly instead of multiplying the sprite colour // Shader interprets negative alpha as a flag to use the tint colour directly instead of multiplying the sprite colour
var a = alpha; var a = Alpha;
if ((tintModifiers & TintModifiers.ReplaceColor) != 0) if ((TintModifiers & TintModifiers.ReplaceColor) != 0)
a *= -1; a *= -1;
wsr.DrawSprite(sprite, palette, ScreenPosition(wr), scale, t, a, rotation.RendererRadians()); wsr.DrawSprite(sprite, Palette, ScreenPosition(wr), scale, t, a, rotation.RendererRadians());
} }
public void RenderDebugGeometry(WorldRenderer wr) public void RenderDebugGeometry(WorldRenderer wr)

View File

@@ -16,10 +16,7 @@ namespace OpenRA.Graphics
public class UISpriteRenderable : IRenderable, IPalettedRenderable, IFinalizedRenderable public class UISpriteRenderable : IRenderable, IPalettedRenderable, IFinalizedRenderable
{ {
readonly Sprite sprite; readonly Sprite sprite;
readonly WPos effectiveWorldPos;
readonly int2 screenPos; readonly int2 screenPos;
readonly int zOffset;
readonly PaletteReference palette;
readonly float scale; readonly float scale;
readonly float alpha; readonly float alpha;
readonly float rotation = 0f; readonly float rotation = 0f;
@@ -27,10 +24,10 @@ namespace OpenRA.Graphics
public UISpriteRenderable(Sprite sprite, WPos effectiveWorldPos, int2 screenPos, int zOffset, PaletteReference palette, float scale = 1f, float alpha = 1f, float rotation = 0f) public UISpriteRenderable(Sprite sprite, WPos effectiveWorldPos, int2 screenPos, int zOffset, PaletteReference palette, float scale = 1f, float alpha = 1f, float rotation = 0f)
{ {
this.sprite = sprite; this.sprite = sprite;
this.effectiveWorldPos = effectiveWorldPos; Pos = effectiveWorldPos;
this.screenPos = screenPos; this.screenPos = screenPos;
this.zOffset = zOffset; ZOffset = zOffset;
this.palette = palette; Palette = palette;
this.scale = scale; this.scale = scale;
this.alpha = alpha; this.alpha = alpha;
this.rotation = rotation; this.rotation = rotation;
@@ -39,18 +36,18 @@ namespace OpenRA.Graphics
// HACK: This is working around the fact that palettes are defined on traits rather than sequences // HACK: This is working around the fact that palettes are defined on traits rather than sequences
// and can be removed once this has been fixed // and can be removed once this has been fixed
if (sprite.Channel == TextureChannel.RGBA && !(palette?.HasColorShift ?? false)) if (sprite.Channel == TextureChannel.RGBA && !(palette?.HasColorShift ?? false))
this.palette = null; Palette = null;
} }
// Does not exist in the world, so a world positions don't make sense // Does not exist in the world, so a world positions don't make sense
public WPos Pos => effectiveWorldPos; public WPos Pos { get; }
public WVec Offset => WVec.Zero; public WVec Offset => WVec.Zero;
public bool IsDecoration => true; public bool IsDecoration => true;
public PaletteReference Palette => palette; public PaletteReference Palette { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public IPalettedRenderable WithPalette(PaletteReference newPalette) { return new UISpriteRenderable(sprite, effectiveWorldPos, screenPos, zOffset, newPalette, scale, alpha, rotation); } public IPalettedRenderable WithPalette(PaletteReference newPalette) { return new UISpriteRenderable(sprite, Pos, screenPos, ZOffset, newPalette, scale, alpha, rotation); }
public IRenderable WithZOffset(int newOffset) { return this; } public IRenderable WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(in WVec vec) { return this; } public IRenderable OffsetBy(in WVec vec) { return this; }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
@@ -58,7 +55,7 @@ namespace OpenRA.Graphics
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
Game.Renderer.SpriteRenderer.DrawSprite(sprite, palette, screenPos, scale, float3.Ones, alpha, rotation); Game.Renderer.SpriteRenderer.DrawSprite(sprite, Palette, screenPos, scale, float3.Ones, alpha, rotation);
} }
public void RenderDebugGeometry(WorldRenderer wr) public void RenderDebugGeometry(WorldRenderer wr)

View File

@@ -66,9 +66,6 @@ namespace OpenRA.Graphics
WorldViewport lastViewportDistance; WorldViewport lastViewportDistance;
float zoom = 1f; float zoom = 1f;
float minZoom = 1f;
float maxZoom = 2f;
bool unlockMinZoom; bool unlockMinZoom;
float unlockedMinZoomScale; float unlockedMinZoomScale;
float unlockedMinZoom = 1f; float unlockedMinZoom = 1f;
@@ -86,12 +83,13 @@ namespace OpenRA.Graphics
} }
} }
public float MinZoom => minZoom; public float MinZoom { get; private set; } = 1f;
public float MaxZoom { get; private set; } = 2f;
public void AdjustZoom(float dz) public void AdjustZoom(float dz)
{ {
// Exponential ensures that equal positive and negative steps have the same effect // Exponential ensures that equal positive and negative steps have the same effect
Zoom = (zoom * (float)Math.Exp(dz)).Clamp(unlockMinZoom ? unlockedMinZoom : minZoom, maxZoom); Zoom = (zoom * (float)Math.Exp(dz)).Clamp(unlockMinZoom ? unlockedMinZoom : MinZoom, MaxZoom);
} }
public void AdjustZoom(float dz, int2 center) public void AdjustZoom(float dz, int2 center)
@@ -105,10 +103,10 @@ namespace OpenRA.Graphics
public void ToggleZoom() public void ToggleZoom()
{ {
// Unlocked zooms always reset to the default zoom // Unlocked zooms always reset to the default zoom
if (zoom < minZoom) if (zoom < MinZoom)
Zoom = minZoom; Zoom = MinZoom;
else else
Zoom = zoom > minZoom ? minZoom : maxZoom; Zoom = zoom > MinZoom ? MinZoom : MaxZoom;
} }
public void UnlockMinimumZoom(float scale) public void UnlockMinimumZoom(float scale)
@@ -210,14 +208,14 @@ namespace OpenRA.Graphics
var vd = graphicSettings.ViewportDistance; var vd = graphicSettings.ViewportDistance;
if (viewportSizes.AllowNativeZoom && vd == WorldViewport.Native) if (viewportSizes.AllowNativeZoom && vd == WorldViewport.Native)
minZoom = viewportSizes.DefaultScale; MinZoom = viewportSizes.DefaultScale;
else else
{ {
var range = viewportSizes.GetSizeRange(vd); var range = viewportSizes.GetSizeRange(vd);
minZoom = CalculateMinimumZoom(range.X, range.Y) * viewportSizes.DefaultScale; MinZoom = CalculateMinimumZoom(range.X, range.Y) * viewportSizes.DefaultScale;
} }
maxZoom = Math.Min(minZoom * viewportSizes.MaxZoomScale, Game.Renderer.NativeResolution.Height * viewportSizes.DefaultScale / viewportSizes.MaxZoomWindowHeight); MaxZoom = Math.Min(MinZoom * viewportSizes.MaxZoomScale, Game.Renderer.NativeResolution.Height * viewportSizes.DefaultScale / viewportSizes.MaxZoomWindowHeight);
if (unlockMinZoom) if (unlockMinZoom)
{ {
@@ -225,19 +223,19 @@ namespace OpenRA.Graphics
// TODO: Allow zooming out until the full map is visible // TODO: Allow zooming out until the full map is visible
// We need to improve our viewport scroll handling to center the map as we zoom out // We need to improve our viewport scroll handling to center the map as we zoom out
// before this will work well enough to enable // before this will work well enough to enable
unlockedMinZoom = minZoom * unlockedMinZoomScale; unlockedMinZoom = MinZoom * unlockedMinZoomScale;
} }
if (resetCurrentZoom) if (resetCurrentZoom)
Zoom = minZoom; Zoom = MinZoom;
else else
Zoom = Zoom.Clamp(minZoom, maxZoom); Zoom = Zoom.Clamp(MinZoom, MaxZoom);
var maxSize = 1f / (unlockMinZoom ? unlockedMinZoom : minZoom) * new float2(Game.Renderer.NativeResolution); var maxSize = 1f / (unlockMinZoom ? unlockedMinZoom : MinZoom) * new float2(Game.Renderer.NativeResolution);
Game.Renderer.SetMaximumViewportSize(new Size((int)maxSize.X, (int)maxSize.Y)); Game.Renderer.SetMaximumViewportSize(new Size((int)maxSize.X, (int)maxSize.Y));
foreach (var t in worldRenderer.World.WorldActor.TraitsImplementing<INotifyViewportZoomExtentsChanged>()) foreach (var t in worldRenderer.World.WorldActor.TraitsImplementing<INotifyViewportZoomExtentsChanged>())
t.ViewportZoomExtentsChanged(minZoom, maxZoom); t.ViewportZoomExtentsChanged(MinZoom, MaxZoom);
} }
public CPos ViewToWorld(int2 view) public CPos ViewToWorld(int2 view)

View File

@@ -126,15 +126,12 @@ namespace OpenRA
// Current position, in map coordinates // Current position, in map coordinates
int u, v; int u, v;
// Current position, in cell coordinates
CPos current;
public CellRegionEnumerator(CellRegion region) public CellRegionEnumerator(CellRegion region)
: this() : this()
{ {
r = region; r = region;
Reset(); Reset();
current = new MPos(u, v).ToCPos(r.gridType); Current = new MPos(u, v).ToCPos(r.gridType);
} }
public bool MoveNext() public bool MoveNext()
@@ -152,7 +149,8 @@ namespace OpenRA
return false; return false;
} }
current = new MPos(u, v).ToCPos(r.gridType); // Current position, in cell coordinates
Current = new MPos(u, v).ToCPos(r.gridType);
return true; return true;
} }
@@ -163,7 +161,7 @@ namespace OpenRA
v = r.mapTopLeft.V; v = r.mapTopLeft.V;
} }
public CPos Current => current; public CPos Current { get; private set; }
object IEnumerator.Current => Current; object IEnumerator.Current => Current;
public void Dispose() { } public void Dispose() { }
} }

View File

@@ -19,7 +19,6 @@ namespace OpenRA
public struct MapCoordsEnumerator : IEnumerator<MPos> public struct MapCoordsEnumerator : IEnumerator<MPos>
{ {
readonly MapCoordsRegion r; readonly MapCoordsRegion r;
MPos current;
public MapCoordsEnumerator(MapCoordsRegion region) public MapCoordsEnumerator(MapCoordsRegion region)
: this() : this()
@@ -30,41 +29,38 @@ namespace OpenRA
public bool MoveNext() public bool MoveNext()
{ {
var u = current.U + 1; var u = Current.U + 1;
var v = current.V; var v = Current.V;
// Check for column overflow // Check for column overflow
if (u > r.bottomRight.U) if (u > r.BottomRight.U)
{ {
v += 1; v += 1;
u = r.topLeft.U; u = r.TopLeft.U;
// Check for row overflow // Check for row overflow
if (v > r.bottomRight.V) if (v > r.BottomRight.V)
return false; return false;
} }
current = new MPos(u, v); Current = new MPos(u, v);
return true; return true;
} }
public void Reset() public void Reset()
{ {
current = new MPos(r.topLeft.U - 1, r.topLeft.V); Current = new MPos(r.TopLeft.U - 1, r.TopLeft.V);
} }
public MPos Current => current; public MPos Current { get; private set; }
object IEnumerator.Current => Current; object IEnumerator.Current => Current;
public void Dispose() { } public void Dispose() { }
} }
readonly MPos topLeft;
readonly MPos bottomRight;
public MapCoordsRegion(MPos mapTopLeft, MPos mapBottomRight) public MapCoordsRegion(MPos mapTopLeft, MPos mapBottomRight)
{ {
topLeft = mapTopLeft; TopLeft = mapTopLeft;
bottomRight = mapBottomRight; BottomRight = mapBottomRight;
} }
public override string ToString() public override string ToString()
@@ -87,7 +83,7 @@ namespace OpenRA
return GetEnumerator(); return GetEnumerator();
} }
public MPos TopLeft => topLeft; public MPos TopLeft { get; }
public MPos BottomRight => bottomRight; public MPos BottomRight { get; }
} }
} }

View File

@@ -83,14 +83,12 @@ namespace OpenRA
// Current position, in projected map coordinates // Current position, in projected map coordinates
int u, v; int u, v;
PPos current;
public ProjectedCellRegionEnumerator(ProjectedCellRegion region) public ProjectedCellRegionEnumerator(ProjectedCellRegion region)
: this() : this()
{ {
r = region; r = region;
Reset(); Reset();
current = new PPos(u, v); Current = new PPos(u, v);
} }
public bool MoveNext() public bool MoveNext()
@@ -108,7 +106,7 @@ namespace OpenRA
return false; return false;
} }
current = new PPos(u, v); Current = new PPos(u, v);
return true; return true;
} }
@@ -119,7 +117,7 @@ namespace OpenRA
v = r.TopLeft.V; v = r.TopLeft.V;
} }
public PPos Current => current; public PPos Current { get; private set; }
object IEnumerator.Current => Current; object IEnumerator.Current => Current;
public void Dispose() { } public void Dispose() { }
} }

View File

@@ -107,12 +107,9 @@ namespace OpenRA.Network
readonly Queue<OrderPacket> sentImmediateOrders = new Queue<OrderPacket>(); readonly Queue<OrderPacket> sentImmediateOrders = new Queue<OrderPacket>();
readonly ConcurrentQueue<(int FromClient, byte[] Data)> receivedPackets = new ConcurrentQueue<(int, byte[])>(); readonly ConcurrentQueue<(int FromClient, byte[] Data)> receivedPackets = new ConcurrentQueue<(int, byte[])>();
TcpClient tcp; TcpClient tcp;
IPEndPoint endpoint;
volatile ConnectionState connectionState = ConnectionState.Connecting; volatile ConnectionState connectionState = ConnectionState.Connecting;
volatile int clientId; volatile int clientId;
bool disposed; bool disposed;
string errorMessage;
public NetworkConnection(ConnectionTarget target) public NetworkConnection(ConnectionTarget target)
{ {
@@ -124,6 +121,12 @@ namespace OpenRA.Network
}.Start(); }.Start();
} }
public ConnectionState ConnectionState => connectionState;
public IPEndPoint EndPoint { get; private set; }
public string ErrorMessage { get; private set; }
void NetworkConnectionConnect() void NetworkConnectionConnect()
{ {
var queue = new BlockingCollection<TcpClient>(); var queue = new BlockingCollection<TcpClient>();
@@ -151,7 +154,7 @@ namespace OpenRA.Network
} }
catch (Exception ex) catch (Exception ex)
{ {
errorMessage = "Failed to connect"; ErrorMessage = "Failed to connect";
Log.Write("client", $"Failed to connect to {endpoint}: {ex.Message}"); Log.Write("client", $"Failed to connect to {endpoint}: {ex.Message}");
} }
}) })
@@ -163,7 +166,7 @@ namespace OpenRA.Network
if (!atLeastOneEndpoint) if (!atLeastOneEndpoint)
{ {
errorMessage = "Failed to resolve address"; ErrorMessage = "Failed to resolve address";
connectionState = ConnectionState.NotConnected; connectionState = ConnectionState.NotConnected;
} }
@@ -171,7 +174,7 @@ namespace OpenRA.Network
else if (queue.TryTake(out tcp, 5000)) else if (queue.TryTake(out tcp, 5000))
{ {
// Copy endpoint here to have it even after getting disconnected. // Copy endpoint here to have it even after getting disconnected.
endpoint = (IPEndPoint)tcp.Client.RemoteEndPoint; EndPoint = (IPEndPoint)tcp.Client.RemoteEndPoint;
new Thread(NetworkConnectionReceive) new Thread(NetworkConnectionReceive)
{ {
@@ -215,8 +218,8 @@ namespace OpenRA.Network
} }
catch (Exception ex) catch (Exception ex)
{ {
errorMessage = "Connection failed"; ErrorMessage = "Connection failed";
Log.Write("client", $"Connection to {endpoint} failed: {ex.Message}"); Log.Write("client", $"Connection to {EndPoint} failed: {ex.Message}");
} }
finally finally
{ {
@@ -367,12 +370,6 @@ namespace OpenRA.Network
Recorder = new ReplayRecorder(chooseFilename); Recorder = new ReplayRecorder(chooseFilename);
} }
public ConnectionState ConnectionState => connectionState;
public IPEndPoint EndPoint => endpoint;
public string ErrorMessage => errorMessage;
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
if (disposed) if (disposed)

View File

@@ -329,6 +329,8 @@ namespace OpenRA
case OrderType.Fields: case OrderType.Fields:
{ {
var targetState = Target.SerializableState;
var fields = OrderFields.None; var fields = OrderFields.None;
if (Subject != null) if (Subject != null)
fields |= OrderFields.Subject; fields |= OrderFields.Subject;
@@ -339,7 +341,7 @@ namespace OpenRA
if (ExtraData != 0) if (ExtraData != 0)
fields |= OrderFields.ExtraData; fields |= OrderFields.ExtraData;
if (Target.SerializableType != TargetType.Invalid) if (targetState.Type != TargetType.Invalid)
fields |= OrderFields.Target; fields |= OrderFields.Target;
if (Queued) if (Queued)
@@ -354,7 +356,7 @@ namespace OpenRA
if (ExtraLocation != CPos.Zero) if (ExtraLocation != CPos.Zero)
fields |= OrderFields.ExtraLocation; fields |= OrderFields.ExtraLocation;
if (Target.SerializableCell != null) if (targetState.Cell != null)
fields |= OrderFields.TargetIsCell; fields |= OrderFields.TargetIsCell;
w.Write((short)fields); w.Write((short)fields);
@@ -364,12 +366,12 @@ namespace OpenRA
if (fields.HasField(OrderFields.Target)) if (fields.HasField(OrderFields.Target))
{ {
w.Write((byte)Target.SerializableType); w.Write((byte)targetState.Type);
switch (Target.SerializableType) switch (targetState.Type)
{ {
case TargetType.Actor: case TargetType.Actor:
w.Write(UIntFromActor(Target.SerializableActor)); w.Write(UIntFromActor(targetState.Actor));
w.Write(Target.SerializableGeneration); w.Write(targetState.Generation);
break; break;
case TargetType.FrozenActor: case TargetType.FrozenActor:
w.Write(Target.FrozenActor.Viewer.PlayerActor.ActorID); w.Write(Target.FrozenActor.Viewer.PlayerActor.ActorID);
@@ -378,14 +380,14 @@ namespace OpenRA
case TargetType.Terrain: case TargetType.Terrain:
if (fields.HasField(OrderFields.TargetIsCell)) if (fields.HasField(OrderFields.TargetIsCell))
{ {
w.Write(Target.SerializableCell.Value.Bits); w.Write(targetState.Cell.Value.Bits);
w.Write((byte)Target.SerializableSubCell); w.Write((byte)targetState.SubCell);
} }
else else
{ {
w.Write(Target.SerializablePos.X); w.Write(targetState.Pos.X);
w.Write(Target.SerializablePos.Y); w.Write(targetState.Pos.Y);
w.Write(Target.SerializablePos.Z); w.Write(targetState.Pos.Z);
} }
break; break;

View File

@@ -17,19 +17,13 @@ namespace OpenRA.Network
{ {
readonly Func<int> timestep; readonly Func<int> timestep;
long lastTickTime;
public TickTime(Func<int> timestep, long lastTickTime) public TickTime(Func<int> timestep, long lastTickTime)
{ {
this.timestep = timestep; this.timestep = timestep;
this.lastTickTime = lastTickTime; Value = lastTickTime;
} }
public long Value public long Value { get; set; }
{
get => lastTickTime;
set => lastTickTime = value;
}
public bool ShouldAdvance(long tick) public bool ShouldAdvance(long tick)
{ {
@@ -38,18 +32,18 @@ namespace OpenRA.Network
if (i == 0) if (i == 0)
return false; return false;
var tickDelta = tick - lastTickTime; var tickDelta = tick - Value;
return tickDelta >= i; return tickDelta >= i;
} }
public void AdvanceTickTime(long tick) public void AdvanceTickTime(long tick)
{ {
var tickDelta = tick - lastTickTime; var tickDelta = tick - Value;
var currentTimestep = timestep(); var currentTimestep = timestep();
var integralTickTimestep = tickDelta / currentTimestep * currentTimestep; var integralTickTimestep = tickDelta / currentTimestep * currentTimestep;
lastTickTime += integralTickTimestep >= Game.TimestepJankThreshold Value += integralTickTimestep >= Game.TimestepJankThreshold
? integralTickTimestep ? integralTickTimestep
: currentTimestep; : currentTimestep;
} }

View File

@@ -52,12 +52,11 @@ namespace OpenRA
IFrameBuffer worldBuffer; IFrameBuffer worldBuffer;
Sheet worldSheet; Sheet worldSheet;
Sprite worldSprite; Sprite worldSprite;
int worldDownscaleFactor = 1;
Size lastMaximumViewportSize; Size lastMaximumViewportSize;
Size lastWorldViewportSize; Size lastWorldViewportSize;
public Size WorldFrameBufferSize => worldSheet.Size; public Size WorldFrameBufferSize => worldSheet.Size;
public int WorldDownscaleFactor => worldDownscaleFactor; public int WorldDownscaleFactor { get; private set; } = 1;
SheetBuilder fontSheetBuilder; SheetBuilder fontSheetBuilder;
readonly IPlatform platform; readonly IPlatform platform;
@@ -240,11 +239,11 @@ namespace OpenRA
var vh = worldViewport.Size.Height; var vh = worldViewport.Size.Height;
var bw = worldSheet.Size.Width; var bw = worldSheet.Size.Width;
var bh = worldSheet.Size.Height; var bh = worldSheet.Size.Height;
worldDownscaleFactor = 1; WorldDownscaleFactor = 1;
while (vw / worldDownscaleFactor > bw || vh / worldDownscaleFactor > bh) while (vw / WorldDownscaleFactor > bw || vh / WorldDownscaleFactor > bh)
worldDownscaleFactor++; WorldDownscaleFactor++;
var s = new Size(vw / worldDownscaleFactor, vh / worldDownscaleFactor); var s = new Size(vw / WorldDownscaleFactor, vh / WorldDownscaleFactor);
worldSprite = new Sprite(worldSheet, new Rectangle(int2.Zero, s), TextureChannel.RGBA); worldSprite = new Sprite(worldSheet, new Rectangle(int2.Zero, s), TextureChannel.RGBA);
lastWorldViewportSize = worldViewport.Size; lastWorldViewportSize = worldViewport.Size;
} }
@@ -253,7 +252,7 @@ namespace OpenRA
if (lastWorldViewport != worldViewport) if (lastWorldViewport != worldViewport)
{ {
WorldSpriteRenderer.SetViewportParams(worldSheet.Size, worldDownscaleFactor, depthMargin, worldViewport.Location); WorldSpriteRenderer.SetViewportParams(worldSheet.Size, WorldDownscaleFactor, depthMargin, worldViewport.Location);
WorldModelRenderer.SetViewportParams(); WorldModelRenderer.SetViewportParams();
lastWorldViewport = worldViewport; lastWorldViewport = worldViewport;
@@ -391,10 +390,10 @@ namespace OpenRA
if (renderType == RenderType.World) if (renderType == RenderType.World)
{ {
var r = Rectangle.FromLTRB( var r = Rectangle.FromLTRB(
rect.Left / worldDownscaleFactor, rect.Left / WorldDownscaleFactor,
rect.Top / worldDownscaleFactor, rect.Top / WorldDownscaleFactor,
(rect.Right + worldDownscaleFactor - 1) / worldDownscaleFactor, (rect.Right + WorldDownscaleFactor - 1) / WorldDownscaleFactor,
(rect.Bottom + worldDownscaleFactor - 1) / worldDownscaleFactor); (rect.Bottom + WorldDownscaleFactor - 1) / WorldDownscaleFactor);
worldBuffer.EnableScissor(r); worldBuffer.EnableScissor(r);
} }
else else
@@ -415,10 +414,10 @@ namespace OpenRA
{ {
var rect = scissorState.Peek(); var rect = scissorState.Peek();
var r = Rectangle.FromLTRB( var r = Rectangle.FromLTRB(
rect.Left / worldDownscaleFactor, rect.Left / WorldDownscaleFactor,
rect.Top / worldDownscaleFactor, rect.Top / WorldDownscaleFactor,
(rect.Right + worldDownscaleFactor - 1) / worldDownscaleFactor, (rect.Right + WorldDownscaleFactor - 1) / WorldDownscaleFactor,
(rect.Bottom + worldDownscaleFactor - 1) / worldDownscaleFactor); (rect.Bottom + WorldDownscaleFactor - 1) / WorldDownscaleFactor);
worldBuffer.EnableScissor(r); worldBuffer.EnableScissor(r);
} }
else else

View File

@@ -43,7 +43,6 @@ namespace OpenRA
ISoundSource videoSource; ISoundSource videoSource;
ISound music; ISound music;
ISound video; ISound video;
MusicInfo currentMusic;
readonly Dictionary<uint, ISound> currentSounds = new Dictionary<uint, ISound>(); readonly Dictionary<uint, ISound> currentSounds = new Dictionary<uint, ISound>();
readonly Dictionary<string, ISound> currentNotifications = new Dictionary<string, ISound>(); readonly Dictionary<string, ISound> currentNotifications = new Dictionary<string, ISound>();
public bool DummyEngine { get; } public bool DummyEngine { get; }
@@ -226,7 +225,7 @@ namespace OpenRA
Action onMusicComplete; Action onMusicComplete;
public bool MusicPlaying { get; private set; } public bool MusicPlaying { get; private set; }
public MusicInfo CurrentMusic => currentMusic; public MusicInfo CurrentMusic { get; private set; }
public void PlayMusicThen(MusicInfo m, Action then) public void PlayMusicThen(MusicInfo m, Action then)
{ {
@@ -235,7 +234,7 @@ namespace OpenRA
onMusicComplete = then; onMusicComplete = then;
if (m == currentMusic && music != null) if (m == CurrentMusic && music != null)
{ {
soundEngine.PauseSound(music, false); soundEngine.PauseSound(music, false);
MusicPlaying = true; MusicPlaying = true;
@@ -263,7 +262,7 @@ namespace OpenRA
return; return;
} }
currentMusic = m; CurrentMusic = m;
MusicPlaying = true; MusicPlaying = true;
} }
@@ -290,7 +289,7 @@ namespace OpenRA
music = null; music = null;
} }
currentMusic = null; CurrentMusic = null;
MusicPlaying = false; MusicPlaying = false;
} }

View File

@@ -38,10 +38,10 @@ namespace OpenRA.Traits
public readonly WPos CenterPosition; public readonly WPos CenterPosition;
readonly Actor actor; readonly Actor actor;
readonly ICreatesFrozenActors frozenTrait; readonly ICreatesFrozenActors frozenTrait;
readonly Player viewer;
readonly Shroud shroud; readonly Shroud shroud;
readonly List<WPos> targetablePositions = new List<WPos>(); readonly List<WPos> targetablePositions = new List<WPos>();
public Player Viewer { get; }
public Player Owner { get; private set; } public Player Owner { get; private set; }
public BitSet<TargetableType> TargetTypes { get; private set; } public BitSet<TargetableType> TargetTypes { get; private set; }
public IEnumerable<WPos> TargetablePositions => targetablePositions; public IEnumerable<WPos> TargetablePositions => targetablePositions;
@@ -86,7 +86,7 @@ namespace OpenRA.Traits
{ {
this.actor = actor; this.actor = actor;
this.frozenTrait = frozenTrait; this.frozenTrait = frozenTrait;
this.viewer = viewer; Viewer = viewer;
shroud = viewer.Shroud; shroud = viewer.Shroud;
NeedRenderables = startsRevealed; NeedRenderables = startsRevealed;
@@ -119,7 +119,6 @@ namespace OpenRA.Traits
public bool IsValid => Owner != null; public bool IsValid => Owner != null;
public ActorInfo Info => actor.Info; public ActorInfo Info => actor.Info;
public Actor Actor => !actor.IsDead ? actor : null; public Actor Actor => !actor.IsDead ? actor : null;
public Player Viewer => viewer;
public void RefreshState() public void RefreshState()
{ {
@@ -147,7 +146,7 @@ namespace OpenRA.Traits
Hidden = false; Hidden = false;
foreach (var visibilityModifier in visibilityModifiers) foreach (var visibilityModifier in visibilityModifiers)
{ {
if (!visibilityModifier.IsVisible(actor, viewer)) if (!visibilityModifier.IsVisible(actor, Viewer))
{ {
Hidden = true; Hidden = true;
break; break;

View File

@@ -20,10 +20,10 @@ namespace OpenRA.Traits
{ {
public static readonly Target[] None = Array.Empty<Target>(); public static readonly Target[] None = Array.Empty<Target>();
public static readonly Target Invalid = default; public static readonly Target Invalid = default;
public Actor Actor { get; }
public FrozenActor FrozenActor { get; }
readonly TargetType type; readonly TargetType type;
readonly Actor actor;
readonly FrozenActor frozen;
readonly WPos terrainCenterPosition; readonly WPos terrainCenterPosition;
readonly WPos[] terrainPositions; readonly WPos[] terrainPositions;
readonly CPos? cell; readonly CPos? cell;
@@ -36,8 +36,8 @@ namespace OpenRA.Traits
this.terrainCenterPosition = terrainCenterPosition; this.terrainCenterPosition = terrainCenterPosition;
this.terrainPositions = terrainPositions ?? new[] { terrainCenterPosition }; this.terrainPositions = terrainPositions ?? new[] { terrainCenterPosition };
actor = null; Actor = null;
frozen = null; FrozenActor = null;
cell = null; cell = null;
subCell = null; subCell = null;
generation = 0; generation = 0;
@@ -51,20 +51,20 @@ namespace OpenRA.Traits
cell = c; cell = c;
this.subCell = subCell; this.subCell = subCell;
actor = null; Actor = null;
frozen = null; FrozenActor = null;
generation = 0; generation = 0;
} }
Target(Actor a, int generation) Target(Actor a, int generation)
{ {
type = TargetType.Actor; type = TargetType.Actor;
actor = a; Actor = a;
this.generation = generation; this.generation = generation;
terrainCenterPosition = WPos.Zero; terrainCenterPosition = WPos.Zero;
terrainPositions = null; terrainPositions = null;
frozen = null; FrozenActor = null;
cell = null; cell = null;
subCell = null; subCell = null;
} }
@@ -72,11 +72,11 @@ namespace OpenRA.Traits
Target(FrozenActor fa) Target(FrozenActor fa)
{ {
type = TargetType.FrozenActor; type = TargetType.FrozenActor;
frozen = fa; FrozenActor = fa;
terrainCenterPosition = WPos.Zero; terrainCenterPosition = WPos.Zero;
terrainPositions = null; terrainPositions = null;
actor = null; Actor = null;
cell = null; cell = null;
subCell = null; subCell = null;
generation = 0; generation = 0;
@@ -88,9 +88,6 @@ namespace OpenRA.Traits
public static Target FromActor(Actor a) { return a != null ? new Target(a, a.Generation) : Invalid; } public static Target FromActor(Actor a) { return a != null ? new Target(a, a.Generation) : Invalid; }
public static Target FromFrozenActor(FrozenActor fa) { return new Target(fa); } public static Target FromFrozenActor(FrozenActor fa) { return new Target(fa); }
public Actor Actor => actor;
public FrozenActor FrozenActor => frozen;
public TargetType Type public TargetType Type
{ {
get get
@@ -98,11 +95,11 @@ namespace OpenRA.Traits
if (type == TargetType.Actor) if (type == TargetType.Actor)
{ {
// Actor is no longer in the world // Actor is no longer in the world
if (!actor.IsInWorld || actor.IsDead) if (!Actor.IsInWorld || Actor.IsDead)
return TargetType.Invalid; return TargetType.Invalid;
// Actor generation has changed (teleported or captured) // Actor generation has changed (teleported or captured)
if (actor.Generation != generation) if (Actor.Generation != generation)
return TargetType.Invalid; return TargetType.Invalid;
} }
@@ -118,9 +115,9 @@ namespace OpenRA.Traits
switch (Type) switch (Type)
{ {
case TargetType.Actor: case TargetType.Actor:
return actor.IsTargetableBy(targeter); return Actor.IsTargetableBy(targeter);
case TargetType.FrozenActor: case TargetType.FrozenActor:
return frozen.IsValid && frozen.Visible && !frozen.Hidden; return FrozenActor.IsValid && FrozenActor.Visible && !FrozenActor.Hidden;
case TargetType.Invalid: case TargetType.Invalid:
return false; return false;
default: default:
@@ -135,12 +132,12 @@ namespace OpenRA.Traits
{ {
get get
{ {
if (actor == null) if (Actor == null)
return false; return false;
// PERF: Avoid LINQ. // PERF: Avoid LINQ.
var isTargetable = false; var isTargetable = false;
foreach (var targetable in actor.Targetables) foreach (var targetable in Actor.Targetables)
{ {
if (!targetable.IsTraitEnabled()) if (!targetable.IsTraitEnabled())
continue; continue;
@@ -162,9 +159,9 @@ namespace OpenRA.Traits
switch (Type) switch (Type)
{ {
case TargetType.Actor: case TargetType.Actor:
return actor.CenterPosition; return Actor.CenterPosition;
case TargetType.FrozenActor: case TargetType.FrozenActor:
return frozen.CenterPosition; return FrozenActor.CenterPosition;
case TargetType.Terrain: case TargetType.Terrain:
return terrainCenterPosition; return terrainCenterPosition;
default: default:
@@ -183,10 +180,10 @@ namespace OpenRA.Traits
switch (Type) switch (Type)
{ {
case TargetType.Actor: case TargetType.Actor:
return actor.GetTargetablePositions(); return Actor.GetTargetablePositions();
case TargetType.FrozenActor: case TargetType.FrozenActor:
// TargetablePositions may be null if it is Invalid // TargetablePositions may be null if it is Invalid
return frozen.TargetablePositions ?? NoPositions; return FrozenActor.TargetablePositions ?? NoPositions;
case TargetType.Terrain: case TargetType.Terrain:
return terrainPositions; return terrainPositions;
default: default:
@@ -210,10 +207,10 @@ namespace OpenRA.Traits
switch (Type) switch (Type)
{ {
case TargetType.Actor: case TargetType.Actor:
return actor.ToString(); return Actor.ToString();
case TargetType.FrozenActor: case TargetType.FrozenActor:
return frozen.ToString(); return FrozenActor.ToString();
case TargetType.Terrain: case TargetType.Terrain:
return terrainCenterPosition.ToString(); return terrainCenterPosition.ToString();
@@ -291,11 +288,7 @@ namespace OpenRA.Traits
// Expose internal state for serialization by the orders code *only* // Expose internal state for serialization by the orders code *only*
internal static Target FromSerializedActor(Actor a, int generation) { return a != null ? new Target(a, generation) : Invalid; } internal static Target FromSerializedActor(Actor a, int generation) { return a != null ? new Target(a, generation) : Invalid; }
internal TargetType SerializableType => type; internal (TargetType Type, Actor Actor, int Generation, CPos? Cell, SubCell? SubCell, WPos Pos) SerializableState =>
internal Actor SerializableActor => actor; (type, Actor, generation, cell, subCell, terrainCenterPosition);
internal int SerializableGeneration => generation;
internal CPos? SerializableCell => cell;
internal SubCell? SerializableSubCell => subCell;
internal WPos SerializablePos => terrainCenterPosition;
} }
} }

View File

@@ -30,9 +30,6 @@ namespace OpenRA.Mods.Cnc.Graphics
new int[] { -8, 8, -4, 4, 3 }, new int[] { -8, 8, -4, 4, 3 },
new int[] { 8, -8, 4, -4, 3 } new int[] { 8, -8, 4, -4, 3 }
}; };
readonly WPos pos;
readonly int zOffset;
readonly WVec length; readonly WVec length;
readonly string image; readonly string image;
readonly string palette; readonly string palette;
@@ -46,8 +43,8 @@ namespace OpenRA.Mods.Cnc.Graphics
public TeslaZapRenderable(WPos pos, int zOffset, in WVec length, string image, string brightSequence, int brightZaps, string dimSequence, int dimZaps, string palette) public TeslaZapRenderable(WPos pos, int zOffset, in WVec length, string image, string brightSequence, int brightZaps, string dimSequence, int dimZaps, string palette)
{ {
this.pos = pos; Pos = pos;
this.zOffset = zOffset; ZOffset = zOffset;
this.length = length; this.length = length;
this.image = image; this.image = image;
this.palette = palette; this.palette = palette;
@@ -61,28 +58,28 @@ namespace OpenRA.Mods.Cnc.Graphics
cache = Array.Empty<IFinalizedRenderable>(); cache = Array.Empty<IFinalizedRenderable>();
} }
public WPos Pos => pos; public WPos Pos { get; }
public PaletteReference Palette => null; public PaletteReference Palette => null;
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => true; public bool IsDecoration => true;
public IPalettedRenderable WithPalette(PaletteReference newPalette) public IPalettedRenderable WithPalette(PaletteReference newPalette)
{ {
return new TeslaZapRenderable(pos, zOffset, length, image, brightSequence, brightZaps, dimSequence, dimZaps, palette); return new TeslaZapRenderable(Pos, ZOffset, length, image, brightSequence, brightZaps, dimSequence, dimZaps, palette);
} }
public IRenderable WithZOffset(int newOffset) { return new TeslaZapRenderable(pos, zOffset, length, image, brightSequence, brightZaps, dimSequence, dimZaps, palette); } public IRenderable WithZOffset(int newOffset) { return new TeslaZapRenderable(Pos, ZOffset, length, image, brightSequence, brightZaps, dimSequence, dimZaps, palette); }
public IRenderable OffsetBy(in WVec vec) { return new TeslaZapRenderable(pos + vec, zOffset, length, image, brightSequence, brightZaps, dimSequence, dimZaps, palette); } public IRenderable OffsetBy(in WVec vec) { return new TeslaZapRenderable(Pos + vec, ZOffset, length, image, brightSequence, brightZaps, dimSequence, dimZaps, palette); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void RenderDebugGeometry(WorldRenderer wr) { } public void RenderDebugGeometry(WorldRenderer wr) { }
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
if (wr.World.FogObscures(pos) && wr.World.FogObscures(pos + length)) if (wr.World.FogObscures(Pos) && wr.World.FogObscures(Pos + length))
return; return;
if (!cache.Any() || length != cachedLength || pos != cachedPos) if (!cache.Any() || length != cachedLength || Pos != cachedPos)
cache = GenerateRenderables(wr); cache = GenerateRenderables(wr);
foreach (var renderable in cache) foreach (var renderable in cache)
@@ -96,8 +93,8 @@ namespace OpenRA.Mods.Cnc.Graphics
var bright = wr.World.Map.Sequences.GetSequence(image, brightSequence); var bright = wr.World.Map.Sequences.GetSequence(image, brightSequence);
var dim = wr.World.Map.Sequences.GetSequence(image, dimSequence); var dim = wr.World.Map.Sequences.GetSequence(image, dimSequence);
var source = wr.ScreenPosition(pos); var source = wr.ScreenPosition(Pos);
var target = wr.ScreenPosition(pos + length); var target = wr.ScreenPosition(Pos + length);
for (var n = 0; n < dimZaps; n++) for (var n = 0; n < dimZaps; n++)
foreach (var z in DrawZapWandering(wr, source, target, dim, palette)) foreach (var z in DrawZapWandering(wr, source, target, dim, palette))

View File

@@ -64,16 +64,14 @@ namespace OpenRA.Mods.Cnc.Traits
IEnumerable<int> speedModifiers; IEnumerable<int> speedModifiers;
INotifyCenterPositionChanged[] notifyCenterPositionChanged; INotifyCenterPositionChanged[] notifyCenterPositionChanged;
WRot orientation;
[Sync] [Sync]
public WAngle Facing public WAngle Facing
{ {
get => orientation.Yaw; get => Orientation.Yaw;
set => orientation = orientation.WithYaw(value); set => Orientation = Orientation.WithYaw(value);
} }
public WRot Orientation => orientation; public WRot Orientation { get; private set; }
[Sync] [Sync]
public WPos CenterPosition { get; private set; } public WPos CenterPosition { get; private set; }

View File

@@ -79,13 +79,12 @@ namespace OpenRA.Mods.Common.AudioLoaders
public class StreamAbstraction : TagLib.File.IFileAbstraction public class StreamAbstraction : TagLib.File.IFileAbstraction
{ {
readonly Stream s;
public StreamAbstraction(Stream s) public StreamAbstraction(Stream s)
{ {
this.s = s; ReadStream = s;
} }
public Stream ReadStream => s; public Stream ReadStream { get; }
public Stream WriteStream => throw new NotImplementedException(); public Stream WriteStream => throw new NotImplementedException();

View File

@@ -17,8 +17,6 @@ namespace OpenRA.Mods.Common.Graphics
public enum BeamRenderableShape { Cylindrical, Flat } public enum BeamRenderableShape { Cylindrical, Flat }
public class BeamRenderable : IRenderable, IFinalizedRenderable public class BeamRenderable : IRenderable, IFinalizedRenderable
{ {
readonly WPos pos;
readonly int zOffset;
readonly WVec length; readonly WVec length;
readonly BeamRenderableShape shape; readonly BeamRenderableShape shape;
readonly WDist width; readonly WDist width;
@@ -26,20 +24,20 @@ namespace OpenRA.Mods.Common.Graphics
public BeamRenderable(WPos pos, int zOffset, in WVec length, BeamRenderableShape shape, WDist width, Color color) public BeamRenderable(WPos pos, int zOffset, in WVec length, BeamRenderableShape shape, WDist width, Color color)
{ {
this.pos = pos; Pos = pos;
this.zOffset = zOffset; ZOffset = zOffset;
this.length = length; this.length = length;
this.shape = shape; this.shape = shape;
this.width = width; this.width = width;
this.color = color; this.color = color;
} }
public WPos Pos => pos; public WPos Pos { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return new BeamRenderable(pos, zOffset, length, shape, width, color); } public IRenderable WithZOffset(int newOffset) { return new BeamRenderable(Pos, ZOffset, length, shape, width, color); }
public IRenderable OffsetBy(in WVec vec) { return new BeamRenderable(pos + vec, zOffset, length, shape, width, color); } public IRenderable OffsetBy(in WVec vec) { return new BeamRenderable(Pos + vec, ZOffset, length, shape, width, color); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
@@ -53,16 +51,16 @@ namespace OpenRA.Mods.Common.Graphics
{ {
var delta = length * width.Length / (2 * vecLength); var delta = length * width.Length / (2 * vecLength);
var corner = new WVec(-delta.Y, delta.X, delta.Z); var corner = new WVec(-delta.Y, delta.X, delta.Z);
var a = wr.Screen3DPosition(pos - corner); var a = wr.Screen3DPosition(Pos - corner);
var b = wr.Screen3DPosition(pos + corner); var b = wr.Screen3DPosition(Pos + corner);
var c = wr.Screen3DPosition(pos + corner + length); var c = wr.Screen3DPosition(Pos + corner + length);
var d = wr.Screen3DPosition(pos - corner + length); var d = wr.Screen3DPosition(Pos - corner + length);
Game.Renderer.WorldRgbaColorRenderer.FillRect(a, b, c, d, color); Game.Renderer.WorldRgbaColorRenderer.FillRect(a, b, c, d, color);
} }
else else
{ {
var start = wr.Screen3DPosition(pos); var start = wr.Screen3DPosition(Pos);
var end = wr.Screen3DPosition(pos + length); var end = wr.Screen3DPosition(Pos + length);
var screenWidth = wr.ScreenVector(new WVec(width, WDist.Zero, WDist.Zero))[0]; var screenWidth = wr.ScreenVector(new WVec(width, WDist.Zero, WDist.Zero))[0];
Game.Renderer.WorldRgbaColorRenderer.DrawLine(start, end, screenWidth, color); Game.Renderer.WorldRgbaColorRenderer.DrawLine(start, end, screenWidth, color);
} }

View File

@@ -18,8 +18,6 @@ namespace OpenRA.Mods.Common.Graphics
{ {
const int CircleSegments = 32; const int CircleSegments = 32;
static readonly WVec[] FacingOffsets = Exts.MakeArray(CircleSegments, i => new WVec(1024, 0, 0).Rotate(WRot.FromFacing(i * 256 / CircleSegments))); static readonly WVec[] FacingOffsets = Exts.MakeArray(CircleSegments, i => new WVec(1024, 0, 0).Rotate(WRot.FromFacing(i * 256 / CircleSegments)));
readonly WPos centerPosition;
readonly WDist radius; readonly WDist radius;
readonly int width; readonly int width;
readonly Color color; readonly Color color;
@@ -27,19 +25,19 @@ namespace OpenRA.Mods.Common.Graphics
public CircleAnnotationRenderable(WPos centerPosition, WDist radius, int width, Color color, bool filled = false) public CircleAnnotationRenderable(WPos centerPosition, WDist radius, int width, Color color, bool filled = false)
{ {
this.centerPosition = centerPosition; Pos = centerPosition;
this.radius = radius; this.radius = radius;
this.width = width; this.width = width;
this.color = color; this.color = color;
this.filled = filled; this.filled = filled;
} }
public WPos Pos => centerPosition; public WPos Pos { get; }
public int ZOffset => 0; public int ZOffset => 0;
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return new CircleAnnotationRenderable(centerPosition, radius, width, color, filled); } public IRenderable WithZOffset(int newOffset) { return new CircleAnnotationRenderable(Pos, radius, width, color, filled); }
public IRenderable OffsetBy(in WVec vec) { return new CircleAnnotationRenderable(centerPosition + vec, radius, width, color, filled); } public IRenderable OffsetBy(in WVec vec) { return new CircleAnnotationRenderable(Pos + vec, radius, width, color, filled); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
@@ -49,18 +47,18 @@ namespace OpenRA.Mods.Common.Graphics
if (filled) if (filled)
{ {
var offset = new WVec(radius.Length, radius.Length, 0); var offset = new WVec(radius.Length, radius.Length, 0);
var tl = wr.Viewport.WorldToViewPx(wr.ScreenPosition(centerPosition - offset)); var tl = wr.Viewport.WorldToViewPx(wr.ScreenPosition(Pos - offset));
var br = wr.Viewport.WorldToViewPx(wr.ScreenPosition(centerPosition + offset)); var br = wr.Viewport.WorldToViewPx(wr.ScreenPosition(Pos + offset));
cr.FillEllipse(tl, br, color); cr.FillEllipse(tl, br, color);
} }
else else
{ {
var r = radius.Length; var r = radius.Length;
var a = wr.Viewport.WorldToViewPx(wr.ScreenPosition(centerPosition + r * FacingOffsets[CircleSegments - 1] / 1024)); var a = wr.Viewport.WorldToViewPx(wr.ScreenPosition(Pos + r * FacingOffsets[CircleSegments - 1] / 1024));
for (var i = 0; i < CircleSegments; i++) for (var i = 0; i < CircleSegments; i++)
{ {
var b = wr.Viewport.WorldToViewPx(wr.ScreenPosition(centerPosition + r * FacingOffsets[i] / 1024)); var b = wr.Viewport.WorldToViewPx(wr.ScreenPosition(Pos + r * FacingOffsets[i] / 1024));
cr.DrawLine(a, b, width, color); cr.DrawLine(a, b, width, color);
a = b; a = b;
} }

View File

@@ -24,7 +24,6 @@ namespace OpenRA.Mods.Common.Graphics
readonly World world; readonly World world;
readonly Color startcolor; readonly Color startcolor;
readonly Color endcolor; readonly Color endcolor;
readonly int zOffset;
// Store trail positions in a circular buffer // Store trail positions in a circular buffer
readonly WPos[] trail; readonly WPos[] trail;
@@ -46,11 +45,11 @@ namespace OpenRA.Mods.Common.Graphics
this.skip = skip; this.skip = skip;
this.startcolor = startcolor; this.startcolor = startcolor;
this.endcolor = endcolor; this.endcolor = endcolor;
this.zOffset = zOffset; ZOffset = zOffset;
} }
public WPos Pos => trail[Index(next - 1)]; public WPos Pos => trail[Index(next - 1)];
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return new ContrailRenderable(world, (WPos[])trail.Clone(), width, next, length, skip, startcolor, endcolor, newOffset); } public IRenderable WithZOffset(int newOffset) { return new ContrailRenderable(world, (WPos[])trail.Clone(), width, next, length, skip, startcolor, endcolor, newOffset); }
@@ -58,7 +57,7 @@ namespace OpenRA.Mods.Common.Graphics
{ {
// Lambdas can't use 'in' variables, so capture a copy for later // Lambdas can't use 'in' variables, so capture a copy for later
var offset = vec; var offset = vec;
return new ContrailRenderable(world, trail.Select(pos => pos + offset).ToArray(), width, next, length, skip, startcolor, endcolor, zOffset); return new ContrailRenderable(world, trail.Select(pos => pos + offset).ToArray(), width, next, length, skip, startcolor, endcolor, ZOffset);
} }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }

View File

@@ -16,9 +16,7 @@ namespace OpenRA.Mods.Common.Graphics
{ {
public class DetectionCircleAnnotationRenderable : IRenderable, IFinalizedRenderable public class DetectionCircleAnnotationRenderable : IRenderable, IFinalizedRenderable
{ {
readonly WPos centerPosition;
readonly WDist radius; readonly WDist radius;
readonly int zOffset;
readonly int trailCount; readonly int trailCount;
readonly WAngle trailSeparation; readonly WAngle trailSeparation;
readonly WAngle trailAngle; readonly WAngle trailAngle;
@@ -30,9 +28,9 @@ namespace OpenRA.Mods.Common.Graphics
public DetectionCircleAnnotationRenderable(WPos centerPosition, WDist radius, int zOffset, public DetectionCircleAnnotationRenderable(WPos centerPosition, WDist radius, int zOffset,
int lineTrails, WAngle trailSeparation, WAngle trailAngle, Color color, float width, Color borderColor, float borderWidth) int lineTrails, WAngle trailSeparation, WAngle trailAngle, Color color, float width, Color borderColor, float borderWidth)
{ {
this.centerPosition = centerPosition; Pos = centerPosition;
this.radius = radius; this.radius = radius;
this.zOffset = zOffset; ZOffset = zOffset;
trailCount = lineTrails; trailCount = lineTrails;
this.trailSeparation = trailSeparation; this.trailSeparation = trailSeparation;
this.trailAngle = trailAngle; this.trailAngle = trailAngle;
@@ -42,19 +40,19 @@ namespace OpenRA.Mods.Common.Graphics
this.borderWidth = borderWidth; this.borderWidth = borderWidth;
} }
public WPos Pos => centerPosition; public WPos Pos { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) public IRenderable WithZOffset(int newOffset)
{ {
return new DetectionCircleAnnotationRenderable(centerPosition, radius, newOffset, return new DetectionCircleAnnotationRenderable(Pos, radius, newOffset,
trailCount, trailSeparation, trailAngle, color, width, borderColor, borderWidth); trailCount, trailSeparation, trailAngle, color, width, borderColor, borderWidth);
} }
public IRenderable OffsetBy(in WVec vec) public IRenderable OffsetBy(in WVec vec)
{ {
return new DetectionCircleAnnotationRenderable(centerPosition + vec, radius, zOffset, return new DetectionCircleAnnotationRenderable(Pos + vec, radius, ZOffset,
trailCount, trailSeparation, trailAngle, color, width, borderColor, borderWidth); trailCount, trailSeparation, trailAngle, color, width, borderColor, borderWidth);
} }
@@ -64,19 +62,19 @@ namespace OpenRA.Mods.Common.Graphics
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
var cr = Game.Renderer.RgbaColorRenderer; var cr = Game.Renderer.RgbaColorRenderer;
var center = wr.Viewport.WorldToViewPx(wr.Screen3DPosition(centerPosition)); var center = wr.Viewport.WorldToViewPx(wr.Screen3DPosition(Pos));
for (var i = 0; i < trailCount; i++) for (var i = 0; i < trailCount; i++)
{ {
var angle = trailAngle - new WAngle(i * (trailSeparation.Angle <= 512 ? 1 : -1)); var angle = trailAngle - new WAngle(i * (trailSeparation.Angle <= 512 ? 1 : -1));
var length = radius.Length * new WVec(angle.Cos(), angle.Sin(), 0) / 1024; var length = radius.Length * new WVec(angle.Cos(), angle.Sin(), 0) / 1024;
var end = wr.Viewport.WorldToViewPx(wr.Screen3DPosition(centerPosition + length)); var end = wr.Viewport.WorldToViewPx(wr.Screen3DPosition(Pos + length));
var alpha = color.A - i * color.A / trailCount; var alpha = color.A - i * color.A / trailCount;
cr.DrawLine(center, end, borderWidth, Color.FromArgb(alpha, borderColor)); cr.DrawLine(center, end, borderWidth, Color.FromArgb(alpha, borderColor));
cr.DrawLine(center, end, width, Color.FromArgb(alpha, color)); cr.DrawLine(center, end, width, Color.FromArgb(alpha, color));
} }
RangeCircleAnnotationRenderable.DrawRangeCircle(wr, centerPosition, radius, width, color, borderWidth, borderColor); RangeCircleAnnotationRenderable.DrawRangeCircle(wr, Pos, radius, width, color, borderWidth, borderColor);
} }
public void RenderDebugGeometry(WorldRenderer wr) { } public void RenderDebugGeometry(WorldRenderer wr) { }

View File

@@ -25,36 +25,32 @@ namespace OpenRA.Mods.Common.Graphics
static readonly Color DarkEmptyColor = Color.FromArgb(160, 15, 15, 15); static readonly Color DarkEmptyColor = Color.FromArgb(160, 15, 15, 15);
static readonly Color DarkenColor = Color.FromArgb(24, 0, 0, 0); static readonly Color DarkenColor = Color.FromArgb(24, 0, 0, 0);
static readonly Color LightenColor = Color.FromArgb(24, 255, 255, 255); static readonly Color LightenColor = Color.FromArgb(24, 255, 255, 255);
readonly WPos pos;
readonly Actor actor; readonly Actor actor;
readonly bool displayHealth;
readonly bool displayExtra;
readonly Polygon bounds; readonly Polygon bounds;
public IsometricSelectionBarsAnnotationRenderable(Actor actor, Polygon bounds, bool displayHealth, bool displayExtra) public IsometricSelectionBarsAnnotationRenderable(Actor actor, Polygon bounds, bool displayHealth, bool displayExtra)
: this(actor.CenterPosition, actor, bounds) : this(actor.CenterPosition, actor, bounds)
{ {
this.displayHealth = displayHealth; DisplayHealth = displayHealth;
this.displayExtra = displayExtra; DisplayExtra = displayExtra;
} }
public IsometricSelectionBarsAnnotationRenderable(WPos pos, Actor actor, Polygon bounds) public IsometricSelectionBarsAnnotationRenderable(WPos pos, Actor actor, Polygon bounds)
{ {
this.pos = pos; Pos = pos;
this.actor = actor; this.actor = actor;
this.bounds = bounds; this.bounds = bounds;
} }
public WPos Pos => pos; public WPos Pos { get; }
public bool DisplayHealth => displayHealth; public bool DisplayHealth { get; }
public bool DisplayExtra => displayExtra; public bool DisplayExtra { get; }
public int ZOffset => 0; public int ZOffset => 0;
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return this; } public IRenderable WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(in WVec vec) { return new IsometricSelectionBarsAnnotationRenderable(pos + vec, actor, bounds); } public IRenderable OffsetBy(in WVec vec) { return new IsometricSelectionBarsAnnotationRenderable(Pos + vec, actor, bounds); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
void DrawExtraBars(WorldRenderer wr) void DrawExtraBars(WorldRenderer wr)

View File

@@ -29,32 +29,30 @@ namespace OpenRA.Mods.Common.Graphics
-TROffset, TOffset, TLOffset, -TROffset, TOffset, TLOffset,
TLOffset, -TOffset, -TROffset TLOffset, -TOffset, -TROffset
}; };
readonly WPos pos;
readonly Polygon bounds; readonly Polygon bounds;
readonly Color color; readonly Color color;
public IsometricSelectionBoxAnnotationRenderable(Actor actor, in Polygon bounds, Color color) public IsometricSelectionBoxAnnotationRenderable(Actor actor, in Polygon bounds, Color color)
{ {
pos = actor.CenterPosition; Pos = actor.CenterPosition;
this.bounds = bounds; this.bounds = bounds;
this.color = color; this.color = color;
} }
public IsometricSelectionBoxAnnotationRenderable(WPos pos, in Polygon bounds, Color color) public IsometricSelectionBoxAnnotationRenderable(WPos pos, in Polygon bounds, Color color)
{ {
this.pos = pos; Pos = pos;
this.bounds = bounds; this.bounds = bounds;
this.color = color; this.color = color;
} }
public WPos Pos => pos; public WPos Pos { get; }
public int ZOffset => 0; public int ZOffset => 0;
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return this; } public IRenderable WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(in WVec vec) { return new IsometricSelectionBoxAnnotationRenderable(pos + vec, bounds, color); } public IRenderable OffsetBy(in WVec vec) { return new IsometricSelectionBoxAnnotationRenderable(Pos + vec, bounds, color); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }

View File

@@ -16,7 +16,6 @@ namespace OpenRA.Mods.Common.Graphics
{ {
public class LineAnnotationRenderable : IRenderable, IFinalizedRenderable public class LineAnnotationRenderable : IRenderable, IFinalizedRenderable
{ {
readonly WPos start;
readonly WPos end; readonly WPos end;
readonly float width; readonly float width;
readonly Color startColor; readonly Color startColor;
@@ -24,7 +23,7 @@ namespace OpenRA.Mods.Common.Graphics
public LineAnnotationRenderable(WPos start, WPos end, float width, Color color) public LineAnnotationRenderable(WPos start, WPos end, float width, Color color)
{ {
this.start = start; Pos = start;
this.end = end; this.end = end;
this.width = width; this.width = width;
startColor = endColor = color; startColor = endColor = color;
@@ -32,26 +31,26 @@ namespace OpenRA.Mods.Common.Graphics
public LineAnnotationRenderable(WPos start, WPos end, float width, Color startColor, Color endColor) public LineAnnotationRenderable(WPos start, WPos end, float width, Color startColor, Color endColor)
{ {
this.start = start; Pos = start;
this.end = end; this.end = end;
this.width = width; this.width = width;
this.startColor = startColor; this.startColor = startColor;
this.endColor = endColor; this.endColor = endColor;
} }
public WPos Pos => start; public WPos Pos { get; }
public int ZOffset => 0; public int ZOffset => 0;
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return new LineAnnotationRenderable(start, end, width, startColor, endColor); } public IRenderable WithZOffset(int newOffset) { return new LineAnnotationRenderable(Pos, end, width, startColor, endColor); }
public IRenderable OffsetBy(in WVec vec) { return new LineAnnotationRenderable(start + vec, end + vec, width, startColor, endColor); } public IRenderable OffsetBy(in WVec vec) { return new LineAnnotationRenderable(Pos + vec, end + vec, width, startColor, endColor); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
Game.Renderer.RgbaColorRenderer.DrawLine( Game.Renderer.RgbaColorRenderer.DrawLine(
wr.Viewport.WorldToViewPx(wr.ScreenPosition(start)), wr.Viewport.WorldToViewPx(wr.ScreenPosition(Pos)),
wr.Viewport.WorldToViewPx(wr.Screen3DPosition(end)), wr.Viewport.WorldToViewPx(wr.Screen3DPosition(end)),
width, startColor, endColor); width, startColor, endColor);
} }

View File

@@ -20,19 +20,13 @@ namespace OpenRA.Mods.Common.Graphics
public class ModelRenderable : IPalettedRenderable, IModifyableRenderable public class ModelRenderable : IPalettedRenderable, IModifyableRenderable
{ {
readonly IEnumerable<ModelAnimation> models; readonly IEnumerable<ModelAnimation> models;
readonly WPos pos;
readonly int zOffset;
readonly WRot camera; readonly WRot camera;
readonly WRot lightSource; readonly WRot lightSource;
readonly float[] lightAmbientColor; readonly float[] lightAmbientColor;
readonly float[] lightDiffuseColor; readonly float[] lightDiffuseColor;
readonly PaletteReference palette;
readonly PaletteReference normalsPalette; readonly PaletteReference normalsPalette;
readonly PaletteReference shadowPalette; readonly PaletteReference shadowPalette;
readonly float scale; readonly float scale;
readonly float alpha;
readonly float3 tint;
readonly TintModifiers tintModifiers;
public ModelRenderable( public ModelRenderable(
IEnumerable<ModelAnimation> models, WPos pos, int zOffset, in WRot camera, float scale, IEnumerable<ModelAnimation> models, WPos pos, int zOffset, in WRot camera, float scale,
@@ -50,52 +44,52 @@ namespace OpenRA.Mods.Common.Graphics
float alpha, in float3 tint, TintModifiers tintModifiers) float alpha, in float3 tint, TintModifiers tintModifiers)
{ {
this.models = models; this.models = models;
this.pos = pos; Pos = pos;
this.zOffset = zOffset; ZOffset = zOffset;
this.scale = scale; this.scale = scale;
this.camera = camera; this.camera = camera;
this.lightSource = lightSource; this.lightSource = lightSource;
this.lightAmbientColor = lightAmbientColor; this.lightAmbientColor = lightAmbientColor;
this.lightDiffuseColor = lightDiffuseColor; this.lightDiffuseColor = lightDiffuseColor;
palette = color; Palette = color;
normalsPalette = normals; normalsPalette = normals;
shadowPalette = shadow; shadowPalette = shadow;
this.alpha = alpha; Alpha = alpha;
this.tint = tint; Tint = tint;
this.tintModifiers = tintModifiers; TintModifiers = tintModifiers;
} }
public WPos Pos => pos; public WPos Pos { get; }
public PaletteReference Palette => palette; public PaletteReference Palette { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => false; public bool IsDecoration => false;
public float Alpha => alpha; public float Alpha { get; }
public float3 Tint => tint; public float3 Tint { get; }
public TintModifiers TintModifiers => tintModifiers; public TintModifiers TintModifiers { get; }
public IPalettedRenderable WithPalette(PaletteReference newPalette) public IPalettedRenderable WithPalette(PaletteReference newPalette)
{ {
return new ModelRenderable( return new ModelRenderable(
models, pos, zOffset, camera, scale, models, Pos, ZOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor, lightSource, lightAmbientColor, lightDiffuseColor,
newPalette, normalsPalette, shadowPalette, alpha, tint, tintModifiers); newPalette, normalsPalette, shadowPalette, Alpha, Tint, TintModifiers);
} }
public IRenderable WithZOffset(int newOffset) public IRenderable WithZOffset(int newOffset)
{ {
return new ModelRenderable( return new ModelRenderable(
models, pos, newOffset, camera, scale, models, Pos, newOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor, lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette, alpha, tint, tintModifiers); Palette, normalsPalette, shadowPalette, Alpha, Tint, TintModifiers);
} }
public IRenderable OffsetBy(in WVec vec) public IRenderable OffsetBy(in WVec vec)
{ {
return new ModelRenderable( return new ModelRenderable(
models, pos + vec, zOffset, camera, scale, models, Pos + vec, ZOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor, lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette, alpha, tint, tintModifiers); Palette, normalsPalette, shadowPalette, Alpha, Tint, TintModifiers);
} }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
@@ -103,17 +97,17 @@ namespace OpenRA.Mods.Common.Graphics
public IModifyableRenderable WithAlpha(float newAlpha) public IModifyableRenderable WithAlpha(float newAlpha)
{ {
return new ModelRenderable( return new ModelRenderable(
models, pos, zOffset, camera, scale, models, Pos, ZOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor, lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette, newAlpha, tint, tintModifiers); Palette, normalsPalette, shadowPalette, newAlpha, Tint, TintModifiers);
} }
public IModifyableRenderable WithTint(in float3 newTint, TintModifiers newTintModifiers) public IModifyableRenderable WithTint(in float3 newTint, TintModifiers newTintModifiers)
{ {
return new ModelRenderable( return new ModelRenderable(
models, pos, zOffset, camera, scale, models, Pos, ZOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor, lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette, alpha, newTint, newTintModifiers); Palette, normalsPalette, shadowPalette, Alpha, newTint, newTintModifiers);
} }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) public IFinalizedRenderable PrepareRender(WorldRenderer wr)
@@ -132,21 +126,21 @@ namespace OpenRA.Mods.Common.Graphics
var draw = model.models.Where(v => v.IsVisible); var draw = model.models.Where(v => v.IsVisible);
var map = wr.World.Map; var map = wr.World.Map;
var groundOrientation = map.TerrainOrientation(map.CellContaining(model.pos)); var groundOrientation = map.TerrainOrientation(map.CellContaining(model.Pos));
renderProxy = Game.Renderer.WorldModelRenderer.RenderAsync( renderProxy = Game.Renderer.WorldModelRenderer.RenderAsync(
wr, draw, model.camera, model.scale, groundOrientation, model.lightSource, wr, draw, model.camera, model.scale, groundOrientation, model.lightSource,
model.lightAmbientColor, model.lightDiffuseColor, model.lightAmbientColor, model.lightDiffuseColor,
model.palette, model.normalsPalette, model.shadowPalette); model.Palette, model.normalsPalette, model.shadowPalette);
} }
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
var map = wr.World.Map; var map = wr.World.Map;
var groundPos = model.pos - new WVec(0, 0, map.DistanceAboveTerrain(model.pos).Length); var groundPos = model.Pos - new WVec(0, 0, map.DistanceAboveTerrain(model.Pos).Length);
var tileScale = map.Grid.Type == MapGridType.RectangularIsometric ? 1448f : 1024f; var tileScale = map.Grid.Type == MapGridType.RectangularIsometric ? 1448f : 1024f;
var groundZ = map.Grid.TileSize.Height * (groundPos.Z - model.pos.Z) / tileScale; var groundZ = map.Grid.TileSize.Height * (groundPos.Z - model.Pos.Z) / tileScale;
var pxOrigin = wr.Screen3DPosition(model.pos); var pxOrigin = wr.Screen3DPosition(model.Pos);
// HACK: We don't have enough texture channels to pass the depth data to the shader // HACK: We don't have enough texture channels to pass the depth data to the shader
// so for now just offset everything forward so that the back corner is rendered at pos. // so for now just offset everything forward so that the back corner is rendered at pos.
@@ -154,7 +148,7 @@ namespace OpenRA.Mods.Common.Graphics
// HACK: The previous hack isn't sufficient for the ramp type that is half flat and half // HACK: The previous hack isn't sufficient for the ramp type that is half flat and half
// sloped towards the camera. Offset it by another half cell to avoid clipping. // sloped towards the camera. Offset it by another half cell to avoid clipping.
var cell = map.CellContaining(model.pos); var cell = map.CellContaining(model.Pos);
if (map.Ramp.Contains(cell) && map.Ramp[cell] == 7) if (map.Ramp.Contains(cell) && map.Ramp[cell] == 7)
pxOrigin += new float3(0, 0, 0.5f * map.Grid.TileSize.Height); pxOrigin += new float3(0, 0, 0.5f * map.Grid.TileSize.Height);
@@ -167,13 +161,13 @@ namespace OpenRA.Mods.Common.Graphics
var sd = shadowOrigin + psb[3]; var sd = shadowOrigin + psb[3];
var wrsr = Game.Renderer.WorldRgbaSpriteRenderer; var wrsr = Game.Renderer.WorldRgbaSpriteRenderer;
var t = model.tint; var t = model.Tint;
if (wr.TerrainLighting != null && (model.tintModifiers & TintModifiers.IgnoreWorldTint) == 0) if (wr.TerrainLighting != null && (model.TintModifiers & TintModifiers.IgnoreWorldTint) == 0)
t *= wr.TerrainLighting.TintAt(model.pos); t *= wr.TerrainLighting.TintAt(model.Pos);
// Shader interprets negative alpha as a flag to use the tint colour directly instead of multiplying the sprite colour // Shader interprets negative alpha as a flag to use the tint colour directly instead of multiplying the sprite colour
var a = model.alpha; var a = model.Alpha;
if ((model.tintModifiers & TintModifiers.ReplaceColor) != 0) if ((model.TintModifiers & TintModifiers.ReplaceColor) != 0)
a *= -1; a *= -1;
wrsr.DrawSprite(renderProxy.ShadowSprite, sa, sb, sc, sd, t, a); wrsr.DrawSprite(renderProxy.ShadowSprite, sa, sb, sc, sd, t, a);
@@ -182,9 +176,9 @@ namespace OpenRA.Mods.Common.Graphics
public void RenderDebugGeometry(WorldRenderer wr) public void RenderDebugGeometry(WorldRenderer wr)
{ {
var groundPos = model.pos - new WVec(0, 0, wr.World.Map.DistanceAboveTerrain(model.pos).Length); var groundPos = model.Pos - new WVec(0, 0, wr.World.Map.DistanceAboveTerrain(model.Pos).Length);
var groundZ = wr.World.Map.Grid.TileSize.Height * (groundPos.Z - model.pos.Z) / 1024f; var groundZ = wr.World.Map.Grid.TileSize.Height * (groundPos.Z - model.Pos.Z) / 1024f;
var pxOrigin = wr.Screen3DPosition(model.pos); var pxOrigin = wr.Screen3DPosition(model.Pos);
var shadowOrigin = pxOrigin - groundZ * new float2(renderProxy.ShadowDirection, 1); var shadowOrigin = pxOrigin - groundZ * new float2(renderProxy.ShadowDirection, 1);
// Draw sprite rect // Draw sprite rect
@@ -256,7 +250,7 @@ namespace OpenRA.Mods.Common.Graphics
(Rectangle Bounds, float2 Z) Screen3DBounds(WorldRenderer wr) (Rectangle Bounds, float2 Z) Screen3DBounds(WorldRenderer wr)
{ {
var pxOrigin = wr.ScreenPosition(model.pos); var pxOrigin = wr.ScreenPosition(model.Pos);
var draw = model.models.Where(v => v.IsVisible); var draw = model.models.Where(v => v.IsVisible);
var scaleTransform = OpenRA.Graphics.Util.ScaleMatrix(model.scale, model.scale, model.scale); var scaleTransform = OpenRA.Graphics.Util.ScaleMatrix(model.scale, model.scale, model.scale);
var cameraTransform = OpenRA.Graphics.Util.MakeFloatMatrix(model.camera.AsMatrix()); var cameraTransform = OpenRA.Graphics.Util.MakeFloatMatrix(model.camera.AsMatrix());

View File

@@ -18,29 +18,28 @@ namespace OpenRA.Mods.Common.Graphics
public class PolygonAnnotationRenderable : IRenderable, IFinalizedRenderable public class PolygonAnnotationRenderable : IRenderable, IFinalizedRenderable
{ {
readonly WPos[] vertices; readonly WPos[] vertices;
readonly WPos effectivePos;
readonly int width; readonly int width;
readonly Color color; readonly Color color;
public PolygonAnnotationRenderable(WPos[] vertices, WPos effectivePos, int width, Color color) public PolygonAnnotationRenderable(WPos[] vertices, WPos effectivePos, int width, Color color)
{ {
this.vertices = vertices; this.vertices = vertices;
this.effectivePos = effectivePos; Pos = effectivePos;
this.width = width; this.width = width;
this.color = color; this.color = color;
} }
public WPos Pos => effectivePos; public WPos Pos { get; }
public int ZOffset => 0; public int ZOffset => 0;
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return new PolygonAnnotationRenderable(vertices, effectivePos, width, color); } public IRenderable WithZOffset(int newOffset) { return new PolygonAnnotationRenderable(vertices, Pos, width, color); }
public IRenderable OffsetBy(in WVec vec) public IRenderable OffsetBy(in WVec vec)
{ {
// Lambdas can't use 'in' variables, so capture a copy for later // Lambdas can't use 'in' variables, so capture a copy for later
var offset = vec; var offset = vec;
return new PolygonAnnotationRenderable(vertices.Select(v => v + offset).ToArray(), effectivePos + vec, width, color); return new PolygonAnnotationRenderable(vertices.Select(v => v + offset).ToArray(), Pos + vec, width, color);
} }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }

View File

@@ -17,8 +17,6 @@ namespace OpenRA.Mods.Common.Graphics
{ {
public class RailgunHelixRenderable : IRenderable, IFinalizedRenderable public class RailgunHelixRenderable : IRenderable, IFinalizedRenderable
{ {
readonly WPos pos;
readonly int zOffset;
readonly Railgun railgun; readonly Railgun railgun;
readonly RailgunInfo info; readonly RailgunInfo info;
readonly WDist helixRadius; readonly WDist helixRadius;
@@ -29,8 +27,8 @@ namespace OpenRA.Mods.Common.Graphics
public RailgunHelixRenderable(WPos pos, int zOffset, Railgun railgun, RailgunInfo railgunInfo, int ticks) public RailgunHelixRenderable(WPos pos, int zOffset, Railgun railgun, RailgunInfo railgunInfo, int ticks)
{ {
this.pos = pos; Pos = pos;
this.zOffset = zOffset; ZOffset = zOffset;
this.railgun = railgun; this.railgun = railgun;
info = railgunInfo; info = railgunInfo;
this.ticks = ticks; this.ticks = ticks;
@@ -40,12 +38,12 @@ namespace OpenRA.Mods.Common.Graphics
angle = new WAngle(ticks * info.HelixAngleDeltaPerTick.Angle); angle = new WAngle(ticks * info.HelixAngleDeltaPerTick.Angle);
} }
public WPos Pos => pos; public WPos Pos { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return new RailgunHelixRenderable(pos, newOffset, railgun, info, ticks); } public IRenderable WithZOffset(int newOffset) { return new RailgunHelixRenderable(Pos, newOffset, railgun, info, ticks); }
public IRenderable OffsetBy(in WVec vec) { return new RailgunHelixRenderable(pos + vec, zOffset, railgun, info, ticks); } public IRenderable OffsetBy(in WVec vec) { return new RailgunHelixRenderable(Pos + vec, ZOffset, railgun, info, ticks); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
@@ -57,7 +55,7 @@ namespace OpenRA.Mods.Common.Graphics
var screenWidth = wr.ScreenVector(new WVec(info.HelixThickness.Length, 0, 0))[0]; var screenWidth = wr.ScreenVector(new WVec(info.HelixThickness.Length, 0, 0))[0];
// Move forward from self to target to draw helix // Move forward from self to target to draw helix
var centerPos = pos; var centerPos = Pos;
var points = new float3[railgun.CycleCount * info.QuantizationCount]; var points = new float3[railgun.CycleCount * info.QuantizationCount];
for (var i = points.Length - 1; i >= 0; i--) for (var i = points.Length - 1; i >= 0; i--)
{ {

View File

@@ -19,10 +19,7 @@ namespace OpenRA.Mods.Common.Graphics
const int RangeCircleSegments = 32; const int RangeCircleSegments = 32;
static readonly Int32Matrix4x4[] RangeCircleStartRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i).AsMatrix()); static readonly Int32Matrix4x4[] RangeCircleStartRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i).AsMatrix());
static readonly Int32Matrix4x4[] RangeCircleEndRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i + 6).AsMatrix()); static readonly Int32Matrix4x4[] RangeCircleEndRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i + 6).AsMatrix());
readonly WPos centerPosition;
readonly WDist radius; readonly WDist radius;
readonly int zOffset;
readonly Color color; readonly Color color;
readonly float width; readonly float width;
readonly Color borderColor; readonly Color borderColor;
@@ -30,27 +27,27 @@ namespace OpenRA.Mods.Common.Graphics
public RangeCircleAnnotationRenderable(WPos centerPosition, WDist radius, int zOffset, Color color, float width, Color borderColor, float borderWidth) public RangeCircleAnnotationRenderable(WPos centerPosition, WDist radius, int zOffset, Color color, float width, Color borderColor, float borderWidth)
{ {
this.centerPosition = centerPosition; Pos = centerPosition;
this.radius = radius; this.radius = radius;
this.zOffset = zOffset; ZOffset = zOffset;
this.color = color; this.color = color;
this.width = width; this.width = width;
this.borderColor = borderColor; this.borderColor = borderColor;
this.borderWidth = borderWidth; this.borderWidth = borderWidth;
} }
public WPos Pos => centerPosition; public WPos Pos { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return new RangeCircleAnnotationRenderable(centerPosition, radius, newOffset, color, width, borderColor, borderWidth); } public IRenderable WithZOffset(int newOffset) { return new RangeCircleAnnotationRenderable(Pos, radius, newOffset, color, width, borderColor, borderWidth); }
public IRenderable OffsetBy(in WVec vec) { return new RangeCircleAnnotationRenderable(centerPosition + vec, radius, zOffset, color, width, borderColor, borderWidth); } public IRenderable OffsetBy(in WVec vec) { return new RangeCircleAnnotationRenderable(Pos + vec, radius, ZOffset, color, width, borderColor, borderWidth); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
DrawRangeCircle(wr, centerPosition, radius, width, color, borderWidth, borderColor); DrawRangeCircle(wr, Pos, radius, width, color, borderWidth, borderColor);
} }
public static void DrawRangeCircle(WorldRenderer wr, WPos centerPosition, WDist radius, public static void DrawRangeCircle(WorldRenderer wr, WPos centerPosition, WDist radius,

View File

@@ -17,35 +17,32 @@ namespace OpenRA.Mods.Common.Graphics
{ {
public class SelectionBarsAnnotationRenderable : IRenderable, IFinalizedRenderable public class SelectionBarsAnnotationRenderable : IRenderable, IFinalizedRenderable
{ {
readonly WPos pos;
readonly Actor actor; readonly Actor actor;
readonly bool displayHealth;
readonly bool displayExtra;
readonly Rectangle decorationBounds; readonly Rectangle decorationBounds;
public SelectionBarsAnnotationRenderable(Actor actor, Rectangle decorationBounds, bool displayHealth, bool displayExtra) public SelectionBarsAnnotationRenderable(Actor actor, Rectangle decorationBounds, bool displayHealth, bool displayExtra)
: this(actor.CenterPosition, actor, decorationBounds) : this(actor.CenterPosition, actor, decorationBounds)
{ {
this.displayHealth = displayHealth; DisplayHealth = displayHealth;
this.displayExtra = displayExtra; DisplayExtra = displayExtra;
} }
public SelectionBarsAnnotationRenderable(WPos pos, Actor actor, Rectangle decorationBounds) public SelectionBarsAnnotationRenderable(WPos pos, Actor actor, Rectangle decorationBounds)
{ {
this.pos = pos; Pos = pos;
this.actor = actor; this.actor = actor;
this.decorationBounds = decorationBounds; this.decorationBounds = decorationBounds;
} }
public WPos Pos => pos; public WPos Pos { get; }
public bool DisplayHealth => displayHealth; public bool DisplayHealth { get; }
public bool DisplayExtra => displayExtra; public bool DisplayExtra { get; }
public int ZOffset => 0; public int ZOffset => 0;
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return this; } public IRenderable WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(in WVec vec) { return new SelectionBarsAnnotationRenderable(pos + vec, actor, decorationBounds); } public IRenderable OffsetBy(in WVec vec) { return new SelectionBarsAnnotationRenderable(Pos + vec, actor, decorationBounds); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
void DrawExtraBars(float2 start, float2 end) void DrawExtraBars(float2 start, float2 end)

View File

@@ -16,7 +16,6 @@ namespace OpenRA.Mods.Common.Graphics
{ {
public class SelectionBoxAnnotationRenderable : IRenderable, IFinalizedRenderable public class SelectionBoxAnnotationRenderable : IRenderable, IFinalizedRenderable
{ {
readonly WPos pos;
readonly Rectangle decorationBounds; readonly Rectangle decorationBounds;
readonly Color color; readonly Color color;
@@ -25,18 +24,18 @@ namespace OpenRA.Mods.Common.Graphics
public SelectionBoxAnnotationRenderable(WPos pos, Rectangle decorationBounds, Color color) public SelectionBoxAnnotationRenderable(WPos pos, Rectangle decorationBounds, Color color)
{ {
this.pos = pos; Pos = pos;
this.decorationBounds = decorationBounds; this.decorationBounds = decorationBounds;
this.color = color; this.color = color;
} }
public WPos Pos => pos; public WPos Pos { get; }
public int ZOffset => 0; public int ZOffset => 0;
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return this; } public IRenderable WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(in WVec vec) { return new SelectionBoxAnnotationRenderable(pos + vec, decorationBounds, color); } public IRenderable OffsetBy(in WVec vec) { return new SelectionBoxAnnotationRenderable(Pos + vec, decorationBounds, color); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }

View File

@@ -18,8 +18,6 @@ namespace OpenRA.Mods.Common.Graphics
public class TextAnnotationRenderable : IRenderable, IFinalizedRenderable public class TextAnnotationRenderable : IRenderable, IFinalizedRenderable
{ {
readonly SpriteFont font; readonly SpriteFont font;
readonly WPos pos;
readonly int zOffset;
readonly Color color; readonly Color color;
readonly Color bgDark; readonly Color bgDark;
readonly Color bgLight; readonly Color bgLight;
@@ -28,8 +26,8 @@ namespace OpenRA.Mods.Common.Graphics
public TextAnnotationRenderable(SpriteFont font, WPos pos, int zOffset, Color color, Color bgDark, Color bgLight, string text) public TextAnnotationRenderable(SpriteFont font, WPos pos, int zOffset, Color color, Color bgDark, Color bgLight, string text)
{ {
this.font = font; this.font = font;
this.pos = pos; Pos = pos;
this.zOffset = zOffset; ZOffset = zOffset;
this.color = color; this.color = color;
this.bgDark = bgDark; this.bgDark = bgDark;
this.bgLight = bgLight; this.bgLight = bgLight;
@@ -42,25 +40,25 @@ namespace OpenRA.Mods.Common.Graphics
ChromeMetrics.Get<Color>("TextContrastColorLight"), ChromeMetrics.Get<Color>("TextContrastColorLight"),
text) { } text) { }
public WPos Pos => pos; public WPos Pos { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return new TextAnnotationRenderable(font, pos, zOffset, color, text); } public IRenderable WithZOffset(int newOffset) { return new TextAnnotationRenderable(font, Pos, ZOffset, color, text); }
public IRenderable OffsetBy(in WVec vec) { return new TextAnnotationRenderable(font, pos + vec, zOffset, color, text); } public IRenderable OffsetBy(in WVec vec) { return new TextAnnotationRenderable(font, Pos + vec, ZOffset, color, text); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
var screenPos = wr.Viewport.WorldToViewPx(wr.ScreenPosition(pos)) - 0.5f * font.Measure(text).ToFloat2(); var screenPos = wr.Viewport.WorldToViewPx(wr.ScreenPosition(Pos)) - 0.5f * font.Measure(text).ToFloat2();
font.DrawTextWithContrast(text, screenPos, color, bgDark, bgLight, 1); font.DrawTextWithContrast(text, screenPos, color, bgDark, bgLight, 1);
} }
public void RenderDebugGeometry(WorldRenderer wr) public void RenderDebugGeometry(WorldRenderer wr)
{ {
var size = font.Measure(text).ToFloat2(); var size = font.Measure(text).ToFloat2();
var screenPos = wr.Viewport.WorldToViewPx(wr.ScreenPosition(pos)); var screenPos = wr.Viewport.WorldToViewPx(wr.ScreenPosition(Pos));
Game.Renderer.RgbaColorRenderer.DrawRect(screenPos - 0.5f * size, screenPos + 0.5f * size, 1, Color.Red); Game.Renderer.RgbaColorRenderer.DrawRect(screenPos - 0.5f * size, screenPos + 0.5f * size, 1, Color.Red);
} }

View File

@@ -20,14 +20,11 @@ namespace OpenRA.Mods.Common.Graphics
public class UIModelRenderable : IRenderable, IPalettedRenderable public class UIModelRenderable : IRenderable, IPalettedRenderable
{ {
readonly IEnumerable<ModelAnimation> models; readonly IEnumerable<ModelAnimation> models;
readonly WPos effectiveWorldPos;
readonly int2 screenPos; readonly int2 screenPos;
readonly int zOffset;
readonly WRot camera; readonly WRot camera;
readonly WRot lightSource; readonly WRot lightSource;
readonly float[] lightAmbientColor; readonly float[] lightAmbientColor;
readonly float[] lightDiffuseColor; readonly float[] lightDiffuseColor;
readonly PaletteReference palette;
readonly PaletteReference normalsPalette; readonly PaletteReference normalsPalette;
readonly PaletteReference shadowPalette; readonly PaletteReference shadowPalette;
readonly float scale; readonly float scale;
@@ -38,28 +35,28 @@ namespace OpenRA.Mods.Common.Graphics
PaletteReference color, PaletteReference normals, PaletteReference shadow) PaletteReference color, PaletteReference normals, PaletteReference shadow)
{ {
this.models = models; this.models = models;
this.effectiveWorldPos = effectiveWorldPos; Pos = effectiveWorldPos;
this.screenPos = screenPos; this.screenPos = screenPos;
this.zOffset = zOffset; ZOffset = zOffset;
this.scale = scale; this.scale = scale;
this.camera = camera; this.camera = camera;
this.lightSource = lightSource; this.lightSource = lightSource;
this.lightAmbientColor = lightAmbientColor; this.lightAmbientColor = lightAmbientColor;
this.lightDiffuseColor = lightDiffuseColor; this.lightDiffuseColor = lightDiffuseColor;
palette = color; Palette = color;
normalsPalette = normals; normalsPalette = normals;
shadowPalette = shadow; shadowPalette = shadow;
} }
public WPos Pos => effectiveWorldPos; public WPos Pos { get; }
public PaletteReference Palette => palette; public PaletteReference Palette { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => false; public bool IsDecoration => false;
public IPalettedRenderable WithPalette(PaletteReference newPalette) public IPalettedRenderable WithPalette(PaletteReference newPalette)
{ {
return new UIModelRenderable( return new UIModelRenderable(
models, effectiveWorldPos, screenPos, zOffset, camera, scale, models, Pos, screenPos, ZOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor, lightSource, lightAmbientColor, lightDiffuseColor,
newPalette, normalsPalette, shadowPalette); newPalette, normalsPalette, shadowPalette);
} }
@@ -86,7 +83,7 @@ namespace OpenRA.Mods.Common.Graphics
renderProxy = Game.Renderer.WorldModelRenderer.RenderAsync( renderProxy = Game.Renderer.WorldModelRenderer.RenderAsync(
wr, draw, model.camera, model.scale, WRot.None, model.lightSource, wr, draw, model.camera, model.scale, WRot.None, model.lightSource,
model.lightAmbientColor, model.lightDiffuseColor, model.lightAmbientColor, model.lightDiffuseColor,
model.palette, model.normalsPalette, model.shadowPalette); model.Palette, model.normalsPalette, model.shadowPalette);
} }
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)

View File

@@ -18,9 +18,7 @@ namespace OpenRA.Mods.Common.Graphics
public class UITextRenderable : IRenderable, IFinalizedRenderable public class UITextRenderable : IRenderable, IFinalizedRenderable
{ {
readonly SpriteFont font; readonly SpriteFont font;
readonly WPos effectiveWorldPos;
readonly int2 screenPos; readonly int2 screenPos;
readonly int zOffset;
readonly Color color; readonly Color color;
readonly Color bgDark; readonly Color bgDark;
readonly Color bgLight; readonly Color bgLight;
@@ -29,9 +27,9 @@ namespace OpenRA.Mods.Common.Graphics
public UITextRenderable(SpriteFont font, WPos effectiveWorldPos, int2 screenPos, int zOffset, Color color, Color bgDark, Color bgLight, string text) public UITextRenderable(SpriteFont font, WPos effectiveWorldPos, int2 screenPos, int zOffset, Color color, Color bgDark, Color bgLight, string text)
{ {
this.font = font; this.font = font;
this.effectiveWorldPos = effectiveWorldPos; Pos = effectiveWorldPos;
this.screenPos = screenPos; this.screenPos = screenPos;
this.zOffset = zOffset; ZOffset = zOffset;
this.color = color; this.color = color;
this.bgDark = bgDark; this.bgDark = bgDark;
this.bgLight = bgLight; this.bgLight = bgLight;
@@ -44,12 +42,12 @@ namespace OpenRA.Mods.Common.Graphics
ChromeMetrics.Get<Color>("TextContrastColorLight"), ChromeMetrics.Get<Color>("TextContrastColorLight"),
text) { } text) { }
public WPos Pos => effectiveWorldPos; public WPos Pos { get; }
public int ZOffset => zOffset; public int ZOffset { get; }
public bool IsDecoration => true; public bool IsDecoration => true;
public IRenderable WithZOffset(int newOffset) { return new UITextRenderable(font, effectiveWorldPos, screenPos, zOffset, color, text); } public IRenderable WithZOffset(int newOffset) { return new UITextRenderable(font, Pos, screenPos, ZOffset, color, text); }
public IRenderable OffsetBy(in WVec vec) { return new UITextRenderable(font, effectiveWorldPos + vec, screenPos, zOffset, color, text); } public IRenderable OffsetBy(in WVec vec) { return new UITextRenderable(font, Pos + vec, screenPos, ZOffset, color, text); }
public IRenderable AsDecoration() { return this; } public IRenderable AsDecoration() { return this; }
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }

View File

@@ -37,9 +37,10 @@ namespace OpenRA.Mods.Common.Terrain
{ {
readonly Dictionary<ushort, TheaterTemplate> templates = new Dictionary<ushort, TheaterTemplate>(); readonly Dictionary<ushort, TheaterTemplate> templates = new Dictionary<ushort, TheaterTemplate>();
readonly Cache<SheetType, SheetBuilder> sheetBuilders; readonly Cache<SheetType, SheetBuilder> sheetBuilders;
readonly Sprite missingTile;
readonly MersenneTwister random; readonly MersenneTwister random;
public Sprite MissingTile { get; }
public DefaultTileCache(DefaultTerrain terrainInfo, Action<uint, string> onMissingImage = null) public DefaultTileCache(DefaultTerrain terrainInfo, Action<uint, string> onMissingImage = null)
{ {
sheetBuilders = new Cache<SheetType, SheetBuilder>(t => new SheetBuilder(t, terrainInfo.SheetSize)); sheetBuilders = new Cache<SheetType, SheetBuilder>(t => new SheetBuilder(t, terrainInfo.SheetSize));
@@ -154,30 +155,28 @@ namespace OpenRA.Mods.Common.Terrain
missingSheetType = SheetType.BGRA; missingSheetType = SheetType.BGRA;
} }
missingTile = sheetBuilders[missingSheetType].Add(new byte[missingDataLength], missingFrameType, new Size(1, 1)); MissingTile = sheetBuilders[missingSheetType].Add(new byte[missingDataLength], missingFrameType, new Size(1, 1));
foreach (var sb in sheetBuilders.Values) foreach (var sb in sheetBuilders.Values)
sb.Current.ReleaseBuffer(); sb.Current.ReleaseBuffer();
} }
public bool HasTileSprite(TerrainTile r, int? variant = null) public bool HasTileSprite(TerrainTile r, int? variant = null)
{ {
return TileSprite(r, variant) != missingTile; return TileSprite(r, variant) != MissingTile;
} }
public Sprite TileSprite(TerrainTile r, int? variant = null) public Sprite TileSprite(TerrainTile r, int? variant = null)
{ {
if (!templates.TryGetValue(r.Type, out var template)) if (!templates.TryGetValue(r.Type, out var template))
return missingTile; return MissingTile;
if (r.Index >= template.Stride) if (r.Index >= template.Stride)
return missingTile; return MissingTile;
var start = template.Variants > 1 ? variant ?? random.Next(template.Variants) : 0; var start = template.Variants > 1 ? variant ?? random.Next(template.Variants) : 0;
return template.Sprites[start * template.Stride + r.Index]; return template.Sprites[start * template.Stride + r.Index];
} }
public Sprite MissingTile => missingTile;
public void Dispose() public void Dispose()
{ {
foreach (var sb in sheetBuilders.Values) foreach (var sb in sheetBuilders.Values)

View File

@@ -235,28 +235,26 @@ namespace OpenRA.Mods.Common.Traits
INotifyCenterPositionChanged[] notifyCenterPositionChanged; INotifyCenterPositionChanged[] notifyCenterPositionChanged;
IOverrideAircraftLanding overrideAircraftLanding; IOverrideAircraftLanding overrideAircraftLanding;
WRot orientation;
[Sync] [Sync]
public WAngle Facing public WAngle Facing
{ {
get => orientation.Yaw; get => Orientation.Yaw;
set => orientation = orientation.WithYaw(value); set => Orientation = Orientation.WithYaw(value);
} }
public WAngle Pitch public WAngle Pitch
{ {
get => orientation.Pitch; get => Orientation.Pitch;
set => orientation = orientation.WithPitch(value); set => Orientation = Orientation.WithPitch(value);
} }
public WAngle Roll public WAngle Roll
{ {
get => orientation.Roll; get => Orientation.Roll;
set => orientation = orientation.WithRoll(value); set => Orientation = Orientation.WithRoll(value);
} }
public WRot Orientation => orientation; public WRot Orientation { get; private set; }
[Sync] [Sync]
public WPos CenterPosition { get; private set; } public WPos CenterPosition { get; private set; }

View File

@@ -109,8 +109,6 @@ namespace OpenRA.Mods.Common.Traits
{ {
public readonly WeaponInfo Weapon; public readonly WeaponInfo Weapon;
public readonly Barrel[] Barrels; public readonly Barrel[] Barrels;
readonly Actor self;
Turreted turret; Turreted turret;
BodyOrientation coords; BodyOrientation coords;
INotifyBurstComplete[] notifyBurstComplete; INotifyBurstComplete[] notifyBurstComplete;
@@ -136,7 +134,7 @@ namespace OpenRA.Mods.Common.Traits
public Armament(Actor self, ArmamentInfo info) public Armament(Actor self, ArmamentInfo info)
: base(info) : base(info)
{ {
this.self = self; Actor = self;
Weapon = info.WeaponInfo; Weapon = info.WeaponInfo;
Burst = Weapon.Burst; Burst = Weapon.Burst;
@@ -400,6 +398,6 @@ namespace OpenRA.Mods.Common.Traits
return WRot.FromYaw(b.Yaw).Rotate(turret?.WorldOrientation ?? self.Orientation); return WRot.FromYaw(b.Yaw).Rotate(turret?.WorldOrientation ?? self.Orientation);
} }
public Actor Actor => self; public Actor Actor { get; }
} }
} }

View File

@@ -135,15 +135,13 @@ namespace OpenRA.Mods.Common.Traits
[Sync] [Sync]
int nextScanTime = 0; int nextScanTime = 0;
public UnitStance Stance => stance; public UnitStance Stance { get; private set; }
[Sync] [Sync]
public Actor Aggressor; public Actor Aggressor;
// NOT SYNCED: do not refer to this anywhere other than UI code // NOT SYNCED: do not refer to this anywhere other than UI code
public UnitStance PredictedStance; public UnitStance PredictedStance;
UnitStance stance;
IOverrideAutoTarget[] overrideAutoTarget; IOverrideAutoTarget[] overrideAutoTarget;
INotifyStanceChanged[] notifyStanceChanged; INotifyStanceChanged[] notifyStanceChanged;
IEnumerable<AutoTargetPriorityInfo> activeTargetPriorities; IEnumerable<AutoTargetPriorityInfo> activeTargetPriorities;
@@ -151,19 +149,19 @@ namespace OpenRA.Mods.Common.Traits
public void SetStance(Actor self, UnitStance value) public void SetStance(Actor self, UnitStance value)
{ {
if (stance == value) if (Stance == value)
return; return;
var oldStance = stance; var oldStance = Stance;
stance = value; Stance = value;
ApplyStanceCondition(self); ApplyStanceCondition(self);
foreach (var nsc in notifyStanceChanged) foreach (var nsc in notifyStanceChanged)
nsc.StanceChanged(self, this, oldStance, stance); nsc.StanceChanged(self, this, oldStance, Stance);
if (self.CurrentActivity != null) if (self.CurrentActivity != null)
foreach (var a in self.CurrentActivity.ActivitiesImplementing<IActivityNotifyStanceChanged>()) foreach (var a in self.CurrentActivity.ActivitiesImplementing<IActivityNotifyStanceChanged>())
a.StanceChanged(self, this, oldStance, stance); a.StanceChanged(self, this, oldStance, Stance);
} }
void ApplyStanceCondition(Actor self) void ApplyStanceCondition(Actor self)
@@ -171,7 +169,7 @@ namespace OpenRA.Mods.Common.Traits
if (conditionToken != Actor.InvalidConditionToken) if (conditionToken != Actor.InvalidConditionToken)
conditionToken = self.RevokeCondition(conditionToken); conditionToken = self.RevokeCondition(conditionToken);
if (Info.ConditionByStance.TryGetValue(stance, out var condition)) if (Info.ConditionByStance.TryGetValue(Stance, out var condition))
conditionToken = self.GrantCondition(condition); conditionToken = self.GrantCondition(condition);
} }
@@ -181,9 +179,9 @@ namespace OpenRA.Mods.Common.Traits
var self = init.Self; var self = init.Self;
ActiveAttackBases = self.TraitsImplementing<AttackBase>().ToArray().Where(t => !t.IsTraitDisabled); ActiveAttackBases = self.TraitsImplementing<AttackBase>().ToArray().Where(t => !t.IsTraitDisabled);
stance = init.GetValue<StanceInit, UnitStance>(self.Owner.IsBot || !self.Owner.Playable ? info.InitialStanceAI : info.InitialStance); Stance = init.GetValue<StanceInit, UnitStance>(self.Owner.IsBot || !self.Owner.Playable ? info.InitialStanceAI : info.InitialStance);
PredictedStance = stance; PredictedStance = Stance;
allowMovement = Info.AllowMovement && self.TraitOrDefault<IMove>() != null; allowMovement = Info.AllowMovement && self.TraitOrDefault<IMove>() != null;
} }

View File

@@ -146,7 +146,7 @@ namespace OpenRA.Mods.Common.Traits
return randomConstructionYard?.Location ?? initialBaseCenter; return randomConstructionYard?.Location ?? initialBaseCenter;
} }
public CPos DefenseCenter => defenseCenter; public CPos DefenseCenter { get; private set; }
readonly World world; readonly World world;
readonly Player player; readonly Player player;
@@ -155,8 +155,6 @@ namespace OpenRA.Mods.Common.Traits
IResourceLayer resourceLayer; IResourceLayer resourceLayer;
IBotPositionsUpdated[] positionsUpdatedModules; IBotPositionsUpdated[] positionsUpdatedModules;
CPos initialBaseCenter; CPos initialBaseCenter;
CPos defenseCenter;
readonly List<BaseBuilderQueueManager> builders = new List<BaseBuilderQueueManager>(); readonly List<BaseBuilderQueueManager> builders = new List<BaseBuilderQueueManager>();
public BaseBuilderBotModule(Actor self, BaseBuilderBotModuleInfo info) public BaseBuilderBotModule(Actor self, BaseBuilderBotModuleInfo info)
@@ -189,7 +187,7 @@ namespace OpenRA.Mods.Common.Traits
void IBotPositionsUpdated.UpdatedDefenseCenter(CPos newLocation) void IBotPositionsUpdated.UpdatedDefenseCenter(CPos newLocation)
{ {
defenseCenter = newLocation; DefenseCenter = newLocation;
} }
bool IBotRequestPauseUnitProduction.PauseUnitProduction => !IsTraitDisabled && !HasAdequateRefineryCount; bool IBotRequestPauseUnitProduction.PauseUnitProduction => !IsTraitDisabled && !HasAdequateRefineryCount;
@@ -273,7 +271,7 @@ namespace OpenRA.Mods.Common.Traits
return new List<MiniYamlNode>() return new List<MiniYamlNode>()
{ {
new MiniYamlNode("InitialBaseCenter", FieldSaver.FormatValue(initialBaseCenter)), new MiniYamlNode("InitialBaseCenter", FieldSaver.FormatValue(initialBaseCenter)),
new MiniYamlNode("DefenseCenter", FieldSaver.FormatValue(defenseCenter)) new MiniYamlNode("DefenseCenter", FieldSaver.FormatValue(DefenseCenter))
}; };
} }
@@ -288,7 +286,7 @@ namespace OpenRA.Mods.Common.Traits
var defenseCenterNode = data.FirstOrDefault(n => n.Key == "DefenseCenter"); var defenseCenterNode = data.FirstOrDefault(n => n.Key == "DefenseCenter");
if (defenseCenterNode != null) if (defenseCenterNode != null)
defenseCenter = FieldLoader.GetValue<CPos>("DefenseCenter", defenseCenterNode.Value.Value); DefenseCenter = FieldLoader.GetValue<CPos>("DefenseCenter", defenseCenterNode.Value.Value);
} }
} }
} }

View File

@@ -94,20 +94,18 @@ namespace OpenRA.Mods.Common.Traits
{ {
readonly Actor self; readonly Actor self;
readonly bool checkTerrainType; readonly bool checkTerrainType;
DeployState deployState;
INotifyDeployTriggered[] notify; INotifyDeployTriggered[] notify;
int deployedToken = Actor.InvalidConditionToken; int deployedToken = Actor.InvalidConditionToken;
int undeployedToken = Actor.InvalidConditionToken; int undeployedToken = Actor.InvalidConditionToken;
public DeployState DeployState => deployState; public DeployState DeployState { get; private set; }
public GrantConditionOnDeploy(ActorInitializer init, GrantConditionOnDeployInfo info) public GrantConditionOnDeploy(ActorInitializer init, GrantConditionOnDeployInfo info)
: base(info) : base(info)
{ {
self = init.Self; self = init.Self;
checkTerrainType = info.AllowedTerrainTypes.Count > 0; checkTerrainType = info.AllowedTerrainTypes.Count > 0;
deployState = init.GetValue<DeployStateInit, DeployState>(DeployState.Undeployed); DeployState = init.GetValue<DeployStateInit, DeployState>(DeployState.Undeployed);
} }
protected override void Created(Actor self) protected override void Created(Actor self)
@@ -115,14 +113,14 @@ namespace OpenRA.Mods.Common.Traits
notify = self.TraitsImplementing<INotifyDeployTriggered>().ToArray(); notify = self.TraitsImplementing<INotifyDeployTriggered>().ToArray();
base.Created(self); base.Created(self);
if (Info.Facing.HasValue && deployState != DeployState.Undeployed) if (Info.Facing.HasValue && DeployState != DeployState.Undeployed)
{ {
var facing = self.TraitOrDefault<IFacing>(); var facing = self.TraitOrDefault<IFacing>();
if (facing != null) if (facing != null)
facing.Facing = Info.Facing.Value; facing.Facing = Info.Facing.Value;
} }
switch (deployState) switch (DeployState)
{ {
case DeployState.Undeployed: case DeployState.Undeployed:
OnUndeployCompleted(); OnUndeployCompleted();
@@ -153,10 +151,10 @@ namespace OpenRA.Mods.Common.Traits
bool IDelayCarryallPickup.TryLockForPickup(Actor self, Actor carrier) bool IDelayCarryallPickup.TryLockForPickup(Actor self, Actor carrier)
{ {
if (!Info.UndeployOnPickup || deployState == DeployState.Undeployed || IsTraitDisabled) if (!Info.UndeployOnPickup || DeployState == DeployState.Undeployed || IsTraitDisabled)
return true; return true;
if (deployState == DeployState.Deployed && !IsTraitPaused) if (DeployState == DeployState.Deployed && !IsTraitPaused)
Undeploy(); Undeploy();
return false; return false;
@@ -208,7 +206,7 @@ namespace OpenRA.Mods.Common.Traits
if (IsTraitPaused || IsTraitDisabled) if (IsTraitPaused || IsTraitDisabled)
return false; return false;
return IsValidTerrain(self.Location) || (deployState == DeployState.Deployed); return IsValidTerrain(self.Location) || (DeployState == DeployState.Deployed);
} }
public bool IsValidTerrain(CPos location) public bool IsValidTerrain(CPos location)
@@ -253,7 +251,7 @@ namespace OpenRA.Mods.Common.Traits
void Deploy(bool init) void Deploy(bool init)
{ {
// Something went wrong, most likely due to deploy order spam and the fact that this is a delayed action. // Something went wrong, most likely due to deploy order spam and the fact that this is a delayed action.
if (!init && deployState != DeployState.Undeployed) if (!init && DeployState != DeployState.Undeployed)
return; return;
if (!IsValidTerrain(self.Location)) if (!IsValidTerrain(self.Location))
@@ -280,7 +278,7 @@ namespace OpenRA.Mods.Common.Traits
void Undeploy(bool init) void Undeploy(bool init)
{ {
// Something went wrong, most likely due to deploy order spam and the fact that this is a delayed action. // Something went wrong, most likely due to deploy order spam and the fact that this is a delayed action.
if (!init && deployState != DeployState.Deployed) if (!init && DeployState != DeployState.Deployed)
return; return;
if (Info.UndeploySounds != null && Info.UndeploySounds.Length > 0) if (Info.UndeploySounds != null && Info.UndeploySounds.Length > 0)
@@ -303,7 +301,7 @@ namespace OpenRA.Mods.Common.Traits
if (undeployedToken != Actor.InvalidConditionToken) if (undeployedToken != Actor.InvalidConditionToken)
undeployedToken = self.RevokeCondition(undeployedToken); undeployedToken = self.RevokeCondition(undeployedToken);
deployState = DeployState.Deploying; DeployState = DeployState.Deploying;
} }
void OnDeployCompleted() void OnDeployCompleted()
@@ -311,7 +309,7 @@ namespace OpenRA.Mods.Common.Traits
if (deployedToken == Actor.InvalidConditionToken) if (deployedToken == Actor.InvalidConditionToken)
deployedToken = self.GrantCondition(Info.DeployedCondition); deployedToken = self.GrantCondition(Info.DeployedCondition);
deployState = DeployState.Deployed; DeployState = DeployState.Deployed;
} }
void OnUndeployStarted() void OnUndeployStarted()
@@ -319,7 +317,7 @@ namespace OpenRA.Mods.Common.Traits
if (deployedToken != Actor.InvalidConditionToken) if (deployedToken != Actor.InvalidConditionToken)
deployedToken = self.RevokeCondition(deployedToken); deployedToken = self.RevokeCondition(deployedToken);
deployState = DeployState.Deploying; DeployState = DeployState.Deploying;
} }
void OnUndeployCompleted() void OnUndeployCompleted()
@@ -327,7 +325,7 @@ namespace OpenRA.Mods.Common.Traits
if (undeployedToken == Actor.InvalidConditionToken) if (undeployedToken == Actor.InvalidConditionToken)
undeployedToken = self.GrantCondition(Info.UndeployedCondition); undeployedToken = self.GrantCondition(Info.UndeployedCondition);
deployState = DeployState.Undeployed; DeployState = DeployState.Undeployed;
} }
} }

View File

@@ -67,16 +67,14 @@ namespace OpenRA.Mods.Common.Traits
[Sync] [Sync]
public WPos CenterPosition { get; private set; } public WPos CenterPosition { get; private set; }
WRot orientation;
[Sync] [Sync]
public WAngle Facing public WAngle Facing
{ {
get => orientation.Yaw; get => Orientation.Yaw;
set => orientation = orientation.WithYaw(value); set => Orientation = Orientation.WithYaw(value);
} }
public WRot Orientation => orientation; public WRot Orientation { get; private set; }
public WAngle TurnSpeed => WAngle.Zero; public WAngle TurnSpeed => WAngle.Zero;

View File

@@ -194,7 +194,6 @@ namespace OpenRA.Mods.Common.Traits
WAngle oldFacing; WAngle oldFacing;
WRot orientation; WRot orientation;
WPos oldPos; WPos oldPos;
CPos fromCell, toCell;
public SubCell FromSubCell, ToSubCell; public SubCell FromSubCell, ToSubCell;
INotifyCustomLayerChanged[] notifyCustomLayerChanged; INotifyCustomLayerChanged[] notifyCustomLayerChanged;
@@ -226,10 +225,10 @@ namespace OpenRA.Mods.Common.Traits
#endregion #endregion
[Sync] [Sync]
public CPos FromCell => fromCell; public CPos FromCell { get; private set; }
[Sync] [Sync]
public CPos ToCell => toCell; public CPos ToCell { get; private set; }
public Locomotor Locomotor { get; private set; } public Locomotor Locomotor { get; private set; }
@@ -274,7 +273,7 @@ namespace OpenRA.Mods.Common.Traits
var locationInit = init.GetOrDefault<LocationInit>(); var locationInit = init.GetOrDefault<LocationInit>();
if (locationInit != null) if (locationInit != null)
{ {
fromCell = toCell = locationInit.Value; FromCell = ToCell = locationInit.Value;
SetCenterPosition(self, init.World.Map.CenterOfSubCell(FromCell, FromSubCell)); SetCenterPosition(self, init.World.Map.CenterOfSubCell(FromCell, FromSubCell));
} }
@@ -499,7 +498,7 @@ namespace OpenRA.Mods.Common.Traits
return; return;
foreach (var n in notifyCenterPositionChanged) foreach (var n in notifyCenterPositionChanged)
n.CenterPositionChanged(self, fromCell.Layer, toCell.Layer); n.CenterPositionChanged(self, FromCell.Layer, ToCell.Layer);
} }
public void SetTerrainRampOrientation(WRot orientation) public void SetTerrainRampOrientation(WRot orientation)
@@ -510,7 +509,7 @@ namespace OpenRA.Mods.Common.Traits
public bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any) public bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any)
{ {
return ToCell != location && fromCell == location return ToCell != location && FromCell == location
&& (subCell == SubCell.Any || FromSubCell == subCell || subCell == SubCell.FullCell || FromSubCell == SubCell.FullCell); && (subCell == SubCell.Any || FromSubCell == subCell || subCell == SubCell.FullCell || FromSubCell == SubCell.FullCell);
} }
@@ -545,25 +544,25 @@ namespace OpenRA.Mods.Common.Traits
return; return;
RemoveInfluence(); RemoveInfluence();
fromCell = from; FromCell = from;
toCell = to; ToCell = to;
FromSubCell = fromSub; FromSubCell = fromSub;
ToSubCell = toSub; ToSubCell = toSub;
AddInfluence(); AddInfluence();
IsBlocking = false; IsBlocking = false;
// Most custom layer conditions are added/removed when starting the transition between layers. // Most custom layer conditions are added/removed when starting the transition between layers.
if (toCell.Layer != fromCell.Layer) if (ToCell.Layer != FromCell.Layer)
foreach (var n in notifyCustomLayerChanged) foreach (var n in notifyCustomLayerChanged)
n.CustomLayerChanged(self, fromCell.Layer, toCell.Layer); n.CustomLayerChanged(self, FromCell.Layer, ToCell.Layer);
} }
public void FinishedMoving(Actor self) public void FinishedMoving(Actor self)
{ {
// Need to check both fromCell and toCell because FinishedMoving is called multiple times during the move // Need to check both fromCell and toCell because FinishedMoving is called multiple times during the move
if (fromCell.Layer == toCell.Layer) if (FromCell.Layer == ToCell.Layer)
foreach (var n in notifyFinishedMoving) foreach (var n in notifyFinishedMoving)
n.FinishedMoving(self, fromCell.Layer, toCell.Layer); n.FinishedMoving(self, FromCell.Layer, ToCell.Layer);
// Only crush actors on having landed // Only crush actors on having landed
if (!self.IsAtGroundLevel()) if (!self.IsAtGroundLevel())

View File

@@ -126,7 +126,6 @@ namespace OpenRA.Mods.Common.Traits
public class ProductionQueue : IResolveOrder, ITick, ITechTreeElement, INotifyOwnerChanged, INotifyKilled, INotifySold, ISync, INotifyTransform, INotifyCreated public class ProductionQueue : IResolveOrder, ITick, ITechTreeElement, INotifyOwnerChanged, INotifyKilled, INotifySold, ISync, INotifyTransform, INotifyCreated
{ {
public readonly ProductionQueueInfo Info; public readonly ProductionQueueInfo Info;
readonly Actor self;
// A list of things we could possibly build // A list of things we could possibly build
protected readonly Dictionary<ActorInfo, ProductionState> Producible = new Dictionary<ActorInfo, ProductionState>(); protected readonly Dictionary<ActorInfo, ProductionState> Producible = new Dictionary<ActorInfo, ProductionState>();
@@ -142,7 +141,7 @@ namespace OpenRA.Mods.Common.Traits
protected DeveloperMode developerMode; protected DeveloperMode developerMode;
protected TechTree techTree; protected TechTree techTree;
public Actor Actor => self; public Actor Actor { get; }
[Sync] [Sync]
public bool Enabled { get; protected set; } public bool Enabled { get; protected set; }
@@ -154,10 +153,10 @@ namespace OpenRA.Mods.Common.Traits
public ProductionQueue(ActorInitializer init, ProductionQueueInfo info) public ProductionQueue(ActorInitializer init, ProductionQueueInfo info)
{ {
self = init.Self; Actor = init.Self;
Info = info; Info = info;
Faction = init.GetValue<FactionInit, string>(self.Owner.Faction.InternalName); Faction = init.GetValue<FactionInit, string>(Actor.Owner.Faction.InternalName);
IsValidFaction = info.Factions.Count == 0 || info.Factions.Contains(Faction); IsValidFaction = info.Factions.Count == 0 || info.Factions.Contains(Faction);
Enabled = IsValidFaction; Enabled = IsValidFaction;
@@ -205,7 +204,7 @@ namespace OpenRA.Mods.Common.Traits
techTree.Update(); techTree.Update();
} }
void INotifyKilled.Killed(Actor killed, AttackInfo e) { if (killed == self) { ClearQueue(); Enabled = false; } } void INotifyKilled.Killed(Actor killed, AttackInfo e) { if (killed == Actor) { ClearQueue(); Enabled = false; } }
void INotifySold.Selling(Actor self) { ClearQueue(); Enabled = false; } void INotifySold.Selling(Actor self) { ClearQueue(); Enabled = false; }
void INotifySold.Sold(Actor self) { } void INotifySold.Sold(Actor self) { }
@@ -230,7 +229,7 @@ namespace OpenRA.Mods.Common.Traits
IEnumerable<ActorInfo> AllBuildables(string category) IEnumerable<ActorInfo> AllBuildables(string category)
{ {
return self.World.Map.Rules.Actors.Values return Actor.World.Map.Rules.Actors.Values
.Where(x => .Where(x =>
x.Name[0] != '^' && x.Name[0] != '^' &&
x.HasTraitInfo<BuildableInfo>() && x.HasTraitInfo<BuildableInfo>() &&
@@ -239,22 +238,22 @@ namespace OpenRA.Mods.Common.Traits
public void PrerequisitesAvailable(string key) public void PrerequisitesAvailable(string key)
{ {
Producible[self.World.Map.Rules.Actors[key]].Buildable = true; Producible[Actor.World.Map.Rules.Actors[key]].Buildable = true;
} }
public void PrerequisitesUnavailable(string key) public void PrerequisitesUnavailable(string key)
{ {
Producible[self.World.Map.Rules.Actors[key]].Buildable = false; Producible[Actor.World.Map.Rules.Actors[key]].Buildable = false;
} }
public void PrerequisitesItemHidden(string key) public void PrerequisitesItemHidden(string key)
{ {
Producible[self.World.Map.Rules.Actors[key]].Visible = false; Producible[Actor.World.Map.Rules.Actors[key]].Visible = false;
} }
public void PrerequisitesItemVisible(string key) public void PrerequisitesItemVisible(string key)
{ {
Producible[self.World.Map.Rules.Actors[key]].Visible = true; Producible[Actor.World.Map.Rules.Actors[key]].Visible = true;
} }
public virtual bool IsProducing(ProductionItem item) public virtual bool IsProducing(ProductionItem item)
@@ -381,8 +380,8 @@ namespace OpenRA.Mods.Common.Traits
if (bi.BuildLimit > 0) if (bi.BuildLimit > 0)
{ {
var owned = self.Owner.World.ActorsHavingTrait<Buildable>() var owned = Actor.Owner.World.ActorsHavingTrait<Buildable>()
.Count(a => a.Info.Name == actor.Name && a.Owner == self.Owner); .Count(a => a.Info.Name == actor.Name && a.Owner == Actor.Owner);
if (queueCount + owned >= bi.BuildLimit) if (queueCount + owned >= bi.BuildLimit)
return false; return false;
} }
@@ -591,7 +590,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
var traits = productionTraits.Where(p => !p.IsTraitDisabled && p.Info.Produces.Contains(Info.Type)); var traits = productionTraits.Where(p => !p.IsTraitDisabled && p.Info.Produces.Contains(Info.Type));
var unpaused = traits.FirstOrDefault(a => !a.IsTraitPaused); var unpaused = traits.FirstOrDefault(a => !a.IsTraitPaused);
return new TraitPair<Production>(self, unpaused ?? traits.FirstOrDefault()); return new TraitPair<Production>(Actor, unpaused ?? traits.FirstOrDefault());
} }
// Builds a unit from the actor that holds this queue (1 queue per building) // Builds a unit from the actor that holds this queue (1 queue per building)
@@ -601,7 +600,7 @@ namespace OpenRA.Mods.Common.Traits
var mostLikelyProducerTrait = MostLikelyProducer().Trait; var mostLikelyProducerTrait = MostLikelyProducer().Trait;
// Cannot produce if I'm dead or trait is disabled // Cannot produce if I'm dead or trait is disabled
if (!self.IsInWorld || self.IsDead || mostLikelyProducerTrait == null) if (!Actor.IsInWorld || Actor.IsDead || mostLikelyProducerTrait == null)
{ {
CancelProduction(unit.Name, 1); CancelProduction(unit.Name, 1);
return false; return false;
@@ -609,14 +608,14 @@ namespace OpenRA.Mods.Common.Traits
var inits = new TypeDictionary var inits = new TypeDictionary
{ {
new OwnerInit(self.Owner), new OwnerInit(Actor.Owner),
new FactionInit(BuildableInfo.GetInitialFaction(unit, Faction)) new FactionInit(BuildableInfo.GetInitialFaction(unit, Faction))
}; };
var bi = unit.TraitInfo<BuildableInfo>(); var bi = unit.TraitInfo<BuildableInfo>();
var type = developerMode.AllTech ? Info.Type : (bi.BuildAtProductionType ?? Info.Type); var type = developerMode.AllTech ? Info.Type : (bi.BuildAtProductionType ?? Info.Type);
var item = Queue.First(i => i.Done && i.Item == unit.Name); var item = Queue.First(i => i.Done && i.Item == unit.Name);
if (!mostLikelyProducerTrait.IsTraitPaused && mostLikelyProducerTrait.Produce(self, unit, type, inits, item.TotalCost)) if (!mostLikelyProducerTrait.IsTraitPaused && mostLikelyProducerTrait.Produce(Actor, unit, type, inits, item.TotalCost))
{ {
EndProduction(item); EndProduction(item);
return true; return true;

View File

@@ -27,11 +27,10 @@ namespace OpenRA.Mods.Common.Traits
public class TechTree public class TechTree
{ {
readonly List<Watcher> watchers = new List<Watcher>(); readonly List<Watcher> watchers = new List<Watcher>();
readonly Player player;
public TechTree(ActorInitializer init) public TechTree(ActorInitializer init)
{ {
player = init.Self.Owner; Owner = init.Self.Owner;
init.World.ActorAdded += ActorChanged; init.World.ActorAdded += ActorChanged;
init.World.ActorRemoved += ActorChanged; init.World.ActorRemoved += ActorChanged;
} }
@@ -39,13 +38,13 @@ namespace OpenRA.Mods.Common.Traits
public void ActorChanged(Actor a) public void ActorChanged(Actor a)
{ {
var bi = a.Info.TraitInfoOrDefault<BuildableInfo>(); var bi = a.Info.TraitInfoOrDefault<BuildableInfo>();
if (a.Owner == player && (a.Info.HasTraitInfo<ITechTreePrerequisiteInfo>() || (bi != null && bi.BuildLimit > 0))) if (a.Owner == Owner && (a.Info.HasTraitInfo<ITechTreePrerequisiteInfo>() || (bi != null && bi.BuildLimit > 0)))
Update(); Update();
} }
public void Update() public void Update()
{ {
var ownedPrerequisites = GatherOwnedPrerequisites(player); var ownedPrerequisites = GatherOwnedPrerequisites(Owner);
foreach (var w in watchers) foreach (var w in watchers)
w.Update(ownedPrerequisites); w.Update(ownedPrerequisites);
} }
@@ -67,7 +66,7 @@ namespace OpenRA.Mods.Common.Traits
public bool HasPrerequisites(IEnumerable<string> prerequisites) public bool HasPrerequisites(IEnumerable<string> prerequisites)
{ {
var ownedPrereqs = GatherOwnedPrerequisites(player); var ownedPrereqs = GatherOwnedPrerequisites(Owner);
return prerequisites.All(p => !(p.Replace("~", "").StartsWith("!", StringComparison.Ordinal) return prerequisites.All(p => !(p.Replace("~", "").StartsWith("!", StringComparison.Ordinal)
^ !ownedPrereqs.ContainsKey(p.Replace("!", "").Replace("~", "")))); ^ !ownedPrereqs.ContainsKey(p.Replace("!", "").Replace("~", ""))));
} }
@@ -109,16 +108,15 @@ namespace OpenRA.Mods.Common.Traits
return ret; return ret;
} }
public Player Owner => player; public Player Owner { get; }
class Watcher class Watcher
{ {
public readonly string Key; public readonly string Key;
public ITechTreeElement RegisteredBy => watcher; public ITechTreeElement RegisteredBy { get; }
// Strings may be either actor type, or "alternate name" key // Strings may be either actor type, or "alternate name" key
readonly string[] prerequisites; readonly string[] prerequisites;
readonly ITechTreeElement watcher;
bool hasPrerequisites; bool hasPrerequisites;
readonly int limit; readonly int limit;
bool hidden; bool hidden;
@@ -128,7 +126,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
Key = key; Key = key;
this.prerequisites = prerequisites; this.prerequisites = prerequisites;
this.watcher = watcher; RegisteredBy = watcher;
hasPrerequisites = false; hasPrerequisites = false;
this.limit = limit; this.limit = limit;
hidden = false; hidden = false;
@@ -179,16 +177,16 @@ namespace OpenRA.Mods.Common.Traits
// Hide the item from the UI if a prereq annotated with '~' is not met. // Hide the item from the UI if a prereq annotated with '~' is not met.
if (nowHidden && !hidden) if (nowHidden && !hidden)
watcher.PrerequisitesItemHidden(Key); RegisteredBy.PrerequisitesItemHidden(Key);
if (!nowHidden && hidden) if (!nowHidden && hidden)
watcher.PrerequisitesItemVisible(Key); RegisteredBy.PrerequisitesItemVisible(Key);
if (nowHasPrerequisites && !hasPrerequisites) if (nowHasPrerequisites && !hasPrerequisites)
watcher.PrerequisitesAvailable(Key); RegisteredBy.PrerequisitesAvailable(Key);
if (!nowHasPrerequisites && hasPrerequisites) if (!nowHasPrerequisites && hasPrerequisites)
watcher.PrerequisitesUnavailable(Key); RegisteredBy.PrerequisitesUnavailable(Key);
hidden = nowHidden; hidden = nowHidden;
hasPrerequisites = nowHasPrerequisites; hasPrerequisites = nowHasPrerequisites;

View File

@@ -121,10 +121,9 @@ namespace OpenRA.Mods.Common.Traits
readonly SpawnActorPower power; readonly SpawnActorPower power;
readonly SpawnActorPowerInfo info; readonly SpawnActorPowerInfo info;
readonly SupportPowerManager manager; readonly SupportPowerManager manager;
readonly string order;
readonly MouseButton expectedButton; readonly MouseButton expectedButton;
public string OrderKey { get { return order; } } public string OrderKey { get; }
public SelectSpawnActorPowerTarget(string order, SupportPowerManager manager, SpawnActorPower power, MouseButton button) public SelectSpawnActorPowerTarget(string order, SupportPowerManager manager, SpawnActorPower power, MouseButton button)
{ {
@@ -134,7 +133,7 @@ namespace OpenRA.Mods.Common.Traits
this.manager = manager; this.manager = manager;
this.power = power; this.power = power;
this.order = order; OrderKey = order;
expectedButton = button; expectedButton = button;
info = (SpawnActorPowerInfo)power.Info; info = (SpawnActorPowerInfo)power.Info;
@@ -148,13 +147,13 @@ namespace OpenRA.Mods.Common.Traits
yield break; yield break;
if (mi.Button == expectedButton) if (mi.Button == expectedButton)
yield return new Order(order, manager.Self, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true }; yield return new Order(OrderKey, manager.Self, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true };
} }
protected override void Tick(World world) protected override void Tick(World world)
{ {
// Cancel the OG if we can't use the power // Cancel the OG if we can't use the power
if (!manager.Powers.ContainsKey(order)) if (!manager.Powers.ContainsKey(OrderKey))
world.CancelInputMode(); world.CancelInputMode();
} }

View File

@@ -279,11 +279,10 @@ namespace OpenRA.Mods.Common.Traits
public class SelectGenericPowerTarget : OrderGenerator public class SelectGenericPowerTarget : OrderGenerator
{ {
readonly SupportPowerManager manager; readonly SupportPowerManager manager;
readonly string order;
readonly string cursor; readonly string cursor;
readonly MouseButton expectedButton; readonly MouseButton expectedButton;
public string OrderKey => order; public string OrderKey { get; }
public SelectGenericPowerTarget(string order, SupportPowerManager manager, string cursor, MouseButton button) public SelectGenericPowerTarget(string order, SupportPowerManager manager, string cursor, MouseButton button)
{ {
@@ -292,7 +291,7 @@ namespace OpenRA.Mods.Common.Traits
manager.Self.World.Selection.Clear(); manager.Self.World.Selection.Clear();
this.manager = manager; this.manager = manager;
this.order = order; OrderKey = order;
this.cursor = cursor; this.cursor = cursor;
expectedButton = button; expectedButton = button;
} }
@@ -301,13 +300,13 @@ namespace OpenRA.Mods.Common.Traits
{ {
world.CancelInputMode(); world.CancelInputMode();
if (mi.Button == expectedButton && world.Map.Contains(cell)) if (mi.Button == expectedButton && world.Map.Contains(cell))
yield return new Order(order, manager.Self, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true }; yield return new Order(OrderKey, manager.Self, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true };
} }
protected override void Tick(World world) protected override void Tick(World world)
{ {
// Cancel the OG if we can't use the power // Cancel the OG if we can't use the power
if (!manager.Powers.TryGetValue(order, out var p) || !p.Active || !p.Ready) if (!manager.Powers.TryGetValue(OrderKey, out var p) || !p.Active || !p.Ready)
world.CancelInputMode(); world.CancelInputMode();
} }

View File

@@ -229,24 +229,23 @@ namespace OpenRA.Mods.Common.Traits
struct ActorsAtEnumerator : IEnumerator<Actor> struct ActorsAtEnumerator : IEnumerator<Actor>
{ {
InfluenceNode node; InfluenceNode node;
Actor current;
public ActorsAtEnumerator(InfluenceNode node) public ActorsAtEnumerator(InfluenceNode node)
{ {
this.node = node; this.node = node;
current = null; Current = null;
} }
public void Reset() { throw new NotSupportedException(); } public void Reset() { throw new NotSupportedException(); }
public Actor Current => current; public Actor Current { get; private set; }
object IEnumerator.Current => current; object IEnumerator.Current => Current;
public void Dispose() { } public void Dispose() { }
public bool MoveNext() public bool MoveNext()
{ {
while (node != null) while (node != null)
{ {
current = node.Actor; Current = node.Actor;
node = node.Next; node = node.Next;
return true; return true;
} }

View File

@@ -26,19 +26,17 @@ namespace OpenRA.Mods.Common.Widgets
public bool DrawOverlay = true; public bool DrawOverlay = true;
public bool Skippable = true; public bool Skippable = true;
public bool Paused => paused; public bool Paused { get; private set; }
public IVideo Video => video; public IVideo Video { get; private set; } = null;
Sprite videoSprite, overlaySprite; Sprite videoSprite, overlaySprite;
Sheet overlaySheet; Sheet overlaySheet;
IVideo video = null;
string cachedVideoFileName; string cachedVideoFileName;
float invLength; float invLength;
float2 videoOrigin, videoSize; float2 videoOrigin, videoSize;
float2 overlayOrigin, overlaySize; float2 overlayOrigin, overlaySize;
float overlayScale; float overlayScale;
bool stopped; bool stopped;
bool paused;
int textureSize; int textureSize;
Action onComplete; Action onComplete;
@@ -110,13 +108,13 @@ namespace OpenRA.Mods.Common.Widgets
/// <param name="video">An <see cref="IVideo"/> instance.</param> /// <param name="video">An <see cref="IVideo"/> instance.</param>
public void Play(IVideo video) public void Play(IVideo video)
{ {
this.video = video; Video = video;
if (video == null) if (video == null)
return; return;
stopped = true; stopped = true;
paused = true; Paused = true;
Game.Sound.StopVideo(); Game.Sound.StopVideo();
onComplete = () => { }; onComplete = () => { };
@@ -148,34 +146,34 @@ namespace OpenRA.Mods.Common.Widgets
public override void Draw() public override void Draw()
{ {
if (video == null) if (Video == null)
return; return;
if (!stopped && !paused) if (!stopped && !Paused)
{ {
int nextFrame; int nextFrame;
if (video.HasAudio && !Game.Sound.DummyEngine) if (Video.HasAudio && !Game.Sound.DummyEngine)
nextFrame = (int)float2.Lerp(0, video.FrameCount, Game.Sound.VideoSeekPosition * invLength); nextFrame = (int)float2.Lerp(0, Video.FrameCount, Game.Sound.VideoSeekPosition * invLength);
else else
nextFrame = video.CurrentFrameIndex + 1; nextFrame = Video.CurrentFrameIndex + 1;
// Without the 2nd check the sound playback sometimes ends before the final frame is displayed which causes the player to be stuck on the first frame // Without the 2nd check the sound playback sometimes ends before the final frame is displayed which causes the player to be stuck on the first frame
if (nextFrame > video.FrameCount || nextFrame < video.CurrentFrameIndex) if (nextFrame > Video.FrameCount || nextFrame < Video.CurrentFrameIndex)
{ {
Stop(); Stop();
return; return;
} }
var skippedFrames = 0; var skippedFrames = 0;
while (nextFrame > video.CurrentFrameIndex) while (nextFrame > Video.CurrentFrameIndex)
{ {
video.AdvanceFrame(); Video.AdvanceFrame();
videoSprite.Sheet.GetTexture().SetData(video.CurrentFrameData, textureSize, textureSize); videoSprite.Sheet.GetTexture().SetData(Video.CurrentFrameData, textureSize, textureSize);
skippedFrames++; skippedFrames++;
} }
if (skippedFrames > 1) if (skippedFrames > 1)
Log.Write("perf", $"{nameof(VideoPlayerWidget)}: {cachedVideoFileName} skipped {skippedFrames} frames at position {video.CurrentFrameIndex}"); Log.Write("perf", $"{nameof(VideoPlayerWidget)}: {cachedVideoFileName} skipped {skippedFrames} frames at position {Video.CurrentFrameIndex}");
} }
WidgetUtils.DrawSprite(videoSprite, videoOrigin, videoSize); WidgetUtils.DrawSprite(videoSprite, videoOrigin, videoSize);
@@ -196,7 +194,7 @@ namespace OpenRA.Mods.Common.Widgets
// Calculate the scan line height by converting the video scale (copied from Open()) to screen // Calculate the scan line height by converting the video scale (copied from Open()) to screen
// pixels, halving it (scan lines cover half the pixel height), and rounding to the nearest integer. // pixels, halving it (scan lines cover half the pixel height), and rounding to the nearest integer.
var videoScale = Math.Min((float)RenderBounds.Width / video.Width, RenderBounds.Height / (video.Height * AspectRatio)); var videoScale = Math.Min((float)RenderBounds.Width / Video.Width, RenderBounds.Height / (Video.Height * AspectRatio));
var halfRowHeight = (int)(videoScale * scale / 2 + 0.5f); var halfRowHeight = (int)(videoScale * scale / 2 + 0.5f);
// If the video is "too tightly packed" into the player and there is no room for drawing an overlay disable it. // If the video is "too tightly packed" into the player and there is no room for drawing an overlay disable it.
@@ -255,37 +253,37 @@ namespace OpenRA.Mods.Common.Widgets
public void PlayThen(Action after) public void PlayThen(Action after)
{ {
if (video == null) if (Video == null)
return; return;
onComplete = after; onComplete = after;
if (stopped && video.HasAudio) if (stopped && Video.HasAudio)
Game.Sound.PlayVideo(video.AudioData, video.AudioChannels, video.SampleBits, video.SampleRate); Game.Sound.PlayVideo(Video.AudioData, Video.AudioChannels, Video.SampleBits, Video.SampleRate);
else else
Game.Sound.PlayVideo(); Game.Sound.PlayVideo();
stopped = paused = false; stopped = Paused = false;
} }
public void Pause() public void Pause()
{ {
if (stopped || paused || video == null) if (stopped || Paused || Video == null)
return; return;
paused = true; Paused = true;
Game.Sound.PauseVideo(); Game.Sound.PauseVideo();
} }
public void Stop() public void Stop()
{ {
if (stopped || video == null) if (stopped || Video == null)
return; return;
stopped = true; stopped = true;
paused = true; Paused = true;
Game.Sound.StopVideo(); Game.Sound.StopVideo();
video.Reset(); Video.Reset();
videoSprite.Sheet.GetTexture().SetData(video.CurrentFrameData, textureSize, textureSize); videoSprite.Sheet.GetTexture().SetData(Video.CurrentFrameData, textureSize, textureSize);
Game.RunAfterTick(() => Game.RunAfterTick(() =>
{ {
if (onComplete != null) if (onComplete != null)
@@ -299,7 +297,7 @@ namespace OpenRA.Mods.Common.Widgets
public void CloseVideo() public void CloseVideo()
{ {
Stop(); Stop();
video = null; Video = null;
} }
} }
} }

View File

@@ -22,10 +22,9 @@ namespace OpenRA.Platforms.Default
{ {
sealed class Sdl2PlatformWindow : ThreadAffine, IPlatformWindow sealed class Sdl2PlatformWindow : ThreadAffine, IPlatformWindow
{ {
readonly IGraphicsContext context;
readonly Sdl2Input input; readonly Sdl2Input input;
public IGraphicsContext Context => context; public IGraphicsContext Context { get; }
readonly IntPtr window; readonly IntPtr window;
bool disposed; bool disposed;
@@ -341,12 +340,12 @@ namespace OpenRA.Platforms.Default
{ {
var ctx = new Sdl2GraphicsContext(this); var ctx = new Sdl2GraphicsContext(this);
ctx.InitializeOpenGL(); ctx.InitializeOpenGL();
context = ctx; Context = ctx;
} }
else else
context = new ThreadedGraphicsContext(new Sdl2GraphicsContext(this), batchSize); Context = new ThreadedGraphicsContext(new Sdl2GraphicsContext(this), batchSize);
context.SetVSyncEnabled(Game.Settings.Graphics.VSync); Context.SetVSyncEnabled(Game.Settings.Graphics.VSync);
SDL.SDL_SetModState(SDL.SDL_Keymod.KMOD_NONE); SDL.SDL_SetModState(SDL.SDL_Keymod.KMOD_NONE);
input = new Sdl2Input(); input = new Sdl2Input();
@@ -467,7 +466,7 @@ namespace OpenRA.Platforms.Default
disposed = true; disposed = true;
context?.Dispose(); Context?.Dispose();
if (Window != IntPtr.Zero) if (Window != IntPtr.Zero)
SDL.SDL_DestroyWindow(Window); SDL.SDL_DestroyWindow(Window);

View File

@@ -566,7 +566,6 @@ namespace OpenRA.Platforms.Default
class ThreadedTexture : ITextureInternal class ThreadedTexture : ITextureInternal
{ {
readonly ThreadedGraphicsContext device; readonly ThreadedGraphicsContext device;
readonly uint id;
readonly Func<object> getScaleFilter; readonly Func<object> getScaleFilter;
readonly Action<object> setScaleFilter; readonly Action<object> setScaleFilter;
readonly Func<object> getSize; readonly Func<object> getSize;
@@ -581,7 +580,7 @@ namespace OpenRA.Platforms.Default
public ThreadedTexture(ThreadedGraphicsContext device, ITextureInternal texture) public ThreadedTexture(ThreadedGraphicsContext device, ITextureInternal texture)
{ {
this.device = device; this.device = device;
id = texture.ID; ID = texture.ID;
getScaleFilter = () => texture.ScaleFilter; getScaleFilter = () => texture.ScaleFilter;
setScaleFilter = value => texture.ScaleFilter = (TextureScaleFilter)value; setScaleFilter = value => texture.ScaleFilter = (TextureScaleFilter)value;
getSize = () => texture.Size; getSize = () => texture.Size;
@@ -594,7 +593,7 @@ namespace OpenRA.Platforms.Default
dispose = texture.Dispose; dispose = texture.Dispose;
} }
public uint ID => id; public uint ID { get; }
public TextureScaleFilter ScaleFilter public TextureScaleFilter ScaleFilter
{ {