Merge pull request #6830 from RoosterDragon/dispose-renderer-resources
Closes #5116
This commit is contained in:
@@ -46,6 +46,7 @@ namespace OpenRA.Editor
|
|||||||
miniMapBox.Image = null;
|
miniMapBox.Image = null;
|
||||||
currentMod = toolStripComboBox1.SelectedItem as string;
|
currentMod = toolStripComboBox1.SelectedItem as string;
|
||||||
|
|
||||||
|
Game.InitializeSettings(Arguments.Empty);
|
||||||
Game.modData = new ModData(currentMod);
|
Game.modData = new ModData(currentMod);
|
||||||
GlobalFileSystem.LoadFromManifest(Game.modData.Manifest);
|
GlobalFileSystem.LoadFromManifest(Game.modData.Manifest);
|
||||||
Program.Rules = Game.modData.RulesetCache.LoadDefaultRules();
|
Program.Rules = Game.modData.RulesetCache.LoadDefaultRules();
|
||||||
@@ -203,10 +204,10 @@ namespace OpenRA.Editor
|
|||||||
Height = bitmap.Height / 2,
|
Height = bitmap.Height / 2,
|
||||||
SizeMode = PictureBoxSizeMode.StretchImage
|
SizeMode = PictureBoxSizeMode.StretchImage
|
||||||
};
|
};
|
||||||
|
|
||||||
var brushTemplate = new BrushTemplate { Bitmap = bitmap, N = t.Key };
|
var brushTemplate = new BrushTemplate { Bitmap = bitmap, N = t.Key };
|
||||||
ibox.Click += (_, e) => surface1.SetTool(new BrushTool(brushTemplate));
|
ibox.Click += (_, e) => surface1.SetTool(new BrushTool(brushTemplate));
|
||||||
|
|
||||||
var template = t.Value;
|
var template = t.Value;
|
||||||
tilePalette.Controls.Add(ibox);
|
tilePalette.Controls.Add(ibox);
|
||||||
tt.SetToolTip(ibox, "{1}:{0} ({2}x{3})".F(template.Image, template.Id, template.Size.X, template.Size.Y));
|
tt.SetToolTip(ibox, "{1}:{0} ({2}x{3})".F(template.Image, template.Id, template.Size.X, template.Size.Y));
|
||||||
@@ -463,7 +464,7 @@ namespace OpenRA.Editor
|
|||||||
void ExportMinimap(object sender, EventArgs e)
|
void ExportMinimap(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
using (var sfd = new SaveFileDialog()
|
using (var sfd = new SaveFileDialog()
|
||||||
{
|
{
|
||||||
InitialDirectory = Path.Combine(Environment.CurrentDirectory, "maps"),
|
InitialDirectory = Path.Combine(Environment.CurrentDirectory, "maps"),
|
||||||
DefaultExt = "*.png",
|
DefaultExt = "*.png",
|
||||||
Filter = "PNG Image (*.png)|*.png",
|
Filter = "PNG Image (*.png)|*.png",
|
||||||
@@ -471,9 +472,8 @@ namespace OpenRA.Editor
|
|||||||
FileName = Path.ChangeExtension(loadedMapName, ".png"),
|
FileName = Path.ChangeExtension(loadedMapName, ".png"),
|
||||||
RestoreDirectory = true
|
RestoreDirectory = true
|
||||||
})
|
})
|
||||||
|
if (DialogResult.OK == sfd.ShowDialog())
|
||||||
if (DialogResult.OK == sfd.ShowDialog())
|
miniMapBox.Image.Save(sfd.FileName);
|
||||||
miniMapBox.Image.Save(sfd.FileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowActorNamesClicked(object sender, EventArgs e)
|
void ShowActorNamesClicked(object sender, EventArgs e)
|
||||||
@@ -637,7 +637,7 @@ namespace OpenRA.Editor
|
|||||||
{
|
{
|
||||||
ShowGridClicked(sender, e);
|
ShowGridClicked(sender, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateTotalResource()
|
public int CalculateTotalResource()
|
||||||
{
|
{
|
||||||
var totalResource = 0;
|
var totalResource = 0;
|
||||||
@@ -651,7 +651,7 @@ namespace OpenRA.Editor
|
|||||||
|
|
||||||
return totalResource;
|
return totalResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetAdjecentCellsWith(int resourceType, int x, int y)
|
int GetAdjecentCellsWith(int resourceType, int x, int y)
|
||||||
{
|
{
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
|
|||||||
@@ -140,7 +140,10 @@ namespace OpenRA
|
|||||||
orderManager.World = new World(map, orderManager, isShellmap);
|
orderManager.World = new World(map, orderManager, isShellmap);
|
||||||
orderManager.World.Timestep = Timestep;
|
orderManager.World.Timestep = Timestep;
|
||||||
}
|
}
|
||||||
|
if (worldRenderer != null)
|
||||||
|
worldRenderer.Dispose();
|
||||||
worldRenderer = new WorldRenderer(orderManager.World);
|
worldRenderer = new WorldRenderer(orderManager.World);
|
||||||
|
|
||||||
using (new PerfTimer("LoadComplete"))
|
using (new PerfTimer("LoadComplete"))
|
||||||
orderManager.World.LoadComplete(worldRenderer);
|
orderManager.World.LoadComplete(worldRenderer);
|
||||||
|
|
||||||
@@ -172,13 +175,18 @@ namespace OpenRA
|
|||||||
public static Modifiers GetModifierKeys() { return modifiers; }
|
public static Modifiers GetModifierKeys() { return modifiers; }
|
||||||
internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
|
internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
|
||||||
|
|
||||||
|
public static void InitializeSettings(Arguments args)
|
||||||
|
{
|
||||||
|
Settings = new Settings(Platform.ResolvePath("^", "settings.yaml"), args);
|
||||||
|
}
|
||||||
|
|
||||||
internal static void Initialize(Arguments args)
|
internal static void Initialize(Arguments args)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);
|
Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);
|
||||||
|
|
||||||
AppDomain.CurrentDomain.AssemblyResolve += GlobalFileSystem.ResolveAssembly;
|
AppDomain.CurrentDomain.AssemblyResolve += GlobalFileSystem.ResolveAssembly;
|
||||||
|
|
||||||
Settings = new Settings(Platform.ResolvePath("^", "settings.yaml"), args);
|
InitializeSettings(args);
|
||||||
|
|
||||||
Log.AddChannel("perf", "perf.log");
|
Log.AddChannel("perf", "perf.log");
|
||||||
Log.AddChannel("debug", "debug.log");
|
Log.AddChannel("debug", "debug.log");
|
||||||
@@ -215,7 +223,7 @@ namespace OpenRA
|
|||||||
Settings.Graphics.Renderer = r;
|
Settings.Graphics.Renderer = r;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Renderer.Initialize(Settings.Graphics.Mode);
|
Renderer = new Renderer(Settings.Graphics, Settings.Server);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -225,8 +233,6 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer = new Renderer();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Sound.Create(Settings.Sound.Engine);
|
Sound.Create(Settings.Sound.Engine);
|
||||||
@@ -257,12 +263,18 @@ namespace OpenRA
|
|||||||
BeforeGameStart = () => { };
|
BeforeGameStart = () => { };
|
||||||
Ui.ResetAll();
|
Ui.ResetAll();
|
||||||
|
|
||||||
|
if (worldRenderer != null)
|
||||||
|
worldRenderer.Dispose();
|
||||||
worldRenderer = null;
|
worldRenderer = null;
|
||||||
if (server != null)
|
if (server != null)
|
||||||
server.Shutdown();
|
server.Shutdown();
|
||||||
if (orderManager != null)
|
if (orderManager != null)
|
||||||
orderManager.Dispose();
|
orderManager.Dispose();
|
||||||
|
|
||||||
|
if (modData != null)
|
||||||
|
modData.Dispose();
|
||||||
|
modData = null;
|
||||||
|
|
||||||
// Fall back to default if the mod doesn't exist
|
// Fall back to default if the mod doesn't exist
|
||||||
if (!ModMetadata.AllMods.ContainsKey(mod))
|
if (!ModMetadata.AllMods.ContainsKey(mod))
|
||||||
mod = new GameSettings().Mod;
|
mod = new GameSettings().Mod;
|
||||||
@@ -274,7 +286,7 @@ namespace OpenRA
|
|||||||
Sound.StopVideo();
|
Sound.StopVideo();
|
||||||
Sound.Initialize();
|
Sound.Initialize();
|
||||||
|
|
||||||
modData = new ModData(mod);
|
modData = new ModData(mod, true);
|
||||||
Renderer.InitializeFonts(modData.Manifest);
|
Renderer.InitializeFonts(modData.Manifest);
|
||||||
modData.InitializeLoaders();
|
modData.InitializeLoaders();
|
||||||
using (new PerfTimer("LoadMaps"))
|
using (new PerfTimer("LoadMaps"))
|
||||||
@@ -632,8 +644,12 @@ namespace OpenRA
|
|||||||
if (orderManager != null)
|
if (orderManager != null)
|
||||||
orderManager.Dispose();
|
orderManager.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer.Device.Dispose();
|
if (worldRenderer != null)
|
||||||
|
worldRenderer.Dispose();
|
||||||
|
modData.Dispose();
|
||||||
|
ChromeProvider.Deinitialize();
|
||||||
|
Renderer.Dispose();
|
||||||
|
|
||||||
OnQuit();
|
OnQuit();
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ using OpenRA.Support;
|
|||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
{
|
{
|
||||||
public class RulesetCache
|
public sealed class RulesetCache : IDisposable
|
||||||
{
|
{
|
||||||
readonly ModData modData;
|
readonly ModData modData;
|
||||||
|
|
||||||
@@ -137,5 +137,12 @@ namespace OpenRA
|
|||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var cache in sequenceCaches.Values)
|
||||||
|
cache.Dispose();
|
||||||
|
sequenceCaches.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
struct Collection
|
struct Collection
|
||||||
{
|
{
|
||||||
public string src;
|
public string Src;
|
||||||
public Dictionary<string, MappedImage> regions;
|
public Dictionary<string, MappedImage> Regions;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Dictionary<string, Collection> collections;
|
static Dictionary<string, Collection> collections;
|
||||||
@@ -27,6 +27,8 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public static void Initialize(IEnumerable<string> chromeFiles)
|
public static void Initialize(IEnumerable<string> chromeFiles)
|
||||||
{
|
{
|
||||||
|
Deinitialize();
|
||||||
|
|
||||||
collections = new Dictionary<string, Collection>();
|
collections = new Dictionary<string, Collection>();
|
||||||
cachedSheets = new Dictionary<string, Sheet>();
|
cachedSheets = new Dictionary<string, Sheet>();
|
||||||
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
|
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
|
||||||
@@ -37,6 +39,17 @@ namespace OpenRA.Graphics
|
|||||||
LoadCollection(c.Key, c.Value);
|
LoadCollection(c.Key, c.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Deinitialize()
|
||||||
|
{
|
||||||
|
if (cachedSheets != null)
|
||||||
|
foreach (var sheet in cachedSheets.Values)
|
||||||
|
sheet.Dispose();
|
||||||
|
|
||||||
|
collections = null;
|
||||||
|
cachedSheets = null;
|
||||||
|
cachedSprites = null;
|
||||||
|
}
|
||||||
|
|
||||||
public static void Save(string file)
|
public static void Save(string file)
|
||||||
{
|
{
|
||||||
var root = new List<MiniYamlNode>();
|
var root = new List<MiniYamlNode>();
|
||||||
@@ -49,10 +62,10 @@ namespace OpenRA.Graphics
|
|||||||
static MiniYaml SaveCollection(Collection collection)
|
static MiniYaml SaveCollection(Collection collection)
|
||||||
{
|
{
|
||||||
var root = new List<MiniYamlNode>();
|
var root = new List<MiniYamlNode>();
|
||||||
foreach (var kv in collection.regions)
|
foreach (var kv in collection.Regions)
|
||||||
root.Add(new MiniYamlNode(kv.Key, kv.Value.Save(collection.src)));
|
root.Add(new MiniYamlNode(kv.Key, kv.Value.Save(collection.Src)));
|
||||||
|
|
||||||
return new MiniYaml(collection.src, root);
|
return new MiniYaml(collection.Src, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadCollection(string name, MiniYaml yaml)
|
static void LoadCollection(string name, MiniYaml yaml)
|
||||||
@@ -60,8 +73,8 @@ namespace OpenRA.Graphics
|
|||||||
Game.modData.LoadScreen.Display();
|
Game.modData.LoadScreen.Display();
|
||||||
var collection = new Collection()
|
var collection = new Collection()
|
||||||
{
|
{
|
||||||
src = yaml.Value,
|
Src = yaml.Value,
|
||||||
regions = yaml.Nodes.ToDictionary(n => n.Key, n => new MappedImage(yaml.Value, n.Value))
|
Regions = yaml.Nodes.ToDictionary(n => n.Key, n => new MappedImage(yaml.Value, n.Value))
|
||||||
};
|
};
|
||||||
|
|
||||||
collections.Add(name, collection);
|
collections.Add(name, collection);
|
||||||
@@ -83,7 +96,7 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
|
|
||||||
MappedImage mi;
|
MappedImage mi;
|
||||||
if (!collection.regions.TryGetValue(imageName, out mi))
|
if (!collection.Regions.TryGetValue(imageName, out mi))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Cached sheet
|
// Cached sheet
|
||||||
@@ -102,6 +115,7 @@ namespace OpenRA.Graphics
|
|||||||
cachedCollection = new Dictionary<string, Sprite>();
|
cachedCollection = new Dictionary<string, Sprite>();
|
||||||
cachedSprites.Add(collectionName, cachedCollection);
|
cachedSprites.Add(collectionName, cachedCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
var image = mi.GetImage(sheet);
|
var image = mi.GetImage(sheet);
|
||||||
cachedCollection.Add(imageName, image);
|
cachedCollection.Add(imageName, image);
|
||||||
|
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ using OpenRA.Primitives;
|
|||||||
|
|
||||||
namespace OpenRA.Graphics
|
namespace OpenRA.Graphics
|
||||||
{
|
{
|
||||||
public class CursorProvider
|
public sealed class CursorProvider : IDisposable
|
||||||
{
|
{
|
||||||
HardwarePalette palette;
|
readonly HardwarePalette palette = new HardwarePalette();
|
||||||
Dictionary<string, CursorSequence> cursors;
|
readonly Dictionary<string, CursorSequence> cursors = new Dictionary<string, CursorSequence>();
|
||||||
Cache<string, PaletteReference> palettes;
|
readonly Cache<string, PaletteReference> palettes;
|
||||||
|
readonly SheetBuilder sheetBuilder;
|
||||||
|
|
||||||
public static bool CursorViewportZoomed { get { return Game.Settings.Graphics.CursorDouble && Game.Settings.Graphics.PixelDouble; } }
|
public static bool CursorViewportZoomed { get { return Game.Settings.Graphics.CursorDouble && Game.Settings.Graphics.PixelDouble; } }
|
||||||
|
|
||||||
@@ -28,7 +29,6 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
var sequenceFiles = modData.Manifest.Cursors;
|
var sequenceFiles = modData.Manifest.Cursors;
|
||||||
|
|
||||||
cursors = new Dictionary<string, CursorSequence>();
|
|
||||||
palettes = new Cache<string, PaletteReference>(CreatePaletteReference);
|
palettes = new Cache<string, PaletteReference>(CreatePaletteReference);
|
||||||
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
|
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
|
||||||
var shadowIndex = new int[] { };
|
var shadowIndex = new int[] { };
|
||||||
@@ -41,14 +41,14 @@ namespace OpenRA.Graphics
|
|||||||
out shadowIndex[shadowIndex.Length - 1]);
|
out shadowIndex[shadowIndex.Length - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
palette = new HardwarePalette();
|
|
||||||
foreach (var p in nodesDict["Palettes"].Nodes)
|
foreach (var p in nodesDict["Palettes"].Nodes)
|
||||||
palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
|
palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
|
||||||
|
|
||||||
var spriteCache = new SpriteCache(modData.SpriteLoaders, new string[0], new SheetBuilder(SheetType.Indexed));
|
sheetBuilder = new SheetBuilder(SheetType.Indexed);
|
||||||
|
var spriteCache = new SpriteCache(modData.SpriteLoaders, new string[0], sheetBuilder);
|
||||||
foreach (var s in nodesDict["Cursors"].Nodes)
|
foreach (var s in nodesDict["Cursors"].Nodes)
|
||||||
LoadSequencesForCursor(spriteCache, s.Key, s.Value);
|
LoadSequencesForCursor(spriteCache, s.Key, s.Value);
|
||||||
spriteCache.SheetBuilder.Current.ReleaseBuffer();
|
sheetBuilder.Current.ReleaseBuffer();
|
||||||
|
|
||||||
palette.Initialize();
|
palette.Initialize();
|
||||||
}
|
}
|
||||||
@@ -95,5 +95,11 @@ namespace OpenRA.Graphics
|
|||||||
throw new InvalidOperationException("Cursor does not have a sequence `{0}`".F(cursor));
|
throw new InvalidOperationException("Cursor does not have a sequence `{0}`".F(cursor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
palette.Dispose();
|
||||||
|
sheetBuilder.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Graphics
|
namespace OpenRA.Graphics
|
||||||
{
|
{
|
||||||
public class HardwarePalette
|
public sealed class HardwarePalette : IDisposable
|
||||||
{
|
{
|
||||||
public const int MaxPalettes = 256;
|
public const int MaxPalettes = 256;
|
||||||
|
|
||||||
@@ -111,5 +111,10 @@ namespace OpenRA.Graphics
|
|||||||
modifiedPalette.SetFromPalette(originalPalette);
|
modifiedPalette.SetFromPalette(originalPalette);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Texture.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace OpenRA
|
|||||||
void ReleaseWindowMouseFocus();
|
void ReleaseWindowMouseFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IVertexBuffer<T>
|
public interface IVertexBuffer<T> : IDisposable
|
||||||
{
|
{
|
||||||
void Bind();
|
void Bind();
|
||||||
void SetData(T[] vertices, int length);
|
void SetData(T[] vertices, int length);
|
||||||
@@ -80,7 +80,8 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum TextureScaleFilter { Nearest, Linear }
|
public enum TextureScaleFilter { Nearest, Linear }
|
||||||
public interface ITexture
|
|
||||||
|
public interface ITexture : IDisposable
|
||||||
{
|
{
|
||||||
void SetData(Bitmap bitmap);
|
void SetData(Bitmap bitmap);
|
||||||
void SetData(uint[,] colors);
|
void SetData(uint[,] colors);
|
||||||
@@ -90,7 +91,7 @@ namespace OpenRA
|
|||||||
TextureScaleFilter ScaleFilter { get; set; }
|
TextureScaleFilter ScaleFilter { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IFrameBuffer
|
public interface IFrameBuffer : IDisposable
|
||||||
{
|
{
|
||||||
void Bind();
|
void Bind();
|
||||||
void Unbind();
|
void Unbind();
|
||||||
|
|||||||
@@ -15,24 +15,29 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
public class LineRenderer : Renderer.IBatchRenderer
|
public class LineRenderer : Renderer.IBatchRenderer
|
||||||
{
|
{
|
||||||
static float2 offset = new float2(0.5f, 0.5f);
|
static readonly float2 Offset = new float2(0.5f, 0.5f);
|
||||||
float lineWidth = 1f;
|
|
||||||
Renderer renderer;
|
|
||||||
IShader shader;
|
|
||||||
|
|
||||||
Vertex[] vertices = new Vertex[Renderer.TempBufferSize];
|
readonly Renderer renderer;
|
||||||
|
readonly IShader shader;
|
||||||
|
|
||||||
|
readonly Vertex[] vertices;
|
||||||
int nv = 0;
|
int nv = 0;
|
||||||
|
|
||||||
|
float lineWidth = 1f;
|
||||||
|
|
||||||
public LineRenderer(Renderer renderer, IShader shader)
|
public LineRenderer(Renderer renderer, IShader shader)
|
||||||
{
|
{
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
this.shader = shader;
|
this.shader = shader;
|
||||||
|
vertices = new Vertex[renderer.TempBufferSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public float LineWidth
|
public float LineWidth
|
||||||
{
|
{
|
||||||
get { return lineWidth; }
|
get
|
||||||
|
{
|
||||||
|
return lineWidth;
|
||||||
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (LineWidth != value)
|
if (LineWidth != value)
|
||||||
@@ -71,16 +76,16 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void DrawLine(float2 start, float2 end, Color startColor, Color endColor)
|
public void DrawLine(float2 start, float2 end, Color startColor, Color endColor)
|
||||||
{
|
{
|
||||||
Renderer.CurrentBatchRenderer = this;
|
renderer.CurrentBatchRenderer = this;
|
||||||
|
|
||||||
if (nv + 2 > Renderer.TempBufferSize)
|
if (nv + 2 > renderer.TempBufferSize)
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
vertices[nv++] = new Vertex(start + offset,
|
vertices[nv++] = new Vertex(start + Offset,
|
||||||
startColor.R / 255.0f, startColor.G / 255.0f,
|
startColor.R / 255.0f, startColor.G / 255.0f,
|
||||||
startColor.B / 255.0f, startColor.A / 255.0f);
|
startColor.B / 255.0f, startColor.A / 255.0f);
|
||||||
|
|
||||||
vertices[nv++] = new Vertex(end + offset,
|
vertices[nv++] = new Vertex(end + Offset,
|
||||||
endColor.R / 255.0f, endColor.G / 255.0f,
|
endColor.R / 255.0f, endColor.G / 255.0f,
|
||||||
endColor.B / 255.0f, endColor.A / 255.0f);
|
endColor.B / 255.0f, endColor.A / 255.0f);
|
||||||
}
|
}
|
||||||
@@ -99,7 +104,7 @@ namespace OpenRA.Graphics
|
|||||||
var yc = (r.Bottom + r.Top) / 2;
|
var yc = (r.Bottom + r.Top) / 2;
|
||||||
for (var y = r.Top; y <= r.Bottom; y++)
|
for (var y = r.Top; y <= r.Bottom; y++)
|
||||||
{
|
{
|
||||||
var dx = a * (float)(Math.Sqrt(1 - (y - yc) * (y - yc) / b / b));
|
var dx = a * (float)Math.Sqrt(1 - (y - yc) * (y - yc) / b / b);
|
||||||
DrawLine(new float2(xc - dx, y), new float2(xc + dx, y), color, color);
|
DrawLine(new float2(xc - dx, y), new float2(xc + dx, y), color, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,7 +112,7 @@ namespace OpenRA.Graphics
|
|||||||
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
||||||
{
|
{
|
||||||
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
||||||
shader.SetVec("r1", zoom*2f/screen.Width, -zoom*2f/screen.Height);
|
shader.SetVec("r1", zoom * 2f / screen.Width, -zoom * 2f / screen.Height);
|
||||||
shader.SetVec("r2", -1, 1);
|
shader.SetVec("r2", -1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,8 +203,8 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public static Bitmap RenderMapPreview(TileSet tileset, Map map, Ruleset resourceRules, bool actualSize)
|
public static Bitmap RenderMapPreview(TileSet tileset, Map map, Ruleset resourceRules, bool actualSize)
|
||||||
{
|
{
|
||||||
var terrain = TerrainBitmap(tileset, map, actualSize);
|
using (var terrain = TerrainBitmap(tileset, map, actualSize))
|
||||||
return AddStaticResources(tileset, map, resourceRules, terrain);
|
return AddStaticResources(tileset, map, resourceRules, terrain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,16 +14,17 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
public class QuadRenderer : Renderer.IBatchRenderer
|
public class QuadRenderer : Renderer.IBatchRenderer
|
||||||
{
|
{
|
||||||
Renderer renderer;
|
readonly Renderer renderer;
|
||||||
IShader shader;
|
readonly IShader shader;
|
||||||
|
|
||||||
Vertex[] vertices = new Vertex[Renderer.TempBufferSize];
|
readonly Vertex[] vertices;
|
||||||
int nv = 0;
|
int nv = 0;
|
||||||
|
|
||||||
public QuadRenderer(Renderer renderer, IShader shader)
|
public QuadRenderer(Renderer renderer, IShader shader)
|
||||||
{
|
{
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
this.shader = shader;
|
this.shader = shader;
|
||||||
|
vertices = new Vertex[renderer.TempBufferSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Flush()
|
public void Flush()
|
||||||
@@ -45,9 +46,9 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void FillRect(RectangleF rect, Color color)
|
public void FillRect(RectangleF rect, Color color)
|
||||||
{
|
{
|
||||||
Renderer.CurrentBatchRenderer = this;
|
renderer.CurrentBatchRenderer = this;
|
||||||
|
|
||||||
if (nv + 4 > Renderer.TempBufferSize)
|
if (nv + 4 > renderer.TempBufferSize)
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
var r = color.R / 255.0f;
|
var r = color.R / 255.0f;
|
||||||
@@ -65,7 +66,7 @@ namespace OpenRA.Graphics
|
|||||||
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
||||||
{
|
{
|
||||||
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
||||||
shader.SetVec("r1", zoom*2f/screen.Width, -zoom*2f/screen.Height);
|
shader.SetVec("r1", zoom * 2f / screen.Width, -zoom * 2f / screen.Height);
|
||||||
shader.SetVec("r2", -1, 1);
|
shader.SetVec("r2", -1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,19 +11,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using OpenRA.Support;
|
using OpenRA.Support;
|
||||||
|
|
||||||
namespace OpenRA.Graphics
|
namespace OpenRA.Graphics
|
||||||
{
|
{
|
||||||
public class Renderer
|
public sealed class Renderer : IDisposable
|
||||||
{
|
{
|
||||||
internal static int SheetSize;
|
|
||||||
internal static int TempBufferSize;
|
|
||||||
internal static int TempBufferCount;
|
|
||||||
|
|
||||||
public SpriteRenderer WorldSpriteRenderer { get; private set; }
|
public SpriteRenderer WorldSpriteRenderer { get; private set; }
|
||||||
public SpriteRenderer WorldRgbaSpriteRenderer { get; private set; }
|
public SpriteRenderer WorldRgbaSpriteRenderer { get; private set; }
|
||||||
public QuadRenderer WorldQuadRenderer { get; private set; }
|
public QuadRenderer WorldQuadRenderer { get; private set; }
|
||||||
@@ -32,47 +27,77 @@ namespace OpenRA.Graphics
|
|||||||
public LineRenderer LineRenderer { get; private set; }
|
public LineRenderer LineRenderer { get; private set; }
|
||||||
public SpriteRenderer RgbaSpriteRenderer { get; private set; }
|
public SpriteRenderer RgbaSpriteRenderer { get; private set; }
|
||||||
public SpriteRenderer SpriteRenderer { get; private set; }
|
public SpriteRenderer SpriteRenderer { get; private set; }
|
||||||
|
public IReadOnlyDictionary<string, SpriteFont> Fonts;
|
||||||
|
|
||||||
Queue<IVertexBuffer<Vertex>> tempBuffers = new Queue<IVertexBuffer<Vertex>>();
|
internal IGraphicsDevice Device { get; private set; }
|
||||||
|
internal int SheetSize { get; private set; }
|
||||||
|
internal int TempBufferSize { get; private set; }
|
||||||
|
internal int TempBufferCount { get; private set; }
|
||||||
|
|
||||||
public Dictionary<string, SpriteFont> Fonts;
|
readonly Queue<IVertexBuffer<Vertex>> tempBuffers = new Queue<IVertexBuffer<Vertex>>();
|
||||||
Stack<Rectangle> scissorState;
|
readonly Stack<Rectangle> scissorState = new Stack<Rectangle>();
|
||||||
|
|
||||||
public Renderer()
|
Size? lastResolution;
|
||||||
|
int2? lastScroll;
|
||||||
|
float? lastZoom;
|
||||||
|
ITexture currentPaletteTexture;
|
||||||
|
IBatchRenderer currentBatchRenderer;
|
||||||
|
|
||||||
|
public Renderer(GraphicSettings graphicSettings, ServerSettings serverSettings)
|
||||||
{
|
{
|
||||||
TempBufferSize = Game.Settings.Graphics.BatchSize;
|
var resolution = GetResolution(graphicSettings);
|
||||||
TempBufferCount = Game.Settings.Graphics.NumTempBuffers;
|
|
||||||
SheetSize = Game.Settings.Graphics.SheetSize;
|
|
||||||
scissorState = new Stack<Rectangle>();
|
|
||||||
|
|
||||||
WorldSpriteRenderer = new SpriteRenderer(this, device.CreateShader("shp"));
|
var rendererName = serverSettings.Dedicated ? "Null" : graphicSettings.Renderer;
|
||||||
WorldRgbaSpriteRenderer = new SpriteRenderer(this, device.CreateShader("rgba"));
|
var rendererPath = Platform.ResolvePath(".", "OpenRA.Renderer." + rendererName + ".dll");
|
||||||
WorldLineRenderer = new LineRenderer(this, device.CreateShader("line"));
|
|
||||||
WorldVoxelRenderer = new VoxelRenderer(this, device.CreateShader("vxl"));
|
Device = CreateDevice(Assembly.LoadFile(rendererPath), resolution.Width, resolution.Height, graphicSettings.Mode);
|
||||||
LineRenderer = new LineRenderer(this, device.CreateShader("line"));
|
|
||||||
WorldQuadRenderer = new QuadRenderer(this, device.CreateShader("line"));
|
TempBufferSize = graphicSettings.BatchSize;
|
||||||
RgbaSpriteRenderer = new SpriteRenderer(this, device.CreateShader("rgba"));
|
TempBufferCount = graphicSettings.NumTempBuffers;
|
||||||
SpriteRenderer = new SpriteRenderer(this, device.CreateShader("shp"));
|
SheetSize = graphicSettings.SheetSize;
|
||||||
|
|
||||||
|
WorldSpriteRenderer = new SpriteRenderer(this, Device.CreateShader("shp"));
|
||||||
|
WorldRgbaSpriteRenderer = new SpriteRenderer(this, Device.CreateShader("rgba"));
|
||||||
|
WorldLineRenderer = new LineRenderer(this, Device.CreateShader("line"));
|
||||||
|
WorldVoxelRenderer = new VoxelRenderer(this, Device.CreateShader("vxl"));
|
||||||
|
LineRenderer = new LineRenderer(this, Device.CreateShader("line"));
|
||||||
|
WorldQuadRenderer = new QuadRenderer(this, Device.CreateShader("line"));
|
||||||
|
RgbaSpriteRenderer = new SpriteRenderer(this, Device.CreateShader("rgba"));
|
||||||
|
SpriteRenderer = new SpriteRenderer(this, Device.CreateShader("shp"));
|
||||||
|
|
||||||
for (var i = 0; i < TempBufferCount; i++)
|
for (var i = 0; i < TempBufferCount; i++)
|
||||||
tempBuffers.Enqueue(device.CreateVertexBuffer(TempBufferSize));
|
tempBuffers.Enqueue(Device.CreateVertexBuffer(TempBufferSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Size GetResolution(GraphicSettings graphicsSettings)
|
||||||
|
{
|
||||||
|
var size = (graphicsSettings.Mode == WindowMode.Windowed)
|
||||||
|
? graphicsSettings.WindowedSize
|
||||||
|
: graphicsSettings.FullscreenSize;
|
||||||
|
return new Size(size.X, size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IGraphicsDevice CreateDevice(Assembly rendererDll, int width, int height, WindowMode window)
|
||||||
|
{
|
||||||
|
foreach (RendererAttribute r in rendererDll.GetCustomAttributes(typeof(RendererAttribute), false))
|
||||||
|
{
|
||||||
|
var factory = (IDeviceFactory)r.Type.GetConstructor(Type.EmptyTypes).Invoke(null);
|
||||||
|
return factory.Create(new Size(width, height), window);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Renderer DLL is missing RendererAttribute to tell us what type to use!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitializeFonts(Manifest m)
|
public void InitializeFonts(Manifest m)
|
||||||
{
|
{
|
||||||
using (new Support.PerfTimer("SpriteFonts"))
|
using (new Support.PerfTimer("SpriteFonts"))
|
||||||
Fonts = m.Fonts.ToDictionary(x => x.Key, x => new SpriteFont(Platform.ResolvePath(x.Value.First), x.Value.Second));
|
Fonts = m.Fonts.ToDictionary(x => x.Key,
|
||||||
|
x => new SpriteFont(Platform.ResolvePath(x.Value.First), x.Value.Second)).AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal IGraphicsDevice Device { get { return device; } }
|
|
||||||
|
|
||||||
Size? lastResolution;
|
|
||||||
int2? lastScroll;
|
|
||||||
float? lastZoom;
|
|
||||||
|
|
||||||
public void BeginFrame(int2 scroll, float zoom)
|
public void BeginFrame(int2 scroll, float zoom)
|
||||||
{
|
{
|
||||||
device.Clear();
|
Device.Clear();
|
||||||
|
|
||||||
var resolutionChanged = lastResolution != Resolution;
|
var resolutionChanged = lastResolution != Resolution;
|
||||||
if (resolutionChanged)
|
if (resolutionChanged)
|
||||||
@@ -96,7 +121,6 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ITexture currentPaletteTexture;
|
|
||||||
public void SetPalette(HardwarePalette palette)
|
public void SetPalette(HardwarePalette palette)
|
||||||
{
|
{
|
||||||
if (palette.Texture == currentPaletteTexture)
|
if (palette.Texture == currentPaletteTexture)
|
||||||
@@ -115,8 +139,8 @@ namespace OpenRA.Graphics
|
|||||||
public void EndFrame(IInputHandler inputHandler)
|
public void EndFrame(IInputHandler inputHandler)
|
||||||
{
|
{
|
||||||
Flush();
|
Flush();
|
||||||
device.PumpInput(inputHandler);
|
Device.PumpInput(inputHandler);
|
||||||
device.Present();
|
Device.Present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawBatch<T>(IVertexBuffer<T> vertices,
|
public void DrawBatch<T>(IVertexBuffer<T> vertices,
|
||||||
@@ -124,7 +148,7 @@ namespace OpenRA.Graphics
|
|||||||
where T : struct
|
where T : struct
|
||||||
{
|
{
|
||||||
vertices.Bind();
|
vertices.Bind();
|
||||||
device.DrawPrimitives(type, firstVertex, numVertices);
|
Device.DrawPrimitives(type, firstVertex, numVertices);
|
||||||
PerfHistory.Increment("batches", 1);
|
PerfHistory.Increment("batches", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,58 +159,28 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void SetLineWidth(float width)
|
public void SetLineWidth(float width)
|
||||||
{
|
{
|
||||||
device.SetLineWidth(width);
|
Device.SetLineWidth(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IGraphicsDevice device;
|
public Size Resolution { get { return Device.WindowSize; } }
|
||||||
|
|
||||||
public Size Resolution { get { return device.WindowSize; } }
|
|
||||||
|
|
||||||
internal static void Initialize(WindowMode windowMode)
|
|
||||||
{
|
|
||||||
var resolution = GetResolution(windowMode);
|
|
||||||
|
|
||||||
var renderer = Game.Settings.Server.Dedicated ? "Null" : Game.Settings.Graphics.Renderer;
|
|
||||||
var rendererPath = Platform.ResolvePath(".", "OpenRA.Renderer." + renderer + ".dll");
|
|
||||||
|
|
||||||
device = CreateDevice(Assembly.LoadFile(rendererPath), resolution.Width, resolution.Height, windowMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Size GetResolution(WindowMode windowmode)
|
|
||||||
{
|
|
||||||
var size = (windowmode == WindowMode.Windowed)
|
|
||||||
? Game.Settings.Graphics.WindowedSize
|
|
||||||
: Game.Settings.Graphics.FullscreenSize;
|
|
||||||
return new Size(size.X, size.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static IGraphicsDevice CreateDevice(Assembly rendererDll, int width, int height, WindowMode window)
|
|
||||||
{
|
|
||||||
foreach (RendererAttribute r in rendererDll.GetCustomAttributes(typeof(RendererAttribute), false))
|
|
||||||
{
|
|
||||||
var factory = (IDeviceFactory)r.Type.GetConstructor(Type.EmptyTypes).Invoke(null);
|
|
||||||
return factory.Create(new Size(width, height), window);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException("Renderer DLL is missing RendererAttribute to tell us what type to use!");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IVertexBuffer<Vertex> GetTempVertexBuffer()
|
internal IVertexBuffer<Vertex> GetTempVertexBuffer()
|
||||||
{
|
{
|
||||||
var ret = tempBuffers.Dequeue();
|
return tempBuffers.Peek();
|
||||||
tempBuffers.Enqueue(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IBatchRenderer { void Flush(); }
|
public interface IBatchRenderer { void Flush(); }
|
||||||
|
|
||||||
static IBatchRenderer currentBatchRenderer;
|
public IBatchRenderer CurrentBatchRenderer
|
||||||
public static IBatchRenderer CurrentBatchRenderer
|
|
||||||
{
|
{
|
||||||
get { return currentBatchRenderer; }
|
get
|
||||||
|
{
|
||||||
|
return currentBatchRenderer;
|
||||||
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (currentBatchRenderer == value) return;
|
if (currentBatchRenderer == value)
|
||||||
|
return;
|
||||||
if (currentBatchRenderer != null)
|
if (currentBatchRenderer != null)
|
||||||
currentBatchRenderer.Flush();
|
currentBatchRenderer.Flush();
|
||||||
currentBatchRenderer = value;
|
currentBatchRenderer = value;
|
||||||
@@ -233,12 +227,21 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void GrabWindowMouseFocus()
|
public void GrabWindowMouseFocus()
|
||||||
{
|
{
|
||||||
device.GrabWindowMouseFocus();
|
Device.GrabWindowMouseFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReleaseWindowMouseFocus()
|
public void ReleaseWindowMouseFocus()
|
||||||
{
|
{
|
||||||
device.ReleaseWindowMouseFocus();
|
Device.ReleaseWindowMouseFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Device.Dispose();
|
||||||
|
WorldVoxelRenderer.Dispose();
|
||||||
|
foreach (var buffer in tempBuffers)
|
||||||
|
buffer.Dispose();
|
||||||
|
tempBuffers.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SequenceCache
|
public sealed class SequenceCache : IDisposable
|
||||||
{
|
{
|
||||||
readonly ModData modData;
|
readonly ModData modData;
|
||||||
readonly Lazy<SpriteCache> spriteCache;
|
readonly Lazy<SpriteCache> spriteCache;
|
||||||
@@ -141,5 +141,11 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
return new ReadOnlyDictionary<string, Sequence>(unitSequences);
|
return new ReadOnlyDictionary<string, Sequence>(unitSequences);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (spriteCache.IsValueCreated)
|
||||||
|
spriteCache.Value.SheetBuilder.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ using OpenRA.FileSystem;
|
|||||||
|
|
||||||
namespace OpenRA.Graphics
|
namespace OpenRA.Graphics
|
||||||
{
|
{
|
||||||
public class Sheet
|
public sealed class Sheet : IDisposable
|
||||||
{
|
{
|
||||||
readonly object textureLock = new object();
|
readonly object textureLock = new object();
|
||||||
bool dirty;
|
bool dirty;
|
||||||
@@ -178,5 +178,11 @@ namespace OpenRA.Graphics
|
|||||||
releaseBufferOnCommit = true;
|
releaseBufferOnCommit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (texture != null)
|
||||||
|
texture.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace OpenRA.Graphics
|
namespace OpenRA.Graphics
|
||||||
{
|
{
|
||||||
@@ -27,28 +29,34 @@ namespace OpenRA.Graphics
|
|||||||
BGRA = 4,
|
BGRA = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SheetBuilder
|
public sealed class SheetBuilder : IDisposable
|
||||||
{
|
{
|
||||||
|
readonly List<Sheet> sheets = new List<Sheet>();
|
||||||
|
readonly SheetType type;
|
||||||
|
readonly Func<Sheet> allocateSheet;
|
||||||
|
|
||||||
Sheet current;
|
Sheet current;
|
||||||
TextureChannel channel;
|
TextureChannel channel;
|
||||||
SheetType type;
|
|
||||||
int rowHeight = 0;
|
int rowHeight = 0;
|
||||||
Point p;
|
Point p;
|
||||||
Func<Sheet> allocateSheet;
|
|
||||||
|
|
||||||
public static Sheet AllocateSheet()
|
public static Sheet AllocateSheet(int sheetSize)
|
||||||
{
|
{
|
||||||
return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize));
|
return new Sheet(new Size(sheetSize, sheetSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SheetBuilder(SheetType t)
|
public SheetBuilder(SheetType t)
|
||||||
: this(t, AllocateSheet) { }
|
: this(t, Game.Settings.Graphics.SheetSize) { }
|
||||||
|
|
||||||
|
public SheetBuilder(SheetType t, int sheetSize)
|
||||||
|
: this(t, () => AllocateSheet(sheetSize)) { }
|
||||||
|
|
||||||
public SheetBuilder(SheetType t, Func<Sheet> allocateSheet)
|
public SheetBuilder(SheetType t, Func<Sheet> allocateSheet)
|
||||||
{
|
{
|
||||||
channel = TextureChannel.Red;
|
channel = TextureChannel.Red;
|
||||||
type = t;
|
type = t;
|
||||||
current = allocateSheet();
|
current = allocateSheet();
|
||||||
|
sheets.Add(current);
|
||||||
this.allocateSheet = allocateSheet;
|
this.allocateSheet = allocateSheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +119,7 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
current.ReleaseBuffer();
|
current.ReleaseBuffer();
|
||||||
current = allocateSheet();
|
current = allocateSheet();
|
||||||
|
sheets.Add(current);
|
||||||
channel = TextureChannel.Red;
|
channel = TextureChannel.Red;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -127,5 +136,12 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Sheet Current { get { return current; } }
|
public Sheet Current { get { return current; } }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var sheet in sheets)
|
||||||
|
sheet.Dispose();
|
||||||
|
sheets.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace OpenRA.Graphics
|
|||||||
static Library library = new Library();
|
static Library library = new Library();
|
||||||
static SheetBuilder builder;
|
static SheetBuilder builder;
|
||||||
|
|
||||||
int size;
|
readonly int size;
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
public SpriteFont(string name, int size)
|
public SpriteFont(string name, int size)
|
||||||
@@ -114,7 +114,6 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
// A new bitmap is generated each time this property is accessed, so we do need to dispose it.
|
// A new bitmap is generated each time this property is accessed, so we do need to dispose it.
|
||||||
using (var bitmap = face.Glyph.Bitmap)
|
using (var bitmap = face.Glyph.Bitmap)
|
||||||
{
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
var p = (byte*)bitmap.Buffer;
|
var p = (byte*)bitmap.Buffer;
|
||||||
@@ -136,7 +135,7 @@ namespace OpenRA.Graphics
|
|||||||
p += bitmap.Pitch;
|
p += bitmap.Pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
s.sheet.CommitData();
|
s.sheet.CommitData();
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
public class SpriteRenderer : Renderer.IBatchRenderer
|
public class SpriteRenderer : Renderer.IBatchRenderer
|
||||||
{
|
{
|
||||||
Renderer renderer;
|
readonly Renderer renderer;
|
||||||
IShader shader;
|
readonly IShader shader;
|
||||||
|
|
||||||
Vertex[] vertices = new Vertex[Renderer.TempBufferSize];
|
readonly Vertex[] vertices;
|
||||||
Sheet currentSheet = null;
|
Sheet currentSheet;
|
||||||
BlendMode currentBlend = BlendMode.Alpha;
|
BlendMode currentBlend = BlendMode.Alpha;
|
||||||
int nv = 0;
|
int nv = 0;
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
this.shader = shader;
|
this.shader = shader;
|
||||||
|
vertices = new Vertex[renderer.TempBufferSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Flush()
|
public void Flush()
|
||||||
@@ -60,7 +61,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)
|
void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)
|
||||||
{
|
{
|
||||||
Renderer.CurrentBatchRenderer = this;
|
renderer.CurrentBatchRenderer = this;
|
||||||
|
|
||||||
if (s.sheet != currentSheet)
|
if (s.sheet != currentSheet)
|
||||||
Flush();
|
Flush();
|
||||||
@@ -68,7 +69,7 @@ namespace OpenRA.Graphics
|
|||||||
if (s.blendMode != currentBlend)
|
if (s.blendMode != currentBlend)
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
if (nv + 4 > Renderer.TempBufferSize)
|
if (nv + 4 > renderer.TempBufferSize)
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
currentBlend = s.blendMode;
|
currentBlend = s.blendMode;
|
||||||
@@ -90,7 +91,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void DrawSprite(Sprite s, float2 a, float2 b, float2 c, float2 d)
|
public void DrawSprite(Sprite s, float2 a, float2 b, float2 c, float2 d)
|
||||||
{
|
{
|
||||||
Renderer.CurrentBatchRenderer = this;
|
renderer.CurrentBatchRenderer = this;
|
||||||
|
|
||||||
if (s.sheet != currentSheet)
|
if (s.sheet != currentSheet)
|
||||||
Flush();
|
Flush();
|
||||||
@@ -98,7 +99,7 @@ namespace OpenRA.Graphics
|
|||||||
if (s.blendMode != currentBlend)
|
if (s.blendMode != currentBlend)
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
if (nv + 4 > Renderer.TempBufferSize)
|
if (nv + 4 > renderer.TempBufferSize)
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
currentSheet = s.sheet;
|
currentSheet = s.sheet;
|
||||||
@@ -123,7 +124,7 @@ namespace OpenRA.Graphics
|
|||||||
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
||||||
{
|
{
|
||||||
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
||||||
shader.SetVec("r1", zoom*2f/screen.Width, -zoom*2f/screen.Height);
|
shader.SetVec("r1", zoom * 2f / screen.Width, -zoom * 2f / screen.Height);
|
||||||
shader.SetVec("r2", -1, 1);
|
shader.SetVec("r2", -1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Graphics
|
namespace OpenRA.Graphics
|
||||||
{
|
{
|
||||||
class TerrainRenderer
|
sealed class TerrainRenderer : IDisposable
|
||||||
{
|
{
|
||||||
IVertexBuffer<Vertex> vertexBuffer;
|
readonly IVertexBuffer<Vertex> vertexBuffer;
|
||||||
|
readonly World world;
|
||||||
World world;
|
readonly Map map;
|
||||||
Map map;
|
|
||||||
|
|
||||||
public TerrainRenderer(World world, WorldRenderer wr)
|
public TerrainRenderer(World world, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
@@ -42,7 +42,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void Draw(WorldRenderer wr, Viewport viewport)
|
public void Draw(WorldRenderer wr, Viewport viewport)
|
||||||
{
|
{
|
||||||
var verticesPerRow = 4*map.Bounds.Width;
|
var verticesPerRow = 4 * map.Bounds.Width;
|
||||||
var cells = viewport.VisibleCells;
|
var cells = viewport.VisibleCells;
|
||||||
var shape = wr.world.Map.TileShape;
|
var shape = wr.world.Map.TileShape;
|
||||||
|
|
||||||
@@ -58,5 +58,10 @@ namespace OpenRA.Graphics
|
|||||||
foreach (var r in world.WorldActor.TraitsImplementing<IRenderOverlay>())
|
foreach (var r in world.WorldActor.TraitsImplementing<IRenderOverlay>())
|
||||||
r.Render(wr);
|
r.Render(wr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
vertexBuffer.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ using OpenRA.FileSystem;
|
|||||||
|
|
||||||
namespace OpenRA.Graphics
|
namespace OpenRA.Graphics
|
||||||
{
|
{
|
||||||
public class Theater
|
public sealed class Theater : IDisposable
|
||||||
{
|
{
|
||||||
SheetBuilder sheetBuilder;
|
readonly Dictionary<ushort, Sprite[]> templates = new Dictionary<ushort, Sprite[]>();
|
||||||
Dictionary<ushort, Sprite[]> templates;
|
readonly SheetBuilder sheetBuilder;
|
||||||
Sprite missingTile;
|
readonly Sprite missingTile;
|
||||||
TileSet tileset;
|
TileSet tileset;
|
||||||
|
|
||||||
public Theater(TileSet tileset)
|
public Theater(TileSet tileset)
|
||||||
@@ -101,5 +101,10 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Sheet Sheet { get { return sheetBuilder.Current; } }
|
public Sheet Sheet { get { return sheetBuilder.Current; } }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
sheetBuilder.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,16 +32,18 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VoxelLoader
|
public sealed class VoxelLoader : IDisposable
|
||||||
{
|
{
|
||||||
SheetBuilder sheetBuilder;
|
static readonly float[] ChannelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
|
||||||
|
|
||||||
Cache<Pair<string,string>, Voxel> voxels;
|
readonly List<Vertex[]> vertices = new List<Vertex[]>();
|
||||||
|
readonly Cache<Pair<string, string>, Voxel> voxels;
|
||||||
IVertexBuffer<Vertex> vertexBuffer;
|
IVertexBuffer<Vertex> vertexBuffer;
|
||||||
List<Vertex[]> vertices;
|
|
||||||
int totalVertexCount;
|
int totalVertexCount;
|
||||||
int cachedVertexCount;
|
int cachedVertexCount;
|
||||||
|
|
||||||
|
SheetBuilder sheetBuilder;
|
||||||
|
|
||||||
static SheetBuilder CreateSheetBuilder()
|
static SheetBuilder CreateSheetBuilder()
|
||||||
{
|
{
|
||||||
var allocated = false;
|
var allocated = false;
|
||||||
@@ -50,7 +52,7 @@ namespace OpenRA.Graphics
|
|||||||
if (allocated)
|
if (allocated)
|
||||||
throw new SheetOverflowException("");
|
throw new SheetOverflowException("");
|
||||||
allocated = true;
|
allocated = true;
|
||||||
return SheetBuilder.AllocateSheet();
|
return SheetBuilder.AllocateSheet(Game.Renderer.SheetSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
return new SheetBuilder(SheetType.DualIndexed, allocate);
|
return new SheetBuilder(SheetType.DualIndexed, allocate);
|
||||||
@@ -58,7 +60,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public VoxelLoader()
|
public VoxelLoader()
|
||||||
{
|
{
|
||||||
voxels = new Cache<Pair<string,string>, Voxel>(LoadFile);
|
voxels = new Cache<Pair<string, string>, Voxel>(LoadFile);
|
||||||
vertices = new List<Vertex[]>();
|
vertices = new List<Vertex[]>();
|
||||||
totalVertexCount = 0;
|
totalVertexCount = 0;
|
||||||
cachedVertexCount = 0;
|
cachedVertexCount = 0;
|
||||||
@@ -66,29 +68,28 @@ namespace OpenRA.Graphics
|
|||||||
sheetBuilder = CreateSheetBuilder();
|
sheetBuilder = CreateSheetBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
|
Vertex[] GenerateSlicePlane(int su, int sv, Func<int, int, VxlElement> first, Func<int, int, VxlElement> second, Func<int, int, float[]> coord)
|
||||||
Vertex[] GenerateSlicePlane(int su, int sv, Func<int,int,VxlElement> first, Func<int,int,VxlElement> second, Func<int, int, float[]> coord)
|
|
||||||
{
|
{
|
||||||
var colors = new byte[su*sv];
|
var colors = new byte[su * sv];
|
||||||
var normals = new byte[su*sv];
|
var normals = new byte[su * sv];
|
||||||
|
|
||||||
var c = 0;
|
var c = 0;
|
||||||
for (var v = 0; v < sv; v++)
|
for (var v = 0; v < sv; v++)
|
||||||
for (var u = 0; u < su; u++)
|
for (var u = 0; u < su; u++)
|
||||||
{
|
{
|
||||||
var voxel = first(u,v) ?? second(u,v);
|
var voxel = first(u, v) ?? second(u, v);
|
||||||
colors[c] = voxel == null ? (byte)0 : voxel.Color;
|
colors[c] = voxel == null ? (byte)0 : voxel.Color;
|
||||||
normals[c] = voxel == null ? (byte)0 : voxel.Normal;
|
normals[c] = voxel == null ? (byte)0 : voxel.Normal;
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var s = sheetBuilder.Allocate(new Size(su, sv));
|
var s = sheetBuilder.Allocate(new Size(su, sv));
|
||||||
Util.FastCopyIntoChannel(s, 0, colors);
|
Util.FastCopyIntoChannel(s, 0, colors);
|
||||||
Util.FastCopyIntoChannel(s, 1, normals);
|
Util.FastCopyIntoChannel(s, 1, normals);
|
||||||
s.sheet.CommitData();
|
s.sheet.CommitData();
|
||||||
|
|
||||||
var channelP =channelSelect[(int)s.channel];
|
var channelP = ChannelSelect[(int)s.channel];
|
||||||
var channelC = channelSelect[(int)s.channel + 1];
|
var channelC = ChannelSelect[(int)s.channel + 1];
|
||||||
return new Vertex[4]
|
return new Vertex[4]
|
||||||
{
|
{
|
||||||
new Vertex(coord(0, 0), s.left, s.top, channelP, channelC),
|
new Vertex(coord(0, 0), s.left, s.top, channelP, channelC),
|
||||||
@@ -100,7 +101,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
IEnumerable<Vertex[]> GenerateSlicePlanes(VxlLimb l)
|
IEnumerable<Vertex[]> GenerateSlicePlanes(VxlLimb l)
|
||||||
{
|
{
|
||||||
Func<int,int,int,VxlElement> get = (x,y,z) =>
|
Func<int, int, int, VxlElement> get = (x, y, z) =>
|
||||||
{
|
{
|
||||||
if (x < 0 || y < 0 || z < 0)
|
if (x < 0 || y < 0 || z < 0)
|
||||||
return null;
|
return null;
|
||||||
@@ -108,41 +109,41 @@ namespace OpenRA.Graphics
|
|||||||
if (x >= l.Size[0] || y >= l.Size[1] || z >= l.Size[2])
|
if (x >= l.Size[0] || y >= l.Size[1] || z >= l.Size[2])
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var v = l.VoxelMap[(byte)x,(byte)y];
|
var v = l.VoxelMap[(byte)x, (byte)y];
|
||||||
if (v == null || !v.ContainsKey((byte)z))
|
if (v == null || !v.ContainsKey((byte)z))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return l.VoxelMap[(byte)x,(byte)y][(byte)z];
|
return l.VoxelMap[(byte)x, (byte)y][(byte)z];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Cull slices without any visible faces
|
// Cull slices without any visible faces
|
||||||
var xPlanes = new bool[l.Size[0]+1];
|
var xPlanes = new bool[l.Size[0] + 1];
|
||||||
var yPlanes = new bool[l.Size[1]+1];
|
var yPlanes = new bool[l.Size[1] + 1];
|
||||||
var zPlanes = new bool[l.Size[2]+1];
|
var zPlanes = new bool[l.Size[2] + 1];
|
||||||
for (var x = 0; x < l.Size[0]; x++)
|
for (var x = 0; x < l.Size[0]; x++)
|
||||||
{
|
{
|
||||||
for (var y = 0; y < l.Size[1]; y++)
|
for (var y = 0; y < l.Size[1]; y++)
|
||||||
{
|
{
|
||||||
for (var z = 0; z < l.Size[2]; z++)
|
for (var z = 0; z < l.Size[2]; z++)
|
||||||
{
|
{
|
||||||
if (get(x,y,z) == null)
|
if (get(x, y, z) == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Only generate a plane if it is actually visible
|
// Only generate a plane if it is actually visible
|
||||||
if (!xPlanes[x] && get(x-1,y,z) == null)
|
if (!xPlanes[x] && get(x - 1, y, z) == null)
|
||||||
xPlanes[x] = true;
|
xPlanes[x] = true;
|
||||||
if (!xPlanes[x+1] && get(x+1,y,z) == null)
|
if (!xPlanes[x + 1] && get(x + 1, y, z) == null)
|
||||||
xPlanes[x+1] = true;
|
xPlanes[x + 1] = true;
|
||||||
|
|
||||||
if (!yPlanes[y] && get(x,y-1,z) == null)
|
if (!yPlanes[y] && get(x, y - 1, z) == null)
|
||||||
yPlanes[y] = true;
|
yPlanes[y] = true;
|
||||||
if (!yPlanes[y+1] && get(x,y+1,z) == null)
|
if (!yPlanes[y + 1] && get(x, y + 1, z) == null)
|
||||||
yPlanes[y+1] = true;
|
yPlanes[y + 1] = true;
|
||||||
|
|
||||||
if (!zPlanes[z] && get(x,y,z-1) == null)
|
if (!zPlanes[z] && get(x, y, z - 1) == null)
|
||||||
zPlanes[z] = true;
|
zPlanes[z] = true;
|
||||||
if (!zPlanes[z+1] && get(x,y,z+1) == null)
|
if (!zPlanes[z + 1] && get(x, y, z + 1) == null)
|
||||||
zPlanes[z+1] = true;
|
zPlanes[z + 1] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,23 +151,23 @@ namespace OpenRA.Graphics
|
|||||||
for (var x = 0; x <= l.Size[0]; x++)
|
for (var x = 0; x <= l.Size[0]; x++)
|
||||||
if (xPlanes[x])
|
if (xPlanes[x])
|
||||||
yield return GenerateSlicePlane(l.Size[1], l.Size[2],
|
yield return GenerateSlicePlane(l.Size[1], l.Size[2],
|
||||||
(u,v) => get(x, u, v),
|
(u, v) => get(x, u, v),
|
||||||
(u,v) => get(x - 1, u, v),
|
(u, v) => get(x - 1, u, v),
|
||||||
(u,v) => new float[] {x, u, v});
|
(u, v) => new float[] { x, u, v });
|
||||||
|
|
||||||
for (var y = 0; y <= l.Size[1]; y++)
|
for (var y = 0; y <= l.Size[1]; y++)
|
||||||
if (yPlanes[y])
|
if (yPlanes[y])
|
||||||
yield return GenerateSlicePlane(l.Size[0], l.Size[2],
|
yield return GenerateSlicePlane(l.Size[0], l.Size[2],
|
||||||
(u,v) => get(u, y, v),
|
(u, v) => get(u, y, v),
|
||||||
(u,v) => get(u, y - 1, v),
|
(u, v) => get(u, y - 1, v),
|
||||||
(u,v) => new float[] {u, y, v});
|
(u, v) => new float[] { u, y, v });
|
||||||
|
|
||||||
for (var z = 0; z <= l.Size[2]; z++)
|
for (var z = 0; z <= l.Size[2]; z++)
|
||||||
if (zPlanes[z])
|
if (zPlanes[z])
|
||||||
yield return GenerateSlicePlane(l.Size[0], l.Size[1],
|
yield return GenerateSlicePlane(l.Size[0], l.Size[1],
|
||||||
(u,v) => get(u, v, z),
|
(u, v) => get(u, v, z),
|
||||||
(u,v) => get(u, v, z - 1),
|
(u, v) => get(u, v, z - 1),
|
||||||
(u,v) => new float[] {u, v, z});
|
(u, v) => new float[] { u, v, z });
|
||||||
}
|
}
|
||||||
|
|
||||||
public VoxelRenderData GenerateRenderData(VxlLimb l)
|
public VoxelRenderData GenerateRenderData(VxlLimb l)
|
||||||
@@ -195,6 +196,8 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void RefreshBuffer()
|
public void RefreshBuffer()
|
||||||
{
|
{
|
||||||
|
if (vertexBuffer != null)
|
||||||
|
vertexBuffer.Dispose();
|
||||||
vertexBuffer = Game.Renderer.Device.CreateVertexBuffer(totalVertexCount);
|
vertexBuffer = Game.Renderer.Device.CreateVertexBuffer(totalVertexCount);
|
||||||
vertexBuffer.SetData(vertices.SelectMany(v => v).ToArray(), totalVertexCount);
|
vertexBuffer.SetData(vertices.SelectMany(v => v).ToArray(), totalVertexCount);
|
||||||
cachedVertexCount = totalVertexCount;
|
cachedVertexCount = totalVertexCount;
|
||||||
@@ -210,7 +213,7 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Voxel LoadFile(Pair<string,string> files)
|
Voxel LoadFile(Pair<string, string> files)
|
||||||
{
|
{
|
||||||
VxlReader vxl;
|
VxlReader vxl;
|
||||||
HvaReader hva;
|
HvaReader hva;
|
||||||
@@ -230,5 +233,12 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
sheetBuilder.Current.ReleaseBuffer();
|
sheetBuilder.Current.ReleaseBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (vertexBuffer != null)
|
||||||
|
vertexBuffer.Dispose();
|
||||||
|
sheetBuilder.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,33 +32,30 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VoxelRenderer
|
public sealed class VoxelRenderer : IDisposable
|
||||||
{
|
{
|
||||||
Renderer renderer;
|
// Static constants
|
||||||
IShader shader;
|
static readonly float[] ShadowDiffuse = new float[] { 0, 0, 0 };
|
||||||
|
static readonly float[] ShadowAmbient = new float[] { 1, 1, 1 };
|
||||||
|
static readonly float2 SpritePadding = new float2(2, 2);
|
||||||
|
static readonly float[] ZeroVector = new float[] { 0, 0, 0, 1 };
|
||||||
|
static readonly float[] ZVector = new float[] { 0, 0, 1, 1 };
|
||||||
|
static readonly float[] FlipMtx = Util.ScaleMatrix(1, -1, 1);
|
||||||
|
static readonly float[] ShadowScaleFlipMtx = Util.ScaleMatrix(2, -2, 2);
|
||||||
|
|
||||||
|
readonly Renderer renderer;
|
||||||
|
readonly IShader shader;
|
||||||
|
|
||||||
|
readonly Dictionary<Sheet, IFrameBuffer> mappedBuffers = new Dictionary<Sheet, IFrameBuffer>();
|
||||||
|
readonly Stack<KeyValuePair<Sheet, IFrameBuffer>> unmappedBuffers = new Stack<KeyValuePair<Sheet, IFrameBuffer>>();
|
||||||
|
readonly List<Pair<Sheet, Action>> doRender = new List<Pair<Sheet, Action>>();
|
||||||
|
|
||||||
SheetBuilder sheetBuilder;
|
SheetBuilder sheetBuilder;
|
||||||
Dictionary<Sheet, IFrameBuffer> mappedBuffers;
|
|
||||||
Stack<KeyValuePair<Sheet, IFrameBuffer>> unmappedBuffers;
|
|
||||||
List<Pair<Sheet, Action>> doRender;
|
|
||||||
|
|
||||||
// Static constants
|
|
||||||
static readonly float[] shadowDiffuse = new float[] {0,0,0};
|
|
||||||
static readonly float[] shadowAmbient = new float[] {1,1,1};
|
|
||||||
static readonly float2 spritePadding = new float2(2, 2);
|
|
||||||
static readonly float[] zeroVector = new float[] {0,0,0,1};
|
|
||||||
static readonly float[] zVector = new float[] {0,0,1,1};
|
|
||||||
static readonly float[] flipMtx = Util.ScaleMatrix(1, -1, 1);
|
|
||||||
static readonly float[] shadowScaleFlipMtx = Util.ScaleMatrix(2, -2, 2);
|
|
||||||
|
|
||||||
public VoxelRenderer(Renderer renderer, IShader shader)
|
public VoxelRenderer(Renderer renderer, IShader shader)
|
||||||
{
|
{
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
this.shader = shader;
|
this.shader = shader;
|
||||||
|
|
||||||
mappedBuffers = new Dictionary<Sheet, IFrameBuffer>();
|
|
||||||
unmappedBuffers = new Stack<KeyValuePair<Sheet, IFrameBuffer>>();
|
|
||||||
doRender = new List<Pair<Sheet, Action>>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPalette(ITexture palette)
|
public void SetPalette(ITexture palette)
|
||||||
@@ -68,12 +65,12 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
public void SetViewportParams(Size screen, float zoom, int2 scroll)
|
||||||
{
|
{
|
||||||
var a = 2f / Renderer.SheetSize;
|
var a = 2f / renderer.SheetSize;
|
||||||
var view = new float[]
|
var view = new float[]
|
||||||
{
|
{
|
||||||
a, 0, 0, 0,
|
a, 0, 0, 0,
|
||||||
0, -a, 0, 0,
|
0, -a, 0, 0,
|
||||||
0, 0, -2*a, 0,
|
0, 0, -2 * a, 0,
|
||||||
-1, 1, 0, 1
|
-1, 1, 0, 1
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,7 +108,7 @@ namespace OpenRA.Graphics
|
|||||||
var offsetTransform = Util.TranslationMatrix(offsetVec[0], offsetVec[1], offsetVec[2]);
|
var offsetTransform = Util.TranslationMatrix(offsetVec[0], offsetVec[1], offsetVec[2]);
|
||||||
|
|
||||||
var worldTransform = v.RotationFunc().Aggregate(Util.IdentityMatrix(),
|
var worldTransform = v.RotationFunc().Aggregate(Util.IdentityMatrix(),
|
||||||
(x,y) => Util.MatrixMultiply(Util.MakeFloatMatrix(y.AsMatrix()), x));
|
(x, y) => Util.MatrixMultiply(Util.MakeFloatMatrix(y.AsMatrix()), x));
|
||||||
worldTransform = Util.MatrixMultiply(scaleTransform, worldTransform);
|
worldTransform = Util.MatrixMultiply(scaleTransform, worldTransform);
|
||||||
worldTransform = Util.MatrixMultiply(offsetTransform, worldTransform);
|
worldTransform = Util.MatrixMultiply(offsetTransform, worldTransform);
|
||||||
|
|
||||||
@@ -128,18 +125,18 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inflate rects to ensure rendering is within bounds
|
// Inflate rects to ensure rendering is within bounds
|
||||||
tl -= spritePadding;
|
tl -= SpritePadding;
|
||||||
br += spritePadding;
|
br += SpritePadding;
|
||||||
stl -= spritePadding;
|
stl -= SpritePadding;
|
||||||
sbr += spritePadding;
|
sbr += SpritePadding;
|
||||||
|
|
||||||
// Corners of the shadow quad, in shadow-space
|
// Corners of the shadow quad, in shadow-space
|
||||||
var corners = new float[][]
|
var corners = new float[][]
|
||||||
{
|
{
|
||||||
new float[] {stl.X, stl.Y, 0, 1},
|
new[] { stl.X, stl.Y, 0, 1 },
|
||||||
new float[] {sbr.X, sbr.Y, 0, 1},
|
new[] { sbr.X, sbr.Y, 0, 1 },
|
||||||
new float[] {sbr.X, stl.Y, 0, 1},
|
new[] { sbr.X, stl.Y, 0, 1 },
|
||||||
new float[] {stl.X, sbr.Y, 0, 1}
|
new[] { stl.X, sbr.Y, 0, 1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
var shadowScreenTransform = Util.MatrixMultiply(cameraTransform, invShadowTransform);
|
var shadowScreenTransform = Util.MatrixMultiply(cameraTransform, invShadowTransform);
|
||||||
@@ -148,8 +145,8 @@ namespace OpenRA.Graphics
|
|||||||
for (var j = 0; j < 4; j++)
|
for (var j = 0; j < 4; j++)
|
||||||
{
|
{
|
||||||
// Project to ground plane
|
// Project to ground plane
|
||||||
corners[j][2] = -(corners[j][1]*shadowGroundNormal[1]/shadowGroundNormal[2] +
|
corners[j][2] = -(corners[j][1] * shadowGroundNormal[1] / shadowGroundNormal[2] +
|
||||||
corners[j][0]*shadowGroundNormal[0]/shadowGroundNormal[2]);
|
corners[j][0] * shadowGroundNormal[0] / shadowGroundNormal[2]);
|
||||||
|
|
||||||
// Rotate to camera-space
|
// Rotate to camera-space
|
||||||
corners[j] = Util.MatrixVectorMultiply(shadowScreenTransform, corners[j]);
|
corners[j] = Util.MatrixVectorMultiply(shadowScreenTransform, corners[j]);
|
||||||
@@ -169,10 +166,10 @@ namespace OpenRA.Graphics
|
|||||||
var spriteCenter = new float2(sb.Left + sb.Width / 2, sb.Top + sb.Height / 2);
|
var spriteCenter = new float2(sb.Left + sb.Width / 2, sb.Top + sb.Height / 2);
|
||||||
var shadowCenter = new float2(ssb.Left + ssb.Width / 2, ssb.Top + ssb.Height / 2);
|
var shadowCenter = new float2(ssb.Left + ssb.Width / 2, ssb.Top + ssb.Height / 2);
|
||||||
|
|
||||||
var translateMtx = Util.TranslationMatrix(spriteCenter.X - spriteOffset.X, Renderer.SheetSize - (spriteCenter.Y - spriteOffset.Y), 0);
|
var translateMtx = Util.TranslationMatrix(spriteCenter.X - spriteOffset.X, renderer.SheetSize - (spriteCenter.Y - spriteOffset.Y), 0);
|
||||||
var shadowTranslateMtx = Util.TranslationMatrix(shadowCenter.X - shadowSpriteOffset.X, Renderer.SheetSize - (shadowCenter.Y - shadowSpriteOffset.Y), 0);
|
var shadowTranslateMtx = Util.TranslationMatrix(shadowCenter.X - shadowSpriteOffset.X, renderer.SheetSize - (shadowCenter.Y - shadowSpriteOffset.Y), 0);
|
||||||
var correctionTransform = Util.MatrixMultiply(translateMtx, flipMtx);
|
var correctionTransform = Util.MatrixMultiply(translateMtx, FlipMtx);
|
||||||
var shadowCorrectionTransform = Util.MatrixMultiply(shadowTranslateMtx, shadowScaleFlipMtx);
|
var shadowCorrectionTransform = Util.MatrixMultiply(shadowTranslateMtx, ShadowScaleFlipMtx);
|
||||||
|
|
||||||
doRender.Add(Pair.New<Sheet, Action>(sprite.sheet, () =>
|
doRender.Add(Pair.New<Sheet, Action>(sprite.sheet, () =>
|
||||||
{
|
{
|
||||||
@@ -183,7 +180,7 @@ namespace OpenRA.Graphics
|
|||||||
var offsetTransform = Util.TranslationMatrix(offsetVec[0], offsetVec[1], offsetVec[2]);
|
var offsetTransform = Util.TranslationMatrix(offsetVec[0], offsetVec[1], offsetVec[2]);
|
||||||
|
|
||||||
var rotations = v.RotationFunc().Aggregate(Util.IdentityMatrix(),
|
var rotations = v.RotationFunc().Aggregate(Util.IdentityMatrix(),
|
||||||
(x,y) => Util.MatrixMultiply(Util.MakeFloatMatrix(y.AsMatrix()), x));
|
(x, y) => Util.MatrixMultiply(Util.MakeFloatMatrix(y.AsMatrix()), x));
|
||||||
var worldTransform = Util.MatrixMultiply(scaleTransform, rotations);
|
var worldTransform = Util.MatrixMultiply(scaleTransform, rotations);
|
||||||
worldTransform = Util.MatrixMultiply(offsetTransform, worldTransform);
|
worldTransform = Util.MatrixMultiply(offsetTransform, worldTransform);
|
||||||
|
|
||||||
@@ -209,21 +206,21 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
// Disable shadow normals by forcing zero diffuse and identity ambient light
|
// Disable shadow normals by forcing zero diffuse and identity ambient light
|
||||||
Render(rd, Util.MatrixMultiply(shadow, t), lightDirection,
|
Render(rd, Util.MatrixMultiply(shadow, t), lightDirection,
|
||||||
shadowAmbient, shadowDiffuse, shadowPalette.Index, normals.Index);
|
ShadowAmbient, ShadowDiffuse, shadowPalette.Index, normals.Index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var screenLightVector = Util.MatrixVectorMultiply(invShadowTransform, zVector);
|
var screenLightVector = Util.MatrixVectorMultiply(invShadowTransform, ZVector);
|
||||||
screenLightVector = Util.MatrixVectorMultiply(cameraTransform, screenLightVector);
|
screenLightVector = Util.MatrixVectorMultiply(cameraTransform, screenLightVector);
|
||||||
return new VoxelRenderProxy(sprite, shadowSprite, screenCorners, -screenLightVector[2]/screenLightVector[1]);
|
return new VoxelRenderProxy(sprite, shadowSprite, screenCorners, -screenLightVector[2] / screenLightVector[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CalculateSpriteGeometry(float2 tl, float2 br, float scale, out Size size, out int2 offset)
|
static void CalculateSpriteGeometry(float2 tl, float2 br, float scale, out Size size, out int2 offset)
|
||||||
{
|
{
|
||||||
var width = (int)(scale*(br.X - tl.X));
|
var width = (int)(scale * (br.X - tl.X));
|
||||||
var height = (int)(scale*(br.Y - tl.Y));
|
var height = (int)(scale * (br.Y - tl.Y));
|
||||||
offset = (0.5f*scale*(br + tl)).ToInt2();
|
offset = (0.5f * scale * (br + tl)).ToInt2();
|
||||||
|
|
||||||
// Width and height must be even to avoid rendering glitches
|
// Width and height must be even to avoid rendering glitches
|
||||||
if ((width & 1) == 1)
|
if ((width & 1) == 1)
|
||||||
@@ -236,14 +233,14 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
static float[] ExtractRotationVector(float[] mtx)
|
static float[] ExtractRotationVector(float[] mtx)
|
||||||
{
|
{
|
||||||
var tVec = Util.MatrixVectorMultiply(mtx, zVector);
|
var tVec = Util.MatrixVectorMultiply(mtx, ZVector);
|
||||||
var tOrigin = Util.MatrixVectorMultiply(mtx, zeroVector);
|
var tOrigin = Util.MatrixVectorMultiply(mtx, ZeroVector);
|
||||||
tVec[0] -= tOrigin[0]*tVec[3]/tOrigin[3];
|
tVec[0] -= tOrigin[0] * tVec[3] / tOrigin[3];
|
||||||
tVec[1] -= tOrigin[1]*tVec[3]/tOrigin[3];
|
tVec[1] -= tOrigin[1] * tVec[3] / tOrigin[3];
|
||||||
tVec[2] -= tOrigin[2]*tVec[3]/tOrigin[3];
|
tVec[2] -= tOrigin[2] * tVec[3] / tOrigin[3];
|
||||||
|
|
||||||
// Renormalize
|
// Renormalize
|
||||||
var w = (float)Math.Sqrt(tVec[0]*tVec[0] + tVec[1]*tVec[1] + tVec[2]*tVec[2]);
|
var w = (float)Math.Sqrt(tVec[0] * tVec[0] + tVec[1] * tVec[1] + tVec[2] * tVec[2]);
|
||||||
tVec[0] /= w;
|
tVec[0] /= w;
|
||||||
tVec[1] /= w;
|
tVec[1] /= w;
|
||||||
tVec[2] /= w;
|
tVec[2] /= w;
|
||||||
@@ -330,12 +327,24 @@ namespace OpenRA.Graphics
|
|||||||
return kv.Key;
|
return kv.Key;
|
||||||
}
|
}
|
||||||
|
|
||||||
var size = new Size(Renderer.SheetSize, Renderer.SheetSize);
|
var size = new Size(renderer.SheetSize, renderer.SheetSize);
|
||||||
var framebuffer = renderer.Device.CreateFrameBuffer(size);
|
var framebuffer = renderer.Device.CreateFrameBuffer(size);
|
||||||
var sheet = new Sheet(framebuffer.Texture);
|
var sheet = new Sheet(framebuffer.Texture);
|
||||||
mappedBuffers.Add(sheet, framebuffer);
|
mappedBuffers.Add(sheet, framebuffer);
|
||||||
|
|
||||||
return sheet;
|
return sheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var kvp in mappedBuffers.Concat(unmappedBuffers))
|
||||||
|
{
|
||||||
|
kvp.Key.Dispose();
|
||||||
|
kvp.Value.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
mappedBuffers.Clear();
|
||||||
|
unmappedBuffers.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,24 +29,22 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WorldRenderer
|
public sealed class WorldRenderer : IDisposable
|
||||||
{
|
{
|
||||||
public readonly World world;
|
public readonly World world;
|
||||||
public readonly Theater Theater;
|
public readonly Theater Theater;
|
||||||
public Viewport Viewport { get; private set; }
|
public Viewport Viewport { get; private set; }
|
||||||
|
|
||||||
|
readonly HardwarePalette palette = new HardwarePalette();
|
||||||
|
readonly Dictionary<string, PaletteReference> palettes = new Dictionary<string, PaletteReference>();
|
||||||
readonly TerrainRenderer terrainRenderer;
|
readonly TerrainRenderer terrainRenderer;
|
||||||
readonly HardwarePalette palette;
|
|
||||||
readonly Dictionary<string, PaletteReference> palettes;
|
|
||||||
readonly Lazy<DeveloperMode> devTrait;
|
readonly Lazy<DeveloperMode> devTrait;
|
||||||
|
|
||||||
internal WorldRenderer(World world)
|
internal WorldRenderer(World world)
|
||||||
{
|
{
|
||||||
this.world = world;
|
this.world = world;
|
||||||
Viewport = new Viewport(this, world.Map);
|
Viewport = new Viewport(this, world.Map);
|
||||||
palette = new HardwarePalette();
|
|
||||||
|
|
||||||
palettes = new Dictionary<string, PaletteReference>();
|
|
||||||
foreach (var pal in world.traitDict.ActorsWithTrait<ILoadsPalettes>())
|
foreach (var pal in world.traitDict.ActorsWithTrait<ILoadsPalettes>())
|
||||||
pal.Trait.LoadPalettes(this);
|
pal.Trait.LoadPalettes(this);
|
||||||
|
|
||||||
@@ -251,5 +249,12 @@ namespace OpenRA.Graphics
|
|||||||
var ts = Game.modData.Manifest.TileSize;
|
var ts = Game.modData.Manifest.TileSize;
|
||||||
return new WPos(1024 * screenPx.X / ts.Width, 1024 * screenPx.Y / ts.Height, 0);
|
return new WPos(1024 * screenPx.X / ts.Width, 1024 * screenPx.Y / ts.Height, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
palette.Dispose();
|
||||||
|
Theater.Dispose();
|
||||||
|
terrainRenderer.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ using OpenRA.Primitives;
|
|||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
{
|
{
|
||||||
public class MapCache : IEnumerable<MapPreview>
|
public sealed class MapCache : IEnumerable<MapPreview>, IDisposable
|
||||||
{
|
{
|
||||||
public static readonly MapPreview UnknownMap = new MapPreview(null, null);
|
public static readonly MapPreview UnknownMap = new MapPreview(null, null);
|
||||||
readonly Cache<string, MapPreview> previews;
|
readonly Cache<string, MapPreview> previews;
|
||||||
@@ -163,7 +163,13 @@ namespace OpenRA
|
|||||||
foreach (var p in todo)
|
foreach (var p in todo)
|
||||||
{
|
{
|
||||||
// The rendering is thread safe because it only reads from the passed instances and writes to a new bitmap
|
// The rendering is thread safe because it only reads from the passed instances and writes to a new bitmap
|
||||||
var bitmap = p.CustomPreview ?? Minimap.RenderMapPreview(modData.DefaultRules.TileSets[p.Map.Tileset], p.Map, modData.DefaultRules, true);
|
var createdPreview = false;
|
||||||
|
var bitmap = p.CustomPreview;
|
||||||
|
if (bitmap == null)
|
||||||
|
{
|
||||||
|
createdPreview = true;
|
||||||
|
bitmap = Minimap.RenderMapPreview(modData.DefaultRules.TileSets[p.Map.Tileset], p.Map, modData.DefaultRules, true);
|
||||||
|
}
|
||||||
// Note: this is not generally thread-safe, but it works here because:
|
// Note: this is not generally thread-safe, but it works here because:
|
||||||
// (a) This worker is the only thread writing to this sheet
|
// (a) This worker is the only thread writing to this sheet
|
||||||
// (b) The main thread is the only thread reading this sheet
|
// (b) The main thread is the only thread reading this sheet
|
||||||
@@ -172,7 +178,15 @@ namespace OpenRA
|
|||||||
// the next render cycle.
|
// the next render cycle.
|
||||||
// (d) Any partially written bytes from the next minimap is in an
|
// (d) Any partially written bytes from the next minimap is in an
|
||||||
// unallocated area, and will be committed in the next cycle.
|
// unallocated area, and will be committed in the next cycle.
|
||||||
p.SetMinimap(sheetBuilder.Add(bitmap));
|
try
|
||||||
|
{
|
||||||
|
p.SetMinimap(sheetBuilder.Add(bitmap));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (createdPreview)
|
||||||
|
bitmap.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// Yuck... But this helps the UI Jank when opening the map selector significantly.
|
// Yuck... But this helps the UI Jank when opening the map selector significantly.
|
||||||
Thread.Sleep(Environment.ProcessorCount == 1 ? 25 : 5);
|
Thread.Sleep(Environment.ProcessorCount == 1 ? 25 : 5);
|
||||||
@@ -226,5 +240,10 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
return GetEnumerator();
|
return GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
sheetBuilder.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,29 +18,32 @@ using OpenRA.Widgets;
|
|||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
{
|
{
|
||||||
public class ModData
|
public sealed class ModData : IDisposable
|
||||||
{
|
{
|
||||||
public readonly Manifest Manifest;
|
public readonly Manifest Manifest;
|
||||||
public readonly ObjectCreator ObjectCreator;
|
public readonly ObjectCreator ObjectCreator;
|
||||||
public readonly WidgetLoader WidgetLoader;
|
public readonly WidgetLoader WidgetLoader;
|
||||||
public readonly MapCache MapCache;
|
public readonly MapCache MapCache;
|
||||||
public readonly ISpriteLoader[] SpriteLoaders;
|
public readonly ISpriteLoader[] SpriteLoaders;
|
||||||
public ILoadScreen LoadScreen = null;
|
|
||||||
public VoxelLoader VoxelLoader;
|
|
||||||
public readonly RulesetCache RulesetCache;
|
public readonly RulesetCache RulesetCache;
|
||||||
|
public ILoadScreen LoadScreen { get; private set; }
|
||||||
|
public VoxelLoader VoxelLoader { get; private set; }
|
||||||
public CursorProvider CursorProvider { get; private set; }
|
public CursorProvider CursorProvider { get; private set; }
|
||||||
|
|
||||||
Lazy<Ruleset> defaultRules;
|
Lazy<Ruleset> defaultRules;
|
||||||
public Ruleset DefaultRules { get { return defaultRules.Value; } }
|
public Ruleset DefaultRules { get { return defaultRules.Value; } }
|
||||||
|
|
||||||
public ModData(string mod)
|
public ModData(string mod, bool useLoadScreen = false)
|
||||||
{
|
{
|
||||||
Languages = new string[0];
|
Languages = new string[0];
|
||||||
Manifest = new Manifest(mod);
|
Manifest = new Manifest(mod);
|
||||||
ObjectCreator = new ObjectCreator(Manifest);
|
ObjectCreator = new ObjectCreator(Manifest);
|
||||||
LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen.Value);
|
if (useLoadScreen)
|
||||||
LoadScreen.Init(Manifest, Manifest.LoadScreen.ToDictionary(my => my.Value));
|
{
|
||||||
LoadScreen.Display();
|
LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen.Value);
|
||||||
|
LoadScreen.Init(Manifest, Manifest.LoadScreen.ToDictionary(my => my.Value));
|
||||||
|
LoadScreen.Display();
|
||||||
|
}
|
||||||
WidgetLoader = new WidgetLoader(this);
|
WidgetLoader = new WidgetLoader(this);
|
||||||
RulesetCache = new RulesetCache(this);
|
RulesetCache = new RulesetCache(this);
|
||||||
RulesetCache.LoadingProgress += HandleLoadingProgress;
|
RulesetCache.LoadingProgress += HandleLoadingProgress;
|
||||||
@@ -82,8 +85,13 @@ namespace OpenRA
|
|||||||
// horribly when you use ModData in unexpected ways.
|
// horribly when you use ModData in unexpected ways.
|
||||||
ChromeMetrics.Initialize(Manifest.ChromeMetrics);
|
ChromeMetrics.Initialize(Manifest.ChromeMetrics);
|
||||||
ChromeProvider.Initialize(Manifest.Chrome);
|
ChromeProvider.Initialize(Manifest.Chrome);
|
||||||
|
|
||||||
|
if (VoxelLoader != null)
|
||||||
|
VoxelLoader.Dispose();
|
||||||
VoxelLoader = new VoxelLoader();
|
VoxelLoader = new VoxelLoader();
|
||||||
|
|
||||||
|
if (CursorProvider != null)
|
||||||
|
CursorProvider.Dispose();
|
||||||
CursorProvider = new CursorProvider(this);
|
CursorProvider = new CursorProvider(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +138,8 @@ namespace OpenRA
|
|||||||
|
|
||||||
public Map PrepareMap(string uid)
|
public Map PrepareMap(string uid)
|
||||||
{
|
{
|
||||||
LoadScreen.Display();
|
if (LoadScreen != null)
|
||||||
|
LoadScreen.Display();
|
||||||
|
|
||||||
if (MapCache[uid].Status != MapStatus.Available)
|
if (MapCache[uid].Status != MapStatus.Available)
|
||||||
throw new InvalidDataException("Invalid map uid: {0}".F(uid));
|
throw new InvalidDataException("Invalid map uid: {0}".F(uid));
|
||||||
@@ -157,9 +166,21 @@ namespace OpenRA
|
|||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (LoadScreen != null)
|
||||||
|
LoadScreen.Dispose();
|
||||||
|
RulesetCache.Dispose();
|
||||||
|
MapCache.Dispose();
|
||||||
|
if (VoxelLoader != null)
|
||||||
|
VoxelLoader.Dispose();
|
||||||
|
if (CursorProvider != null)
|
||||||
|
CursorProvider.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ILoadScreen
|
public interface ILoadScreen : IDisposable
|
||||||
{
|
{
|
||||||
void Init(Manifest m, Dictionary<string, string> info);
|
void Init(Manifest m, Dictionary<string, string> info);
|
||||||
void Display();
|
void Display();
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ namespace OpenRA.Lint
|
|||||||
FieldLoader.UnknownFieldAction = (s, f) => EmitError("FieldLoader: Missing field `{0}` on `{1}`".F(s, f.Name));
|
FieldLoader.UnknownFieldAction = (s, f) => EmitError("FieldLoader: Missing field `{0}` on `{1}`".F(s, f.Name));
|
||||||
|
|
||||||
AppDomain.CurrentDomain.AssemblyResolve += GlobalFileSystem.ResolveAssembly;
|
AppDomain.CurrentDomain.AssemblyResolve += GlobalFileSystem.ResolveAssembly;
|
||||||
|
Game.InitializeSettings(Arguments.Empty);
|
||||||
Game.modData = new ModData(mod);
|
Game.modData = new ModData(mod);
|
||||||
|
|
||||||
IEnumerable<Map> maps;
|
IEnumerable<Map> maps;
|
||||||
|
|||||||
@@ -11,24 +11,23 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
|
||||||
using OpenRA.FileSystem;
|
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Cnc
|
namespace OpenRA.Mods.Cnc
|
||||||
{
|
{
|
||||||
public class CncLoadScreen : ILoadScreen
|
public sealed class CncLoadScreen : ILoadScreen
|
||||||
{
|
{
|
||||||
Dictionary<string, string> loadInfo;
|
Dictionary<string, string> loadInfo;
|
||||||
Stopwatch loadTimer = Stopwatch.StartNew();
|
Stopwatch loadTimer = Stopwatch.StartNew();
|
||||||
|
Sheet sheet;
|
||||||
Sprite[] ss;
|
Sprite[] ss;
|
||||||
int loadTick;
|
int loadTick;
|
||||||
float2 nodPos, gdiPos, evaPos;
|
float2 nodPos, gdiPos, evaPos;
|
||||||
Sprite nodLogo, gdiLogo, evaLogo, brightBlock, dimBlock;
|
Sprite nodLogo, gdiLogo, evaLogo, brightBlock, dimBlock;
|
||||||
Rectangle bounds;
|
Rectangle bounds;
|
||||||
Renderer r;
|
Renderer r;
|
||||||
NullInputHandler nih = new NullInputHandler();
|
readonly NullInputHandler nih = new NullInputHandler();
|
||||||
|
|
||||||
public void Init(Manifest m, Dictionary<string, string> info)
|
public void Init(Manifest m, Dictionary<string, string> info)
|
||||||
{
|
{
|
||||||
@@ -39,31 +38,31 @@ namespace OpenRA.Mods.Cnc
|
|||||||
r = Game.Renderer;
|
r = Game.Renderer;
|
||||||
if (r == null) return;
|
if (r == null) return;
|
||||||
|
|
||||||
var s = new Sheet(Platform.ResolvePath(loadInfo["Image"]));
|
sheet = new Sheet(Platform.ResolvePath(loadInfo["Image"]));
|
||||||
var res = r.Resolution;
|
var res = r.Resolution;
|
||||||
bounds = new Rectangle(0, 0, res.Width, res.Height);
|
bounds = new Rectangle(0, 0, res.Width, res.Height);
|
||||||
|
|
||||||
ss = new[]
|
ss = new[]
|
||||||
{
|
{
|
||||||
new Sprite(s, new Rectangle(161, 128, 62, 33), TextureChannel.Alpha),
|
new Sprite(sheet, new Rectangle(161, 128, 62, 33), TextureChannel.Alpha),
|
||||||
new Sprite(s, new Rectangle(161, 223, 62, 33), TextureChannel.Alpha),
|
new Sprite(sheet, new Rectangle(161, 223, 62, 33), TextureChannel.Alpha),
|
||||||
new Sprite(s, new Rectangle(128, 161, 33, 62), TextureChannel.Alpha),
|
new Sprite(sheet, new Rectangle(128, 161, 33, 62), TextureChannel.Alpha),
|
||||||
new Sprite(s, new Rectangle(223, 161, 33, 62), TextureChannel.Alpha),
|
new Sprite(sheet, new Rectangle(223, 161, 33, 62), TextureChannel.Alpha),
|
||||||
new Sprite(s, new Rectangle(128, 128, 33, 33), TextureChannel.Alpha),
|
new Sprite(sheet, new Rectangle(128, 128, 33, 33), TextureChannel.Alpha),
|
||||||
new Sprite(s, new Rectangle(223, 128, 33, 33), TextureChannel.Alpha),
|
new Sprite(sheet, new Rectangle(223, 128, 33, 33), TextureChannel.Alpha),
|
||||||
new Sprite(s, new Rectangle(128, 223, 33, 33), TextureChannel.Alpha),
|
new Sprite(sheet, new Rectangle(128, 223, 33, 33), TextureChannel.Alpha),
|
||||||
new Sprite(s, new Rectangle(223, 223, 33, 33), TextureChannel.Alpha)
|
new Sprite(sheet, new Rectangle(223, 223, 33, 33), TextureChannel.Alpha)
|
||||||
};
|
};
|
||||||
|
|
||||||
nodLogo = new Sprite(s, new Rectangle(0, 256, 256, 256), TextureChannel.Alpha);
|
nodLogo = new Sprite(sheet, new Rectangle(0, 256, 256, 256), TextureChannel.Alpha);
|
||||||
gdiLogo = new Sprite(s, new Rectangle(256, 256, 256, 256), TextureChannel.Alpha);
|
gdiLogo = new Sprite(sheet, new Rectangle(256, 256, 256, 256), TextureChannel.Alpha);
|
||||||
evaLogo = new Sprite(s, new Rectangle(256, 64, 128, 64), TextureChannel.Alpha);
|
evaLogo = new Sprite(sheet, new Rectangle(256, 64, 128, 64), TextureChannel.Alpha);
|
||||||
nodPos = new float2(bounds.Width / 2 - 384, bounds.Height / 2 - 128);
|
nodPos = new float2(bounds.Width / 2 - 384, bounds.Height / 2 - 128);
|
||||||
gdiPos = new float2(bounds.Width / 2 + 128, bounds.Height / 2 - 128);
|
gdiPos = new float2(bounds.Width / 2 + 128, bounds.Height / 2 - 128);
|
||||||
evaPos = new float2(bounds.Width - 43 - 128, 43);
|
evaPos = new float2(bounds.Width - 43 - 128, 43);
|
||||||
|
|
||||||
brightBlock = new Sprite(s, new Rectangle(320, 0, 16, 35), TextureChannel.Alpha);
|
brightBlock = new Sprite(sheet, new Rectangle(320, 0, 16, 35), TextureChannel.Alpha);
|
||||||
dimBlock = new Sprite(s, new Rectangle(336, 0, 16, 35), TextureChannel.Alpha);
|
dimBlock = new Sprite(sheet, new Rectangle(336, 0, 16, 35), TextureChannel.Alpha);
|
||||||
|
|
||||||
versionText = m.Mod.Version;
|
versionText = m.Mod.Version;
|
||||||
}
|
}
|
||||||
@@ -123,5 +122,11 @@ namespace OpenRA.Mods.Cnc
|
|||||||
{
|
{
|
||||||
Game.TestAndContinue();
|
Game.TestAndContinue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (sheet != null)
|
||||||
|
sheet.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,20 +11,19 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
|
||||||
using OpenRA.FileSystem;
|
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.LoadScreens
|
namespace OpenRA.Mods.Common.LoadScreens
|
||||||
{
|
{
|
||||||
public class DefaultLoadScreen : ILoadScreen
|
public sealed class DefaultLoadScreen : ILoadScreen
|
||||||
{
|
{
|
||||||
Stopwatch lastUpdate = Stopwatch.StartNew();
|
Stopwatch lastUpdate = Stopwatch.StartNew();
|
||||||
Renderer r;
|
Renderer r;
|
||||||
|
|
||||||
Rectangle stripeRect;
|
Rectangle stripeRect;
|
||||||
float2 logoPos;
|
float2 logoPos;
|
||||||
|
Sheet sheet;
|
||||||
Sprite stripe, logo;
|
Sprite stripe, logo;
|
||||||
string[] messages;
|
string[] messages;
|
||||||
|
|
||||||
@@ -37,9 +36,9 @@ namespace OpenRA.Mods.Common.LoadScreens
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
messages = info["Text"].Split(',');
|
messages = info["Text"].Split(',');
|
||||||
var s = new Sheet(Platform.ResolvePath(info["Image"]));
|
sheet = new Sheet(Platform.ResolvePath(info["Image"]));
|
||||||
logo = new Sprite(s, new Rectangle(0, 0, 256, 256), TextureChannel.Alpha);
|
logo = new Sprite(sheet, new Rectangle(0, 0, 256, 256), TextureChannel.Alpha);
|
||||||
stripe = new Sprite(s, new Rectangle(256, 0, 256, 256), TextureChannel.Alpha);
|
stripe = new Sprite(sheet, new Rectangle(256, 0, 256, 256), TextureChannel.Alpha);
|
||||||
stripeRect = new Rectangle(0, r.Resolution.Height / 2 - 128, r.Resolution.Width, 256);
|
stripeRect = new Rectangle(0, r.Resolution.Height / 2 - 128, r.Resolution.Width, 256);
|
||||||
logoPos = new float2(r.Resolution.Width / 2 - 128, r.Resolution.Height / 2 - 128);
|
logoPos = new float2(r.Resolution.Width / 2 - 128, r.Resolution.Height / 2 - 128);
|
||||||
}
|
}
|
||||||
@@ -71,5 +70,11 @@ namespace OpenRA.Mods.Common.LoadScreens
|
|||||||
{
|
{
|
||||||
Game.TestAndContinue();
|
Game.TestAndContinue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (sheet != null)
|
||||||
|
sheet.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using OpenRA.Widgets;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.LoadScreens
|
namespace OpenRA.Mods.Common.LoadScreens
|
||||||
{
|
{
|
||||||
public class ModChooserLoadScreen : ILoadScreen
|
public sealed class ModChooserLoadScreen : ILoadScreen
|
||||||
{
|
{
|
||||||
Sprite sprite;
|
Sprite sprite;
|
||||||
Rectangle bounds;
|
Rectangle bounds;
|
||||||
@@ -43,5 +43,11 @@ namespace OpenRA.Mods.Common.LoadScreens
|
|||||||
{
|
{
|
||||||
Ui.LoadWidget("MODCHOOSER", Ui.Root, new WidgetArgs());
|
Ui.LoadWidget("MODCHOOSER", Ui.Root, new WidgetArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (sprite != null)
|
||||||
|
sprite.sheet.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ using OpenRA.Widgets;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.LoadScreens
|
namespace OpenRA.Mods.Common.LoadScreens
|
||||||
{
|
{
|
||||||
public class NullLoadScreen : ILoadScreen
|
public sealed class NullLoadScreen : ILoadScreen
|
||||||
{
|
{
|
||||||
public void Init(Manifest m, Dictionary<string, string> info) { }
|
public void Init(Manifest m, Dictionary<string, string> info) { }
|
||||||
|
|
||||||
@@ -31,5 +31,9 @@ namespace OpenRA.Mods.Common.LoadScreens
|
|||||||
{
|
{
|
||||||
Ui.ResetAll();
|
Ui.ResetAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,15 +20,16 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
public class ModBrowserLogic
|
public class ModBrowserLogic
|
||||||
{
|
{
|
||||||
Widget modList;
|
readonly Widget modList;
|
||||||
ButtonWidget modTemplate;
|
readonly ButtonWidget modTemplate;
|
||||||
ModMetadata[] allMods;
|
readonly ModMetadata[] allMods;
|
||||||
|
readonly Dictionary<string, Sprite> previews = new Dictionary<string, Sprite>();
|
||||||
|
readonly Dictionary<string, Sprite> logos = new Dictionary<string, Sprite>();
|
||||||
|
readonly SheetBuilder sheetBuilder;
|
||||||
ModMetadata selectedMod;
|
ModMetadata selectedMod;
|
||||||
string selectedAuthor;
|
string selectedAuthor;
|
||||||
string selectedDescription;
|
string selectedDescription;
|
||||||
int modOffset = 0;
|
int modOffset = 0;
|
||||||
Dictionary<string, Sprite> previews;
|
|
||||||
Dictionary<string, Sprite> logos;
|
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public ModBrowserLogic(Widget widget)
|
public ModBrowserLogic(Widget widget)
|
||||||
@@ -63,9 +64,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
var sheetBuilder = new SheetBuilder(SheetType.BGRA);
|
sheetBuilder = new SheetBuilder(SheetType.BGRA);
|
||||||
previews = new Dictionary<string, Sprite>();
|
|
||||||
logos = new Dictionary<string, Sprite>();
|
|
||||||
allMods = ModMetadata.AllMods.Values.Where(m => m.Id != "modchooser")
|
allMods = ModMetadata.AllMods.Values.Where(m => m.Id != "modchooser")
|
||||||
.OrderBy(m => m.Title)
|
.OrderBy(m => m.Title)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@@ -75,21 +74,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var preview = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "preview.png"));
|
using (var preview = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "preview.png")))
|
||||||
if (preview.Width != 296 || preview.Height != 196)
|
if (preview.Width == 296 && preview.Height == 196)
|
||||||
continue;
|
previews.Add(mod.Id, sheetBuilder.Add(preview));
|
||||||
|
|
||||||
previews.Add(mod.Id, sheetBuilder.Add(preview));
|
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
catch (Exception) { }
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var logo = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "logo.png"));
|
using (var logo = new Bitmap(Platform.ResolvePath(".", "mods", mod.Id, "logo.png")))
|
||||||
if (logo.Width != 96 || logo.Height != 96)
|
if (logo.Width == 96 && logo.Height == 96)
|
||||||
continue;
|
logos.Add(mod.Id, sheetBuilder.Add(logo));
|
||||||
|
|
||||||
logos.Add(mod.Id, sheetBuilder.Add(logo));
|
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
catch (Exception) { }
|
||||||
}
|
}
|
||||||
@@ -155,11 +150,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
modOffset = selectedIndex - 4;
|
modOffset = selectedIndex - 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadMod(ModMetadata mod)
|
void LoadMod(ModMetadata mod)
|
||||||
{
|
{
|
||||||
Game.RunAfterTick(() =>
|
Game.RunAfterTick(() =>
|
||||||
{
|
{
|
||||||
Ui.CloseWindow();
|
Ui.CloseWindow();
|
||||||
|
sheetBuilder.Dispose();
|
||||||
Game.InitializeMod(mod.Id, null);
|
Game.InitializeMod(mod.Id, null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ namespace OpenRA.Renderer.Null
|
|||||||
public void Render(Action a) { }
|
public void Render(Action a) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NullTexture : ITexture
|
public sealed class NullTexture : ITexture
|
||||||
{
|
{
|
||||||
public TextureScaleFilter ScaleFilter { get { return TextureScaleFilter.Nearest; } set { } }
|
public TextureScaleFilter ScaleFilter { get { return TextureScaleFilter.Nearest; } set { } }
|
||||||
public void SetData(Bitmap bitmap) { }
|
public void SetData(Bitmap bitmap) { }
|
||||||
@@ -86,18 +86,21 @@ namespace OpenRA.Renderer.Null
|
|||||||
public void SetData(byte[] colors, int width, int height) { }
|
public void SetData(byte[] colors, int width, int height) { }
|
||||||
public byte[] GetData() { return new byte[0]; }
|
public byte[] GetData() { return new byte[0]; }
|
||||||
public Size Size { get { return new Size(0, 0); } }
|
public Size Size { get { return new Size(0, 0); } }
|
||||||
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NullFrameBuffer : IFrameBuffer
|
public sealed class NullFrameBuffer : IFrameBuffer
|
||||||
{
|
{
|
||||||
public void Bind() { }
|
public void Bind() { }
|
||||||
public void Unbind() { }
|
public void Unbind() { }
|
||||||
public ITexture Texture { get { return new NullTexture(); } }
|
public ITexture Texture { get { return new NullTexture(); } }
|
||||||
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
class NullVertexBuffer<T> : IVertexBuffer<T>
|
sealed class NullVertexBuffer<T> : IVertexBuffer<T>
|
||||||
{
|
{
|
||||||
public void Bind() { }
|
public void Bind() { }
|
||||||
public void SetData(T[] vertices, int length) { }
|
public void SetData(T[] vertices, int length) { }
|
||||||
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ using OpenTK.Graphics.OpenGL;
|
|||||||
|
|
||||||
namespace OpenRA.Renderer.Sdl2
|
namespace OpenRA.Renderer.Sdl2
|
||||||
{
|
{
|
||||||
public class FrameBuffer : IFrameBuffer
|
public sealed class FrameBuffer : IFrameBuffer
|
||||||
{
|
{
|
||||||
Texture texture;
|
Texture texture;
|
||||||
Size size;
|
Size size;
|
||||||
int framebuffer, depth;
|
int framebuffer, depth;
|
||||||
|
bool disposed;
|
||||||
|
|
||||||
public FrameBuffer(Size size)
|
public FrameBuffer(Size size)
|
||||||
{
|
{
|
||||||
@@ -81,16 +82,6 @@ namespace OpenRA.Renderer.Sdl2
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinalizeInner()
|
|
||||||
{
|
|
||||||
GL.Ext.DeleteFramebuffers(1, ref framebuffer);
|
|
||||||
ErrorHandler.CheckGlError();
|
|
||||||
GL.Ext.DeleteRenderbuffers(1, ref depth);
|
|
||||||
ErrorHandler.CheckGlError();
|
|
||||||
}
|
|
||||||
|
|
||||||
~FrameBuffer() { Game.RunAfterTick(FinalizeInner); }
|
|
||||||
|
|
||||||
int[] cv = new int[4];
|
int[] cv = new int[4];
|
||||||
public void Bind()
|
public void Bind()
|
||||||
{
|
{
|
||||||
@@ -120,5 +111,29 @@ namespace OpenRA.Renderer.Sdl2
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ITexture Texture { get { return texture; } }
|
public ITexture Texture { get { return texture; } }
|
||||||
|
|
||||||
|
~FrameBuffer()
|
||||||
|
{
|
||||||
|
Game.RunAfterTick(() => Dispose(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Game.RunAfterTick(() => Dispose(true));
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposed)
|
||||||
|
return;
|
||||||
|
disposed = true;
|
||||||
|
if (disposing)
|
||||||
|
texture.Dispose();
|
||||||
|
GL.Ext.DeleteFramebuffers(1, ref framebuffer);
|
||||||
|
ErrorHandler.CheckGlError();
|
||||||
|
GL.Ext.DeleteRenderbuffers(1, ref depth);
|
||||||
|
ErrorHandler.CheckGlError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ using OpenTK.Graphics.OpenGL;
|
|||||||
|
|
||||||
namespace OpenRA.Renderer.Sdl2
|
namespace OpenRA.Renderer.Sdl2
|
||||||
{
|
{
|
||||||
public class Texture : ITexture
|
public sealed class Texture : ITexture
|
||||||
{
|
{
|
||||||
int texture;
|
int texture;
|
||||||
TextureScaleFilter scaleFilter;
|
TextureScaleFilter scaleFilter;
|
||||||
@@ -26,6 +26,8 @@ namespace OpenRA.Renderer.Sdl2
|
|||||||
|
|
||||||
public Size Size { get { return size; } }
|
public Size Size { get { return size; } }
|
||||||
|
|
||||||
|
bool disposed;
|
||||||
|
|
||||||
public TextureScaleFilter ScaleFilter
|
public TextureScaleFilter ScaleFilter
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -55,9 +57,6 @@ namespace OpenRA.Renderer.Sdl2
|
|||||||
SetData(bitmap);
|
SetData(bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinalizeInner() { GL.DeleteTextures(1, ref texture); }
|
|
||||||
~Texture() { Game.RunAfterTick(FinalizeInner); }
|
|
||||||
|
|
||||||
void PrepareTexture()
|
void PrepareTexture()
|
||||||
{
|
{
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
@@ -131,6 +130,7 @@ namespace OpenRA.Renderer.Sdl2
|
|||||||
bitmap = new Bitmap(bitmap, bitmap.Size.NextPowerOf2());
|
bitmap = new Bitmap(bitmap, bitmap.Size.NextPowerOf2());
|
||||||
allocatedBitmap = true;
|
allocatedBitmap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
size = new Size(bitmap.Width, bitmap.Height);
|
size = new Size(bitmap.Width, bitmap.Height);
|
||||||
@@ -180,5 +180,24 @@ namespace OpenRA.Renderer.Sdl2
|
|||||||
0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Texture()
|
||||||
|
{
|
||||||
|
Game.RunAfterTick(() => Dispose(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Game.RunAfterTick(() => Dispose(true));
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposed)
|
||||||
|
return;
|
||||||
|
disposed = true;
|
||||||
|
GL.DeleteTextures(1, ref texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ using OpenTK.Graphics.OpenGL;
|
|||||||
|
|
||||||
namespace OpenRA.Renderer.Sdl2
|
namespace OpenRA.Renderer.Sdl2
|
||||||
{
|
{
|
||||||
public class VertexBuffer<T> : IVertexBuffer<T>
|
public sealed class VertexBuffer<T> : IVertexBuffer<T>
|
||||||
where T : struct
|
where T : struct
|
||||||
{
|
{
|
||||||
static readonly int VertexSize = Marshal.SizeOf(typeof(T));
|
static readonly int VertexSize = Marshal.SizeOf(typeof(T));
|
||||||
int buffer;
|
int buffer;
|
||||||
|
bool disposed;
|
||||||
|
|
||||||
public VertexBuffer(int size)
|
public VertexBuffer(int size)
|
||||||
{
|
{
|
||||||
@@ -52,7 +53,23 @@ namespace OpenRA.Renderer.Sdl2
|
|||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinalizeInner() { GL.DeleteBuffers(1, ref buffer); }
|
~VertexBuffer()
|
||||||
~VertexBuffer() { Game.RunAfterTick(FinalizeInner); }
|
{
|
||||||
|
Game.RunAfterTick(() => Dispose(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Game.RunAfterTick(() => Dispose(true));
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposed)
|
||||||
|
return;
|
||||||
|
disposed = true;
|
||||||
|
GL.DeleteBuffers(1, ref buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ namespace OpenRA.Utility
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Game.InitializeSettings(Arguments.Empty);
|
||||||
var modData = new ModData(modName);
|
var modData = new ModData(modName);
|
||||||
args = args.Skip(1).ToArray();
|
args = args.Skip(1).ToArray();
|
||||||
var actions = new Dictionary<string, Action<ModData, string[]>>();
|
var actions = new Dictionary<string, Action<ModData, string[]>>();
|
||||||
|
|||||||
Reference in New Issue
Block a user