Merge pull request #5410 from RoosterDragon/IDisposable

Disposable fixup
This commit is contained in:
Paul Chote
2014-06-11 10:55:44 +12:00
37 changed files with 248 additions and 260 deletions

View File

@@ -70,6 +70,7 @@ namespace OpenRA
{ {
Game.OnQuit -= Cancel; Game.OnQuit -= Cancel;
wc.CancelAsync(); wc.CancelAsync();
wc.Dispose();
cancelled = true; cancelled = true;
} }
} }

View File

@@ -17,7 +17,7 @@ using OpenRA.FileFormats;
namespace OpenRA.FileSystem namespace OpenRA.FileSystem
{ {
public class MixFile : IFolder public sealed class MixFile : IFolder, IDisposable
{ {
readonly Dictionary<uint, PackageEntry> index; readonly Dictionary<uint, PackageEntry> index;
readonly long dataStart; readonly long dataStart;
@@ -258,5 +258,11 @@ namespace OpenRA.FileSystem
s.Write(file.Value); s.Write(file.Value);
} }
} }
public void Dispose()
{
if (s != null)
s.Dispose();
}
} }
} }

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
@@ -16,7 +17,7 @@ using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
namespace OpenRA.FileSystem namespace OpenRA.FileSystem
{ {
public class ZipFile : IFolder public sealed class ZipFile : IFolder, IDisposable
{ {
string filename; string filename;
SZipFile pkg; SZipFile pkg;
@@ -105,6 +106,12 @@ namespace OpenRA.FileSystem
pkg.Close(); pkg.Close();
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename))); pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename)));
} }
public void Dispose()
{
if (pkg != null)
pkg.Close();
}
} }
class StaticMemoryDataSource : IStaticDataSource class StaticMemoryDataSource : IStaticDataSource

View File

@@ -504,6 +504,8 @@ namespace OpenRA
// Ensure that the active replay is properly saved // Ensure that the active replay is properly saved
if (orderManager != null) if (orderManager != null)
orderManager.Dispose(); orderManager.Dispose();
Renderer.Device.Dispose();
OnQuit(); OnQuit();
} }

View File

@@ -31,7 +31,8 @@ namespace OpenRA.GameRules
return; return;
Exists = true; Exists = true;
Length = (int)AudLoader.SoundLength(GlobalFileSystem.Open(Filename)); using (var s = GlobalFileSystem.Open(Filename))
Length = (int)AudLoader.SoundLength(s);
} }
public void Reload() public void Reload()
@@ -40,7 +41,8 @@ namespace OpenRA.GameRules
return; return;
Exists = true; Exists = true;
Length = (int)AudLoader.SoundLength(GlobalFileSystem.Open(Filename)); using (var s = GlobalFileSystem.Open(Filename))
Length = (int)AudLoader.SoundLength(s);
} }
} }
} }

View File

@@ -40,31 +40,34 @@ namespace OpenRA.Graphics
public Sheet(string filename) public Sheet(string filename)
{ {
var bitmap = (Bitmap)Image.FromStream(GlobalFileSystem.Open(filename)); using (var stream = GlobalFileSystem.Open(filename))
Size = bitmap.Size; using (var bitmap = (Bitmap)Image.FromStream(stream))
data = new byte[4*Size.Width*Size.Height];
var b = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
unsafe
{ {
int* c = (int*)b.Scan0; Size = bitmap.Size;
for (var x = 0; x < Size.Width; x++) data = new byte[4 * Size.Width * Size.Height];
for (var y = 0; y < Size.Height; y++) var b = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
unsafe
{ {
var i = 4*Size.Width*y + 4*x; int* c = (int*)b.Scan0;
// Convert argb to bgra for (var x = 0; x < Size.Width; x++)
var argb = *(c + (y * b.Stride >> 2) + x); for (var y = 0; y < Size.Height; y++)
data[i++] = (byte)(argb >> 0); {
data[i++] = (byte)(argb >> 8); var i = 4 * Size.Width * y + 4 * x;
data[i++] = (byte)(argb >> 16);
data[i++] = (byte)(argb >> 24); // Convert argb to bgra
var argb = *(c + (y * b.Stride >> 2) + x);
data[i++] = (byte)(argb >> 0);
data[i++] = (byte)(argb >> 8);
data[i++] = (byte)(argb >> 16);
data[i++] = (byte)(argb >> 24);
}
} }
bitmap.UnlockBits(b);
} }
bitmap.UnlockBits(b);
} }
public ITexture Texture public ITexture Texture

View File

@@ -108,27 +108,29 @@ namespace OpenRA.Graphics
Offset = { X = face.Glyph.BitmapLeft, Y = -face.Glyph.BitmapTop } Offset = { X = face.Glyph.BitmapLeft, Y = -face.Glyph.BitmapTop }
}; };
unsafe // A new bitmap is generated each time this property is accessed, so we do need to dispose it.
{ using (var bitmap = face.Glyph.Bitmap)
var p = (byte*)face.Glyph.Bitmap.Buffer; unsafe
var dest = s.sheet.Data;
var destStride = s.sheet.Size.Width * 4;
for (var j = 0; j < s.size.Y; j++)
{ {
for (var i = 0; i < s.size.X; i++) var p = (byte*)bitmap.Buffer;
if (p[i] != 0) var dest = s.sheet.Data;
{ var destStride = s.sheet.Size.Width * 4;
var q = destStride * (j + s.bounds.Top) + 4 * (i + s.bounds.Left);
dest[q] = c.Second.B;
dest[q + 1] = c.Second.G;
dest[q + 2] = c.Second.R;
dest[q + 3] = p[i];
}
p += face.Glyph.Bitmap.Pitch; for (var j = 0; j < s.size.Y; j++)
{
for (var i = 0; i < s.size.X; i++)
if (p[i] != 0)
{
var q = destStride * (j + s.bounds.Top) + 4 * (i + s.bounds.Left);
dest[q] = c.Second.B;
dest[q + 1] = c.Second.G;
dest[q + 2] = c.Second.R;
dest[q + 3] = p[i];
}
p += bitmap.Pitch;
}
} }
}
s.sheet.CommitData(); s.sheet.CommitData();
return g; return g;

View File

@@ -33,10 +33,10 @@ namespace OpenRA.Graphics
Sprite[] CacheSpriteFrames(string filename) Sprite[] CacheSpriteFrames(string filename)
{ {
var stream = GlobalFileSystem.OpenWithExts(filename, exts); using (var stream = GlobalFileSystem.OpenWithExts(filename, exts))
return SpriteSource.LoadSpriteSource(stream, filename).Frames return SpriteSource.LoadSpriteSource(stream, filename).Frames
.Select(a => SheetBuilder.Add(a)) .Select(a => SheetBuilder.Add(a))
.ToArray(); .ToArray();
} }
public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; } public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }

View File

@@ -210,8 +210,12 @@ namespace OpenRA.Graphics
Voxel LoadFile(Pair<string,string> files) Voxel LoadFile(Pair<string,string> files)
{ {
var vxl = new VxlReader(GlobalFileSystem.OpenWithExts(files.First, ".vxl")); VxlReader vxl;
var hva = new HvaReader(GlobalFileSystem.OpenWithExts(files.Second, ".hva")); HvaReader hva;
using (var s = GlobalFileSystem.OpenWithExts(files.First, ".vxl"))
vxl = new VxlReader(s);
using (var s = GlobalFileSystem.OpenWithExts(files.Second, ".hva"))
hva = new HvaReader(s);
return new Voxel(this, vxl, hva); return new Voxel(this, vxl, hva);
} }

View File

@@ -34,7 +34,7 @@ namespace OpenRA
public enum BlendMode { None, Alpha, Additive, Subtractive, Multiply } public enum BlendMode { None, Alpha, Additive, Subtractive, Multiply }
public interface IGraphicsDevice public interface IGraphicsDevice : IDisposable
{ {
IVertexBuffer<Vertex> CreateVertexBuffer(int length); IVertexBuffer<Vertex> CreateVertexBuffer(int length);
ITexture CreateTexture(Bitmap bitmap); ITexture CreateTexture(Bitmap bitmap);
@@ -58,8 +58,6 @@ namespace OpenRA
void DisableDepthBuffer(); void DisableDepthBuffer();
void SetBlendMode(BlendMode mode); void SetBlendMode(BlendMode mode);
void Quit();
} }
public interface IVertexBuffer<T> public interface IVertexBuffer<T>

View File

@@ -93,8 +93,9 @@ namespace OpenRA
List<string> extracted = new List<string>(); List<string> extracted = new List<string>();
try try
{ {
var z = new ZipInputStream(File.OpenRead(zipFile)); using (var stream = File.OpenRead(zipFile))
z.ExtractZip(dest, extracted, s => onProgress("Extracting " + s)); using (var z = new ZipInputStream(stream))
z.ExtractZip(dest, extracted, s => onProgress("Extracting " + s));
} }
catch (SharpZipBaseException) catch (SharpZipBaseException)
{ {

View File

@@ -172,13 +172,11 @@ namespace OpenRA
public static List<MiniYamlNode> FromFileInPackage(string path) public static List<MiniYamlNode> FromFileInPackage(string path)
{ {
StreamReader reader = new StreamReader(GlobalFileSystem.Open(path));
List<string> lines = new List<string>(); List<string> lines = new List<string>();
using (var stream = GlobalFileSystem.Open(path))
while (!reader.EndOfStream) using (var reader = new StreamReader(stream))
lines.Add(reader.ReadLine()); while (!reader.EndOfStream)
reader.Close(); lines.Add(reader.ReadLine());
return FromLines(lines.ToArray(), path); return FromLines(lines.ToArray(), path);
} }

View File

@@ -86,7 +86,7 @@ namespace OpenRA.Network
if (packet.Length == 0) if (packet.Length == 0)
throw new NotImplementedException(); throw new NotImplementedException();
lock (this) lock (this)
receivedPackets.Add(new ReceivedPacket { FromClient = LocalClientId, Data = packet } ); receivedPackets.Add(new ReceivedPacket { FromClient = LocalClientId, Data = packet });
} }
public virtual void Receive(Action<int, byte[]> packetFn) public virtual void Receive(Action<int, byte[]> packetFn)
@@ -102,10 +102,16 @@ namespace OpenRA.Network
packetFn(p.FromClient, p.Data); packetFn(p.FromClient, p.Data);
} }
public virtual void Dispose() { } protected virtual void Dispose(bool disposing) { }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
} }
class NetworkConnection : EchoConnection sealed class NetworkConnection : EchoConnection
{ {
TcpClient socket; TcpClient socket;
int clientId; int clientId;
@@ -193,22 +199,27 @@ namespace OpenRA.Network
bool disposed = false; bool disposed = false;
public override void Dispose() protected override void Dispose(bool disposing)
{ {
if (disposed) return; if (disposed)
return;
disposed = true; disposed = true;
GC.SuppressFinalize(this);
t.Abort(); t.Abort();
if (socket != null) if (disposing)
socket.Client.Close(); if (socket != null)
socket.Client.Close();
using (new PerfSample("Thread.Join")) using (new PerfSample("Thread.Join"))
{ {
if (!t.Join(1000)) if (!t.Join(1000))
return; return;
} }
base.Dispose(disposing);
} }
~NetworkConnection() { Dispose(); } ~NetworkConnection()
{
Dispose(false);
}
} }
} }

View File

@@ -15,7 +15,7 @@ using OpenRA.Primitives;
namespace OpenRA.Network namespace OpenRA.Network
{ {
public class OrderManager : IDisposable public sealed class OrderManager : IDisposable
{ {
readonly SyncReport syncReport; readonly SyncReport syncReport;
readonly FrameData frameData = new FrameData(); readonly FrameData frameData = new FrameData();
@@ -197,22 +197,10 @@ namespace OpenRA.Network
++NetFrameNumber; ++NetFrameNumber;
} }
bool disposed;
protected void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
Connection.Dispose();
disposed = true;
}
public void Dispose() public void Dispose()
{ {
Dispose(true); if (Connection != null)
GC.SuppressFinalize(this); Connection.Dispose();
} }
} }
} }

View File

@@ -16,7 +16,7 @@ using OpenRA.Primitives;
namespace OpenRA.Network namespace OpenRA.Network
{ {
public class ReplayConnection : IConnection public sealed class ReplayConnection : IConnection
{ {
class Chunk class Chunk
{ {

View File

@@ -17,7 +17,7 @@ using OpenRA.Widgets;
namespace OpenRA.Network namespace OpenRA.Network
{ {
class ReplayRecorderConnection : IConnection, IDisposable sealed class ReplayRecorderConnection : IConnection
{ {
public ReplayMetadata Metadata; public ReplayMetadata Metadata;
@@ -98,30 +98,24 @@ namespace OpenRA.Network
} }
bool disposed; bool disposed;
protected void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
if (Metadata != null)
{
if (Metadata.GameInfo != null)
Metadata.GameInfo.EndTimeUtc = DateTime.UtcNow;
Metadata.Write(writer);
}
writer.Close();
inner.Dispose();
}
disposed = true;
}
public void Dispose() public void Dispose()
{ {
Dispose(true); if (disposed)
GC.SuppressFinalize(this); return;
disposed = true;
if (Metadata != null)
{
if (Metadata.GameInfo != null)
Metadata.GameInfo.EndTimeUtc = DateTime.UtcNow;
Metadata.Write(writer);
}
if (preStartBuffer != null)
preStartBuffer.Dispose();
writer.Close();
inner.Dispose();
} }
} }
} }

View File

@@ -12,7 +12,7 @@ using System;
namespace OpenRA.Primitives namespace OpenRA.Primitives
{ {
public class DisposableAction : IDisposable public sealed class DisposableAction : IDisposable
{ {
public DisposableAction(Action onDispose, Action onFinalize) public DisposableAction(Action onDispose, Action onFinalize)
{ {
@@ -26,7 +26,8 @@ namespace OpenRA.Primitives
public void Dispose() public void Dispose()
{ {
if (disposed) return; if (disposed)
return;
disposed = true; disposed = true;
onDispose(); onDispose();
GC.SuppressFinalize(this); GC.SuppressFinalize(this);

View File

@@ -81,12 +81,11 @@ namespace OpenRA.Scripting
public ScriptGlobalAttribute(string name) { Name = name; } public ScriptGlobalAttribute(string name) { Name = name; }
} }
public class ScriptContext : IDisposable public sealed class ScriptContext : IDisposable
{ {
public World World { get; private set; } public World World { get; private set; }
public WorldRenderer WorldRenderer { get; private set; } public WorldRenderer WorldRenderer { get; private set; }
bool disposed;
readonly MemoryConstrainedLuaRuntime runtime; readonly MemoryConstrainedLuaRuntime runtime;
readonly LuaFunction tick; readonly LuaFunction tick;
@@ -100,6 +99,8 @@ namespace OpenRA.Scripting
public readonly Cache<ActorInfo, Type[]> ActorCommands; public readonly Cache<ActorInfo, Type[]> ActorCommands;
public readonly Type[] PlayerCommands; public readonly Type[] PlayerCommands;
bool disposed;
public ScriptContext(World world, WorldRenderer worldRenderer, public ScriptContext(World world, WorldRenderer worldRenderer,
IEnumerable<string> scripts) IEnumerable<string> scripts)
{ {
@@ -196,27 +197,13 @@ namespace OpenRA.Scripting
tick.Call().Dispose(); tick.Call().Dispose();
} }
protected void Dispose(bool disposing) public void Dispose()
{ {
if (disposed) if (disposed)
return; return;
if (disposing)
runtime.Dispose();
disposed = true; disposed = true;
} if (runtime != null)
runtime.Dispose();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~ScriptContext()
{
// Dispose unmanaged resources only
Dispose(false);
} }
static Type[] ExtractRequiredTypes(Type t) static Type[] ExtractRequiredTypes(Type t)

View File

@@ -39,9 +39,11 @@ namespace OpenRA
} }
if (filename.ToLowerInvariant().EndsWith("wav")) if (filename.ToLowerInvariant().EndsWith("wav"))
return LoadWave(new WavLoader(GlobalFileSystem.Open(filename))); using (var s = GlobalFileSystem.Open(filename))
return LoadWave(new WavLoader(s));
return LoadSoundRaw(AudLoader.LoadSound(GlobalFileSystem.Open(filename))); using (var s = GlobalFileSystem.Open(filename))
return LoadSoundRaw(AudLoader.LoadSound(s));
} }
static ISoundSource LoadWave(WavLoader wave) static ISoundSource LoadWave(WavLoader wave)

View File

@@ -105,7 +105,7 @@ namespace OpenRA.Support
} }
} }
public class PerfSample : IDisposable public sealed class PerfSample : IDisposable
{ {
readonly Stopwatch sw = Stopwatch.StartNew(); readonly Stopwatch sw = Stopwatch.StartNew();
readonly string Item; readonly string Item;

View File

@@ -16,7 +16,7 @@ using System.Threading;
namespace OpenRA.Support namespace OpenRA.Support
{ {
public class PerfTimer : IDisposable public sealed class PerfTimer : IDisposable
{ {
readonly string name; readonly string name;
readonly float thresholdMs; readonly float thresholdMs;

View File

@@ -57,7 +57,7 @@ namespace OpenRA
if (Game.Settings.Debug.ShowFatalErrorDialog && !Game.Settings.Server.Dedicated) if (Game.Settings.Debug.ShowFatalErrorDialog && !Game.Settings.Server.Dedicated)
{ {
Game.Renderer.Device.Quit(); Game.Renderer.Device.Dispose();
Platform.ShowFatalErrorDialog(); Platform.ShowFatalErrorDialog();
} }
} }

View File

@@ -17,7 +17,7 @@ using OpenRA.Primitives;
namespace OpenRA.Irc namespace OpenRA.Irc
{ {
public class IrcClient : IDisposable public sealed class IrcClient : IDisposable
{ {
public static readonly IrcClient Instance = new IrcClient(); public static readonly IrcClient Instance = new IrcClient();
@@ -252,14 +252,15 @@ namespace OpenRA.Irc
ConnectionState = IrcConnectionState.Disconnecting; ConnectionState = IrcConnectionState.Disconnecting;
OnDisconnecting(); OnDisconnecting();
connection.Close(); if (connection != null)
connection.Close();
ConnectionState = IrcConnectionState.Disconnected; ConnectionState = IrcConnectionState.Disconnected;
OnDisconnect(); OnDisconnect();
LocalUser = null; LocalUser = null;
connection = null; connection = null;
} }
void IDisposable.Dispose() public void Dispose()
{ {
Disconnect(); Disconnect();
} }

View File

@@ -14,7 +14,7 @@ using System.Net.Sockets;
namespace OpenRA.Irc namespace OpenRA.Irc
{ {
public class IrcConnection : IDisposable public sealed class IrcConnection : IDisposable
{ {
TcpClient socket; TcpClient socket;
Stream stream; Stream stream;
@@ -49,14 +49,8 @@ namespace OpenRA.Irc
public void Close() public void Close()
{ {
CloseImpl(); if (disposed)
GC.SuppressFinalize(this); return;
}
void CloseImpl()
{
if (disposed) return;
disposed = true; disposed = true;
if (socket != null) socket.Close(); if (socket != null) socket.Close();
if (stream != null) stream.Close(); if (stream != null) stream.Close();
@@ -64,16 +58,11 @@ namespace OpenRA.Irc
if (reader != null) reader.Close(); if (reader != null) reader.Close();
} }
void IDisposable.Dispose() public void Dispose()
{ {
Close(); Close();
} }
~IrcConnection()
{
CloseImpl();
}
void CheckDisposed() void CheckDisposed()
{ {
if (disposed) if (disposed)

View File

@@ -15,7 +15,7 @@ using OpenRA.Primitives;
namespace OpenRA.Mods.RA.Move namespace OpenRA.Mods.RA.Move
{ {
public class PathSearch : IDisposable public sealed class PathSearch : IDisposable
{ {
World world; World world;
public CellInfo[,] cellInfo; public CellInfo[,] cellInfo;
@@ -291,11 +291,12 @@ namespace OpenRA.Mods.RA.Move
{ {
if (disposed) if (disposed)
return; return;
disposed = true; disposed = true;
GC.SuppressFinalize(this);
PutBackIntoPool(cellInfo); PutBackIntoPool(cellInfo);
cellInfo = null; cellInfo = null;
GC.SuppressFinalize(this);
} }
~PathSearch() { Dispose(); } ~PathSearch() { Dispose(); }

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities namespace OpenRA.Mods.RA.Activities
{ {
public class CallLuaFunc : Activity, IDisposable public sealed class CallLuaFunc : Activity, IDisposable
{ {
LuaFunction function; LuaFunction function;
@@ -39,28 +39,11 @@ namespace OpenRA.Mods.RA.Activities
base.Cancel(self); base.Cancel(self);
} }
protected void Dispose(bool disposing)
{
if (function == null)
return;
if (disposing)
{
function.Dispose();
function = null;
}
}
public void Dispose() public void Dispose()
{ {
Dispose(true); if (function == null) return;
GC.SuppressFinalize(this); function.Dispose();
} function = null;
~CallLuaFunc()
{
// Dispose unmanaged resources only
Dispose(false);
} }
} }
} }

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using System;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Scripting; using OpenRA.Scripting;
using OpenRA.Traits; using OpenRA.Traits;
@@ -21,7 +22,7 @@ namespace OpenRA.Mods.RA.Scripting
public object Create(ActorInitializer init) { return new LuaScript(this); } public object Create(ActorInitializer init) { return new LuaScript(this); }
} }
public class LuaScript : ITick, IWorldLoaded public sealed class LuaScript : ITick, IWorldLoaded, IDisposable
{ {
readonly LuaScriptInfo info; readonly LuaScriptInfo info;
ScriptContext context; ScriptContext context;
@@ -42,5 +43,11 @@ namespace OpenRA.Mods.RA.Scripting
{ {
context.Tick(self); context.Tick(self);
} }
public void Dispose()
{
if (context != null)
context.Dispose();
}
} }
} }

View File

@@ -18,7 +18,7 @@ using OpenRA.Primitives;
namespace OpenRA.Mods.RA.Scripting namespace OpenRA.Mods.RA.Scripting
{ {
public class LuaScriptContext : IDisposable public sealed class LuaScriptContext : IDisposable
{ {
public Lua Lua { get; private set; } public Lua Lua { get; private set; }
readonly Cache<string, LuaFunction> functionCache; readonly Cache<string, LuaFunction> functionCache;
@@ -133,19 +133,9 @@ namespace OpenRA.Mods.RA.Scripting
} }
public void Dispose() public void Dispose()
{
if (Lua == null)
return;
GC.SuppressFinalize(this);
Lua.Dispose();
Lua = null;
}
~LuaScriptContext()
{ {
if (Lua != null) if (Lua != null)
Game.RunAfterTick(Dispose); Lua.Dispose();
} }
} }
} }

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Mods.RA.Scripting
public object Create(ActorInitializer init) { return new LuaScriptInterface(this); } public object Create(ActorInitializer init) { return new LuaScriptInterface(this); }
} }
public class LuaScriptInterface : IWorldLoaded, ITick public sealed class LuaScriptInterface : IWorldLoaded, ITick, IDisposable
{ {
World world; World world;
SpawnMapActors sma; SpawnMapActors sma;
@@ -90,6 +90,11 @@ namespace OpenRA.Mods.RA.Scripting
context.InvokeLuaFunction("Tick"); context.InvokeLuaFunction("Tick");
} }
public void Dispose()
{
context.Dispose();
}
[LuaGlobal] [LuaGlobal]
public object New(string typeName, LuaTable args) public object New(string typeName, LuaTable args)
{ {

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.RA.Scripting
[Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")] [Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")]
public class ScriptTriggersInfo : TraitInfo<ScriptTriggers> { } public class ScriptTriggersInfo : TraitInfo<ScriptTriggers> { }
public class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, IDisposable public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, IDisposable
{ {
public event Action<Actor> OnKilledInternal = _ => {}; public event Action<Actor> OnKilledInternal = _ => {};
@@ -100,37 +100,11 @@ namespace OpenRA.Mods.RA.Scripting
} }
} }
bool disposed;
protected void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
var toDispose = new [] { onIdle, onDamaged, onKilled, onProduction };
foreach (var f in toDispose.SelectMany(f => f))
f.First.Dispose();
foreach (var l in toDispose)
l.Clear();
}
disposed = true;
}
public void Dispose() public void Dispose()
{ {
Dispose(true); var pairs = new[] { onIdle, onDamaged, onKilled, onProduction };
GC.SuppressFinalize(this); pairs.SelectMany(l => l).Select(p => p.First).Do(f => f.Dispose());
} pairs.Do(l => l.Clear());
~ScriptTriggers()
{
// Dispose unmanaged resources only
Dispose(false);
} }
} }
} }

View File

@@ -18,7 +18,6 @@ namespace OpenRA.Mods.RA.Widgets
{ {
public class HueSliderWidget : SliderWidget public class HueSliderWidget : SliderWidget
{ {
Bitmap hueBitmap;
Sprite hueSprite; Sprite hueSprite;
public HueSliderWidget() {} public HueSliderWidget() {}
@@ -28,20 +27,22 @@ namespace OpenRA.Mods.RA.Widgets
{ {
base.Initialize(args); base.Initialize(args);
hueBitmap = new Bitmap(256, 256); using (var hueBitmap = new Bitmap(256, 256))
hueSprite = new Sprite(new Sheet(new Size(256, 256)), new Rectangle(0, 0, 256, 1), TextureChannel.Alpha);
var bitmapData = hueBitmap.LockBits(hueBitmap.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{ {
int* c = (int*)bitmapData.Scan0; hueSprite = new Sprite(new Sheet(new Size(256, 256)), new Rectangle(0, 0, 256, 1), TextureChannel.Alpha);
for (var h = 0; h < 256; h++)
*(c + h) = HSLColor.FromHSV(h/255f, 1, 1).RGB.ToArgb();
}
hueBitmap.UnlockBits(bitmapData);
hueSprite.sheet.Texture.SetData(hueBitmap); var bitmapData = hueBitmap.LockBits(hueBitmap.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
int* c = (int*)bitmapData.Scan0;
for (var h = 0; h < 256; h++)
*(c + h) = HSLColor.FromHSV(h / 255f, 1, 1).RGB.ToArgb();
}
hueBitmap.UnlockBits(bitmapData);
hueSprite.sheet.Texture.SetData(hueBitmap);
}
} }
public override void Draw() public override void Draw()

View File

@@ -68,16 +68,18 @@ namespace OpenRA.Mods.RA.Widgets
mapRect = new Rectangle(previewOrigin.X, previewOrigin.Y, (int)(previewScale * width), (int)(previewScale * height)); mapRect = new Rectangle(previewOrigin.X, previewOrigin.Y, (int)(previewScale * width), (int)(previewScale * height));
// Only needs to be done once // Only needs to be done once
var terrainBitmap = Minimap.TerrainBitmap(world.Map.Rules.TileSets[world.Map.Tileset], world.Map); using (var terrainBitmap = Minimap.TerrainBitmap(world.Map.Rules.TileSets[world.Map.Tileset], world.Map))
var r = new Rectangle(0, 0, width, height); {
var s = new Size(terrainBitmap.Width, terrainBitmap.Height); var r = new Rectangle(0, 0, width, height);
terrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha); var s = new Size(terrainBitmap.Width, terrainBitmap.Height);
terrainSprite.sheet.Texture.SetData(terrainBitmap); terrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
terrainSprite.sheet.Texture.SetData(terrainBitmap);
// Data is set in Tick() // Data is set in Tick()
customTerrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha); customTerrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
actorSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha); actorSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
shroudSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha); shroudSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
}
} }
public override string GetCursor(int2 pos) public override string GetCursor(int2 pos)
@@ -197,14 +199,17 @@ namespace OpenRA.Mods.RA.Widgets
if (updateTicks <= 0) if (updateTicks <= 0)
{ {
updateTicks = 12; updateTicks = 12;
customTerrainSprite.sheet.Texture.SetData(Minimap.CustomTerrainBitmap(world)); using (var bitmap = Minimap.CustomTerrainBitmap(world))
customTerrainSprite.sheet.Texture.SetData(bitmap);
} }
if (updateTicks == 8) if (updateTicks == 8)
actorSprite.sheet.Texture.SetData(Minimap.ActorsBitmap(world)); using (var bitmap = Minimap.ActorsBitmap(world))
actorSprite.sheet.Texture.SetData(bitmap);
if (updateTicks == 4) if (updateTicks == 4)
shroudSprite.sheet.Texture.SetData(Minimap.ShroudBitmap(world)); using (var bitmap = Minimap.ShroudBitmap(world))
shroudSprite.sheet.Texture.SetData(bitmap);
// Enable/Disable the radar // Enable/Disable the radar
var enabled = IsEnabled(); var enabled = IsEnabled();

View File

@@ -25,7 +25,7 @@ namespace OpenRA.Renderer.Null
} }
} }
public class NullGraphicsDevice : IGraphicsDevice public sealed class NullGraphicsDevice : IGraphicsDevice
{ {
public Size WindowSize { get; internal set; } public Size WindowSize { get; internal set; }
@@ -35,7 +35,7 @@ namespace OpenRA.Renderer.Null
WindowSize = size; WindowSize = size;
} }
public void Quit() { } public void Dispose() { }
public void EnableScissor(int left, int top, int width, int height) { } public void EnableScissor(int left, int top, int width, int height) { }
public void DisableScissor() { } public void DisableScissor() { }

View File

@@ -29,11 +29,12 @@ namespace OpenRA.Renderer.Sdl2
} }
} }
public class Sdl2GraphicsDevice : IGraphicsDevice public sealed class Sdl2GraphicsDevice : IGraphicsDevice
{ {
Size size; Size size;
Sdl2Input input; Sdl2Input input;
IntPtr context, window; IntPtr context, window;
bool disposed;
public Size WindowSize { get { return size; } } public Size WindowSize { get { return size; } }
@@ -101,10 +102,21 @@ namespace OpenRA.Renderer.Sdl2
input = new Sdl2Input(); input = new Sdl2Input();
} }
public virtual void Quit() public void Dispose()
{ {
SDL.SDL_GL_DeleteContext(context); if (disposed)
SDL.SDL_DestroyWindow(window); return;
disposed = true;
if (context != IntPtr.Zero)
{
SDL.SDL_GL_DeleteContext(context);
context = IntPtr.Zero;
}
if (window != IntPtr.Zero)
{
SDL.SDL_DestroyWindow(window);
window = IntPtr.Zero;
}
SDL.SDL_Quit(); SDL.SDL_Quit();
} }

View File

@@ -106,18 +106,29 @@ namespace OpenRA.Renderer.Sdl2
public void SetData(Bitmap bitmap) public void SetData(Bitmap bitmap)
{ {
bool allocatedBitmap = false;
if (!Exts.IsPowerOf2(bitmap.Width) || !Exts.IsPowerOf2(bitmap.Height)) if (!Exts.IsPowerOf2(bitmap.Width) || !Exts.IsPowerOf2(bitmap.Height))
{
bitmap = new Bitmap(bitmap, bitmap.Size.NextPowerOf2()); bitmap = new Bitmap(bitmap, bitmap.Size.NextPowerOf2());
allocatedBitmap = true;
}
try
{
size = new Size(bitmap.Width, bitmap.Height);
var bits = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
size = new Size(bitmap.Width, bitmap.Height); PrepareTexture();
var bits = bitmap.LockBits(bitmap.Bounds(), GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, bits.Width, bits.Height,
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bits.Scan0); // TODO: weird strides
ErrorHandler.CheckGlError();
PrepareTexture(); bitmap.UnlockBits(bits);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, bits.Width, bits.Height, }
0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bits.Scan0); // TODO: weird strides finally
ErrorHandler.CheckGlError(); {
bitmap.UnlockBits(bits); if (allocatedBitmap)
bitmap.Dispose();
}
} }
public byte[] GetData() public byte[] GetData()

View File

@@ -51,8 +51,9 @@ namespace OpenRA.TilesetBuilder
this.size = TileSize; this.size = TileSize;
surface1.TileSize = TileSize; surface1.TileSize = TileSize;
Bitmap fbitmap = new Bitmap(ImageFile); Bitmap rbitmap;
Bitmap rbitmap = fbitmap.Clone(new Rectangle(0, 0, fbitmap.Width, fbitmap.Height), using (var fbitmap = new Bitmap(ImageFile))
rbitmap = fbitmap.Clone(new Rectangle(0, 0, fbitmap.Width, fbitmap.Height),
fbitmap.PixelFormat); fbitmap.PixelFormat);
int[] shadowIndex = { }; int[] shadowIndex = { };

View File

@@ -162,7 +162,8 @@ namespace OpenRA.Utility
else else
{ {
// CnC // CnC
UnpackCncTileData(GlobalFileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin")); using (var s = GlobalFileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin"))
UnpackCncTileData(s);
ReadCncOverlay(file); ReadCncOverlay(file);
ReadCncTrees(file); ReadCncTrees(file);
} }