Everything is now OpenRA, not OpenRa
This commit is contained in:
150
OpenRA.Game/Graphics/Animation.cs
Normal file
150
OpenRA.Game/Graphics/Animation.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Animation
|
||||
{
|
||||
string name;
|
||||
public Sequence CurrentSequence { get; private set; }
|
||||
int frame = 0;
|
||||
bool backwards = false;
|
||||
bool tickAlways;
|
||||
|
||||
Func<int> facingFunc;
|
||||
|
||||
public string Name { get { return name; } }
|
||||
|
||||
public Animation( string name )
|
||||
: this( name, () => 0 )
|
||||
{
|
||||
}
|
||||
|
||||
public Animation( string name, Func<int> facingFunc )
|
||||
{
|
||||
this.name = name.ToLowerInvariant();
|
||||
this.tickFunc = () => { };
|
||||
this.facingFunc = facingFunc;
|
||||
}
|
||||
|
||||
public Sprite Image
|
||||
{
|
||||
get
|
||||
{
|
||||
return backwards
|
||||
? CurrentSequence.GetSprite(CurrentSequence.End - frame - 1, facingFunc())
|
||||
: CurrentSequence.GetSprite(frame, facingFunc());
|
||||
}
|
||||
}
|
||||
|
||||
public void Play( string sequenceName )
|
||||
{
|
||||
PlayThen(sequenceName, () => { });
|
||||
}
|
||||
|
||||
public void PlayRepeating( string sequenceName )
|
||||
{
|
||||
PlayThen( sequenceName, () => PlayRepeating( CurrentSequence.Name ) );
|
||||
}
|
||||
|
||||
public void ReplaceAnim(string sequenceName)
|
||||
{
|
||||
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
|
||||
frame %= CurrentSequence.Length;
|
||||
}
|
||||
|
||||
public void PlayThen( string sequenceName, Action after )
|
||||
{
|
||||
after = after ?? ( () => { } );
|
||||
backwards = false;
|
||||
tickAlways = false;
|
||||
CurrentSequence = SequenceProvider.GetSequence( name, sequenceName );
|
||||
frame = 0;
|
||||
tickFunc = () =>
|
||||
{
|
||||
++frame;
|
||||
if( frame >= CurrentSequence.Length )
|
||||
{
|
||||
frame = CurrentSequence.Length - 1;
|
||||
tickFunc = () => { };
|
||||
after();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void PlayBackwardsThen(string sequenceName, Action after)
|
||||
{
|
||||
PlayThen(sequenceName, after);
|
||||
backwards = true;
|
||||
}
|
||||
|
||||
public void PlayFetchIndex( string sequenceName, Func<int> func )
|
||||
{
|
||||
backwards = false;
|
||||
tickAlways = true;
|
||||
CurrentSequence = SequenceProvider.GetSequence( name, sequenceName );
|
||||
frame = func();
|
||||
tickFunc = () => frame = func();
|
||||
}
|
||||
|
||||
int timeUntilNextFrame;
|
||||
Action tickFunc;
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
Tick( 40 ); // tick one frame
|
||||
}
|
||||
|
||||
public bool HasSequence(string seq) { return SequenceProvider.HasSequence( name, seq ); }
|
||||
|
||||
public void Tick( int t )
|
||||
{
|
||||
if( tickAlways )
|
||||
tickFunc();
|
||||
else
|
||||
{
|
||||
timeUntilNextFrame -= t;
|
||||
while( timeUntilNextFrame <= 0 )
|
||||
{
|
||||
tickFunc();
|
||||
timeUntilNextFrame += 40; // 25 fps == 40 ms
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeImage(string newImage)
|
||||
{
|
||||
newImage = newImage.ToLowerInvariant();
|
||||
|
||||
if (name != newImage)
|
||||
{
|
||||
name = newImage.ToLowerInvariant();
|
||||
ReplaceAnim(CurrentSequence.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public Sequence GetSequence( string sequenceName )
|
||||
{
|
||||
return SequenceProvider.GetSequence( name, sequenceName );
|
||||
}
|
||||
}
|
||||
}
|
||||
97
OpenRA.Game/Graphics/ChromeProvider.cs
Normal file
97
OpenRA.Game/Graphics/ChromeProvider.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class ChromeProvider
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, MappedImage>> collections;
|
||||
static Dictionary<string, Sheet> cachedSheets;
|
||||
static Dictionary<string, Dictionary<string, Sprite>> cachedSprites;
|
||||
|
||||
public static void Initialize(params string[] chromeFiles)
|
||||
{
|
||||
collections = new Dictionary<string, Dictionary<string, MappedImage>>();
|
||||
cachedSheets = new Dictionary<string, Sheet>();
|
||||
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
|
||||
|
||||
foreach (var f in chromeFiles)
|
||||
LoadChromeSource(f);
|
||||
}
|
||||
|
||||
static void LoadChromeSource(string filename)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
foreach (XmlElement eCollection in document.SelectNodes("/chrome/collection"))
|
||||
LoadChromeForCollection(eCollection);
|
||||
}
|
||||
|
||||
static void LoadChromeForCollection(XmlElement eCollection)
|
||||
{
|
||||
string elementName = eCollection.GetAttribute("name");
|
||||
string defaultSrc = (eCollection.HasAttribute("src") ? eCollection.GetAttribute("src") : null);
|
||||
|
||||
var images = eCollection.SelectNodes("./image").OfType<XmlElement>()
|
||||
.Select(e => new MappedImage(defaultSrc, e))
|
||||
.ToDictionary(s => s.Name);
|
||||
|
||||
collections.Add(elementName, images);
|
||||
}
|
||||
|
||||
public static Sprite GetImage(Renderer renderer, string collection, string image)
|
||||
{
|
||||
// Cached sprite
|
||||
if (cachedSprites.ContainsKey(collection) && cachedSprites[collection].ContainsKey(image))
|
||||
return cachedSprites[collection][image];
|
||||
|
||||
MappedImage mi;
|
||||
try { mi = collections[collection][image]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Collection `{0}` does not have an image `{1}`".F(collection, image));
|
||||
}
|
||||
|
||||
// Cached sheet
|
||||
Sheet sheet;
|
||||
if (cachedSheets.ContainsKey(mi.Src))
|
||||
sheet = cachedSheets[mi.Src];
|
||||
else
|
||||
{
|
||||
sheet = new Sheet(renderer, mi.Src);
|
||||
cachedSheets.Add(mi.Src, sheet);
|
||||
}
|
||||
|
||||
// Cache the sprite
|
||||
if (!cachedSprites.ContainsKey(collection))
|
||||
cachedSprites.Add(collection, new Dictionary<string, Sprite>());
|
||||
cachedSprites[collection].Add(image, mi.GetImage(renderer, sheet));
|
||||
|
||||
return cachedSprites[collection][image];
|
||||
}
|
||||
}
|
||||
}
|
||||
61
OpenRA.Game/Graphics/CursorSequence.cs
Normal file
61
OpenRA.Game/Graphics/CursorSequence.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Xml;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class CursorSequence
|
||||
{
|
||||
readonly int start, length;
|
||||
|
||||
public int Start { get { return start; } }
|
||||
public int End { get { return start + length; } }
|
||||
public int Length { get { return length; } }
|
||||
|
||||
public readonly int2 Hotspot;
|
||||
|
||||
Sprite[] sprites;
|
||||
|
||||
public CursorSequence(string cursorSrc, XmlElement e)
|
||||
{
|
||||
sprites = CursorSheetBuilder.LoadAllSprites(cursorSrc);
|
||||
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
|
||||
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||
length = sprites.Length - start;
|
||||
else if (e.HasAttribute("length"))
|
||||
length = int.Parse(e.GetAttribute("length"));
|
||||
else if (e.HasAttribute("end"))
|
||||
length = int.Parse(e.GetAttribute("end")) - start;
|
||||
else
|
||||
length = 1;
|
||||
|
||||
int.TryParse( e.GetAttribute("x"), out Hotspot.X );
|
||||
int.TryParse( e.GetAttribute("y"), out Hotspot.Y );
|
||||
}
|
||||
|
||||
public Sprite GetSprite(int frame)
|
||||
{
|
||||
return sprites[(frame % length) + start];
|
||||
}
|
||||
}
|
||||
}
|
||||
48
OpenRA.Game/Graphics/CursorSheetBuilder.cs
Normal file
48
OpenRA.Game/Graphics/CursorSheetBuilder.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class CursorSheetBuilder
|
||||
{
|
||||
static Cache<string, Sprite[]> cursors = new Cache<string, Sprite[]>(LoadCursors);
|
||||
static readonly string[] exts = { ".shp" };
|
||||
|
||||
static Sprite[] LoadCursors(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, a.Size)).ToArray();
|
||||
}
|
||||
catch (IndexOutOfRangeException) // This will occur when loading a custom (RA-format) .shp
|
||||
{
|
||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
|
||||
}
|
||||
}
|
||||
86
OpenRA.Game/Graphics/HardwarePalette.cs
Normal file
86
OpenRA.Game/Graphics/HardwarePalette.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class HardwarePalette : Sheet
|
||||
{
|
||||
public const int MaxPalettes = 64;
|
||||
int allocated = 0;
|
||||
|
||||
// We need to store the Palettes themselves for the remap palettes to work
|
||||
// We should probably try to fix this somehow
|
||||
static Dictionary<string, Palette> palettes;
|
||||
static Dictionary<string, int> indices;
|
||||
public HardwarePalette(Renderer renderer, Map map)
|
||||
: base(renderer,new Size(256, MaxPalettes))
|
||||
{
|
||||
palettes = new Dictionary<string, Palette>();
|
||||
indices = new Dictionary<string, int>();
|
||||
}
|
||||
|
||||
public Palette GetPalette(string name)
|
||||
{
|
||||
try { return palettes[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name)
|
||||
{
|
||||
try { return indices[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
}
|
||||
|
||||
public int AddPalette(string name, Palette p)
|
||||
{
|
||||
palettes.Add(name, p);
|
||||
indices.Add(name, allocated);
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
this[new Point(i, allocated)] = p.GetColor(i);
|
||||
}
|
||||
return allocated++;
|
||||
}
|
||||
|
||||
public void Update(IEnumerable<IPaletteModifier> paletteMods)
|
||||
{
|
||||
var b = new Bitmap(Bitmap);
|
||||
foreach (var mod in paletteMods)
|
||||
mod.AdjustPalette(b);
|
||||
|
||||
Texture.SetData(b);
|
||||
Game.renderer.PaletteTexture = Texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
89
OpenRA.Game/Graphics/LineRenderer.cs
Normal file
89
OpenRA.Game/Graphics/LineRenderer.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class LineRenderer
|
||||
{
|
||||
Renderer renderer;
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer; /* kindof a waste of space, but the GPU likes indexing, oh well */
|
||||
|
||||
const int linesPerBatch = 1024;
|
||||
|
||||
Vertex[] vertices = new Vertex[ 2 * linesPerBatch ];
|
||||
ushort[] indices = new ushort[ 2 * linesPerBatch ];
|
||||
int lines = 0;
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
public LineRenderer( Renderer renderer )
|
||||
{
|
||||
this.renderer = renderer;
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer(vertices.Length );
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if( lines > 0 )
|
||||
{
|
||||
renderer.LineShader.Render( () =>
|
||||
{
|
||||
vertexBuffer.SetData( vertices );
|
||||
indexBuffer.SetData( indices );
|
||||
renderer.DrawBatch( vertexBuffer, indexBuffer,
|
||||
nv, ni / 2, null, PrimitiveType.LineList );
|
||||
} );
|
||||
|
||||
nv = 0; ni = 0;
|
||||
lines = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawLine( float2 start, float2 end, Color startColor, Color endColor )
|
||||
{
|
||||
indices[ ni++ ] = (ushort)nv;
|
||||
|
||||
vertices[ nv++ ] = new Vertex( start,
|
||||
new float2( startColor.R / 255.0f, startColor.G / 255.0f ),
|
||||
new float2( startColor.B / 255.0f, startColor.A / 255.0f ) );
|
||||
|
||||
indices[ ni++ ] = (ushort)nv;
|
||||
|
||||
vertices[ nv++ ] = new Vertex( end,
|
||||
new float2( endColor.R / 255.0f, endColor.G / 255.0f ),
|
||||
new float2( endColor.B / 255.0f, endColor.A / 255.0f ) );
|
||||
|
||||
if( ++lines >= linesPerBatch )
|
||||
Flush();
|
||||
}
|
||||
|
||||
public void FillRect( RectangleF r, Color color )
|
||||
{
|
||||
for (float y = r.Top; y < r.Bottom; y++)
|
||||
{
|
||||
DrawLine(new float2(r.Left, y), new float2(r.Right, y), color, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
OpenRA.Game/Graphics/MappedImage.cs
Normal file
51
OpenRA.Game/Graphics/MappedImage.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class MappedImage
|
||||
{
|
||||
readonly Rectangle rect;
|
||||
public readonly string Src;
|
||||
public readonly string Name;
|
||||
|
||||
public MappedImage(string defaultSrc, XmlElement e)
|
||||
{
|
||||
Src = (e.HasAttribute("src")) ? e.GetAttribute("src") : defaultSrc;
|
||||
Name = e.GetAttribute("name");
|
||||
if (Src == null)
|
||||
throw new InvalidDataException("Image src missing");
|
||||
|
||||
rect = new Rectangle(int.Parse(e.GetAttribute("x")),
|
||||
int.Parse(e.GetAttribute("y")),
|
||||
int.Parse(e.GetAttribute("width")),
|
||||
int.Parse(e.GetAttribute("height")));
|
||||
}
|
||||
|
||||
public Sprite GetImage(Renderer r, Sheet s)
|
||||
{
|
||||
return new Sprite(s, rect, TextureChannel.Alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
213
OpenRA.Game/Graphics/Minimap.cs
Normal file
213
OpenRA.Game/Graphics/Minimap.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class Minimap
|
||||
{
|
||||
readonly World world;
|
||||
Sheet sheet, mapOnlySheet;
|
||||
SpriteRenderer rgbaRenderer;
|
||||
LineRenderer lineRenderer;
|
||||
Sprite sprite, mapOnlySprite;
|
||||
Bitmap terrain, oreLayer;
|
||||
Rectangle bounds;
|
||||
|
||||
Sprite ownedSpawnPoint;
|
||||
Sprite unownedSpawnPoint;
|
||||
|
||||
const int alpha = 230;
|
||||
|
||||
public void Tick() { }
|
||||
|
||||
public Minimap(World world, Renderer r)
|
||||
{
|
||||
this.world = world;
|
||||
sheet = new Sheet(r, new Size(128, 128));
|
||||
mapOnlySheet = new Sheet(r, new Size(128, 128));
|
||||
|
||||
lineRenderer = new LineRenderer(r);
|
||||
rgbaRenderer = new SpriteRenderer(r, true, r.RgbaSpriteShader);
|
||||
var size = Math.Max(world.Map.Width, world.Map.Height);
|
||||
var dw = (size - world.Map.Width) / 2;
|
||||
var dh = (size - world.Map.Height) / 2;
|
||||
|
||||
bounds = new Rectangle(world.Map.Offset.X - dw, world.Map.Offset.Y - dh, size, size);
|
||||
|
||||
sprite = new Sprite(sheet, bounds, TextureChannel.Alpha);
|
||||
mapOnlySprite = new Sprite(mapOnlySheet, bounds, TextureChannel.Alpha);
|
||||
|
||||
shroudColor = Color.FromArgb(alpha, Color.Black);
|
||||
|
||||
ownedSpawnPoint = ChromeProvider.GetImage(r, "spawnpoints", "owned");
|
||||
unownedSpawnPoint = ChromeProvider.GetImage(r, "spawnpoints", "unowned");
|
||||
}
|
||||
|
||||
public static Rectangle MakeMinimapBounds(Map m)
|
||||
{
|
||||
var size = Math.Max(m.Width, m.Height);
|
||||
var dw = (size - m.Width) / 2;
|
||||
var dh = (size - m.Height) / 2;
|
||||
|
||||
return new Rectangle(m.Offset.X - dw, m.Offset.Y - dh, size, size);
|
||||
}
|
||||
|
||||
static Cache<string, Color[]> terrainTypeColors = new Cache<string, Color[]>(
|
||||
theater =>
|
||||
{
|
||||
var pal = Game.world.WorldRenderer.GetPalette("terrain");
|
||||
return new[] {
|
||||
theater == "snow" ? 0xe3 :0x1a,
|
||||
0x63, 0x2f, 0x1f, 0x14, 0x64, 0x1f, 0x68, 0x6b, 0x6d, 0x88 }
|
||||
.Select(a => Color.FromArgb(alpha, pal.GetColor(a))).ToArray();
|
||||
});
|
||||
|
||||
static Color shroudColor;
|
||||
|
||||
public void InvalidateOre() { oreLayer = null; }
|
||||
|
||||
public static Bitmap RenderTerrainBitmap(Map map, TileSet tileset)
|
||||
{
|
||||
var colors = terrainTypeColors[map.Theater.ToLowerInvariant()];
|
||||
var terrain = new Bitmap(128, 128);
|
||||
for (var y = 0; y < 128; y++)
|
||||
for (var x = 0; x < 128; x++)
|
||||
terrain.SetPixel(x, y, map.IsInMap(x, y)
|
||||
? colors[tileset.GetWalkability(map.MapTiles[x, y])]
|
||||
: shroudColor);
|
||||
return terrain;
|
||||
}
|
||||
|
||||
public static Bitmap RenderTerrainBitmapWithSpawnPoints(Map map, TileSet tileset)
|
||||
{
|
||||
/* todo: do this a bit nicer */
|
||||
|
||||
var terrain = RenderTerrainBitmap(map, tileset);
|
||||
foreach (var sp in map.SpawnPoints)
|
||||
terrain.SetPixel(sp.X, sp.Y, Color.White);
|
||||
|
||||
return terrain;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (terrain == null)
|
||||
terrain = RenderTerrainBitmap(world.Map, world.TileSet);
|
||||
|
||||
if (oreLayer == null)
|
||||
{
|
||||
var colors = terrainTypeColors[world.Map.Theater.ToLowerInvariant()];
|
||||
oreLayer = new Bitmap(terrain);
|
||||
for (var y = world.Map.YOffset; y < world.Map.YOffset + world.Map.Height; y++)
|
||||
for (var x = world.Map.XOffset; x < world.Map.XOffset + world.Map.Width; x++)
|
||||
if (world.Map.ContainsResource(new int2(x, y)))
|
||||
oreLayer.SetPixel(x, y, colors[(int)TerrainMovementType.Ore]);
|
||||
}
|
||||
|
||||
mapOnlySheet.Texture.SetData(oreLayer);
|
||||
|
||||
if (!world.Queries.OwnedBy[world.LocalPlayer].WithTrait<ProvidesRadar>().Any())
|
||||
return;
|
||||
|
||||
var bitmap = new Bitmap(oreLayer);
|
||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
var colors = terrainTypeColors[world.Map.Theater.ToLowerInvariant()];
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
foreach (var a in world.Queries.WithTrait<Unit>().Where( a => a.Actor.Owner != null ))
|
||||
*(c + (a.Actor.Location.Y * bitmapData.Stride >> 2) + a.Actor.Location.X) =
|
||||
Color.FromArgb(alpha, a.Actor.Owner.Color).ToArgb();
|
||||
|
||||
for (var y = world.Map.YOffset; y < world.Map.YOffset + world.Map.Height; y++)
|
||||
for (var x = world.Map.XOffset; x < world.Map.XOffset + world.Map.Width; x++)
|
||||
{
|
||||
if (!world.LocalPlayer.Shroud.DisplayOnRadar(x, y))
|
||||
{
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = shroudColor.ToArgb();
|
||||
continue;
|
||||
}
|
||||
var b = world.WorldActor.traits.Get<BuildingInfluence>().GetBuildingAt(new int2(x, y));
|
||||
if (b != null)
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) =
|
||||
(b.Owner != null ? Color.FromArgb(alpha, b.Owner.Color) : colors[4]).ToArgb();
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
sheet.Texture.SetData(bitmap);
|
||||
}
|
||||
|
||||
public void Draw(RectangleF rect, bool mapOnly)
|
||||
{
|
||||
rgbaRenderer.DrawSprite(mapOnly ? mapOnlySprite : sprite,
|
||||
new float2(rect.X, rect.Y), "chrome", new float2(rect.Width, rect.Height));
|
||||
rgbaRenderer.Flush();
|
||||
}
|
||||
|
||||
int2 TransformCellToMinimapPixel(RectangleF viewRect, int2 p)
|
||||
{
|
||||
var fx = (float)(p.X - bounds.X) / bounds.Width;
|
||||
var fy = (float)(p.Y - bounds.Y) / bounds.Height;
|
||||
|
||||
return new int2(
|
||||
(int)(viewRect.Width * fx + viewRect.Left) - 8,
|
||||
(int)(viewRect.Height * fy + viewRect.Top) - 8);
|
||||
}
|
||||
|
||||
public void DrawSpawnPoints(RectangleF rect)
|
||||
{
|
||||
var points = world.Map.SpawnPoints
|
||||
.Select( (sp,i) => Pair.New(sp,world.players.Values.FirstOrDefault(
|
||||
p => p.SpawnPointIndex == i + 1 ) ))
|
||||
.ToList();
|
||||
|
||||
foreach (var p in points)
|
||||
{
|
||||
var pos = TransformCellToMinimapPixel(rect, p.First);
|
||||
|
||||
if (p.Second == null)
|
||||
rgbaRenderer.DrawSprite(unownedSpawnPoint, pos, "chrome");
|
||||
else
|
||||
{
|
||||
lineRenderer.FillRect(new RectangleF(
|
||||
Game.viewport.Location.X + pos.X + 2,
|
||||
Game.viewport.Location.Y + pos.Y + 2,
|
||||
12, 12), p.Second.Color);
|
||||
|
||||
rgbaRenderer.DrawSprite(ownedSpawnPoint, pos, "chrome");
|
||||
}
|
||||
}
|
||||
|
||||
lineRenderer.Flush();
|
||||
rgbaRenderer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
114
OpenRA.Game/Graphics/OverlayRenderer.cs
Executable file
114
OpenRA.Game/Graphics/OverlayRenderer.cs
Executable file
@@ -0,0 +1,114 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class OverlayRenderer
|
||||
{
|
||||
static string[] overlaySpriteNames =
|
||||
{
|
||||
"sbag", "cycl", "brik", "fenc", "wood",
|
||||
"gold01", "gold02", "gold03", "gold04",
|
||||
"gem01", "gem02", "gem03", "gem04",
|
||||
"v12", "v13", "v14", "v15", "v16", "v17", "v18",
|
||||
"fpls", "wcrate", "scrate", "barb", "sbag",
|
||||
};
|
||||
|
||||
static string[] smudgeSpriteNames =
|
||||
{
|
||||
"bib3", "bib2", "bib1", "sc1", "sc2", "sc3", "sc4", "sc5", "sc6",
|
||||
"cr1", "cr2", "cr3", "cr4", "cr5", "cr6",
|
||||
};
|
||||
|
||||
readonly Sprite[][] overlaySprites;
|
||||
readonly Sprite[] smudgeSprites;
|
||||
|
||||
SpriteRenderer spriteRenderer;
|
||||
Map map;
|
||||
|
||||
public OverlayRenderer( Renderer renderer, Map map )
|
||||
{
|
||||
this.spriteRenderer = new SpriteRenderer( renderer, true );
|
||||
this.map = map;
|
||||
|
||||
overlaySprites = overlaySpriteNames.Select(f => SpriteSheetBuilder.LoadAllSprites(f)).ToArray();
|
||||
smudgeSprites = smudgeSpriteNames.SelectMany(f => SpriteSheetBuilder.LoadAllSprites(f)).ToArray();
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var shroud = Game.world.LocalPlayer.Shroud;
|
||||
|
||||
for (int y = map.YOffset; y < map.YOffset + map.Height; y++)
|
||||
for (int x = map.XOffset; x < map.XOffset + map.Width; x++)
|
||||
{
|
||||
if (!shroud.IsExplored(new int2(x,y))) continue;
|
||||
|
||||
var tr = map.MapTiles[x,y];
|
||||
if (tr.smudge != 0 && tr.smudge <= smudgeSprites.Length)
|
||||
{
|
||||
var location = new int2(x, y);
|
||||
spriteRenderer.DrawSprite(smudgeSprites[tr.smudge - 1],
|
||||
Game.CellSize * (float2)location, "terrain");
|
||||
}
|
||||
|
||||
var o = tr.overlay;
|
||||
if (o < overlaySprites.Length)
|
||||
{
|
||||
var location = new int2(x, y);
|
||||
var sprites = overlaySprites[o];
|
||||
var spriteIndex = 0;
|
||||
if (Ore.overlayIsFence[o]) spriteIndex = NearbyFences(x, y);
|
||||
else if (Ore.overlayIsOre[o]) spriteIndex = map.MapTiles[x,y].density - 1;
|
||||
else if (Ore.overlayIsGems[o]) spriteIndex = map.MapTiles[x,y].density - 1;
|
||||
spriteRenderer.DrawSprite(sprites[spriteIndex],
|
||||
Game.CellSize * (float2)location, "terrain");
|
||||
}
|
||||
}
|
||||
|
||||
spriteRenderer.Flush();
|
||||
}
|
||||
|
||||
bool IsFence( int x, int y )
|
||||
{
|
||||
var o = map.MapTiles[ x, y ].overlay;
|
||||
if (o < Ore.overlayIsFence.Length)
|
||||
return Ore.overlayIsFence[o];
|
||||
return false;
|
||||
}
|
||||
|
||||
int NearbyFences( int x, int y )
|
||||
{
|
||||
int ret = 0;
|
||||
if( IsFence( x, y - 1 ) )
|
||||
ret |= 1;
|
||||
if( IsFence( x + 1, y ) )
|
||||
ret |= 2;
|
||||
if( IsFence( x, y + 1 ) )
|
||||
ret |= 4;
|
||||
if( IsFence( x - 1, y ) )
|
||||
ret |= 8;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
OpenRA.Game/Graphics/Renderer.cs
Normal file
134
OpenRA.Game/Graphics/Renderer.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.Support;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
internal class Renderer
|
||||
{
|
||||
internal static int SheetSize;
|
||||
|
||||
readonly IGraphicsDevice device;
|
||||
|
||||
public IShader SpriteShader { get; private set; } /* note: shared shader params */
|
||||
public IShader LineShader { get; private set; }
|
||||
public IShader RgbaSpriteShader { get; private set; }
|
||||
public IShader WorldSpriteShader { get; private set; }
|
||||
|
||||
public ITexture PaletteTexture;
|
||||
|
||||
public readonly SpriteFont RegularFont, BoldFont;
|
||||
|
||||
public Size Resolution { get { return device.WindowSize; } }
|
||||
|
||||
public Renderer(Size resolution, bool windowed)
|
||||
{
|
||||
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Gl.dll" ) ), resolution.Width, resolution.Height, windowed, false );
|
||||
|
||||
SpriteShader = device.CreateShader(FileSystem.Open("shaders/world-shp.fx"));
|
||||
LineShader = device.CreateShader(FileSystem.Open("shaders/line.fx"));
|
||||
RgbaSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-rgba.fx"));
|
||||
WorldSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-shp.fx"));
|
||||
|
||||
// RegularFont = device.CreateFont( "FreeSans.ttf" );
|
||||
// BoldFont = device.CreateFont( "FreeSansBold.ttf" );
|
||||
|
||||
RegularFont = new SpriteFont(this, "FreeSans.ttf", 14);
|
||||
BoldFont = new SpriteFont(this, "FreeSansBold.ttf", 14);
|
||||
}
|
||||
|
||||
IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, bool windowed, bool vsync )
|
||||
{
|
||||
foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) )
|
||||
{
|
||||
return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( bool ), typeof( bool ) } )
|
||||
.Invoke( new object[] { width, height, windowed, vsync } );
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IGraphicsDevice Device { get { return device; } }
|
||||
|
||||
public void BeginFrame(float2 r1, float2 r2, float2 scroll)
|
||||
{
|
||||
device.Begin();
|
||||
device.Clear(Color.Black);
|
||||
|
||||
SetShaderParams( SpriteShader, r1, r2, scroll );
|
||||
SetShaderParams( LineShader, r1, r2, scroll );
|
||||
SetShaderParams( RgbaSpriteShader, r1, r2, scroll );
|
||||
SetShaderParams( WorldSpriteShader, r1, r2, scroll );
|
||||
}
|
||||
|
||||
private void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll )
|
||||
{
|
||||
s.SetValue( "Palette", PaletteTexture );
|
||||
s.SetValue( "Scroll", scroll.X, scroll.Y );
|
||||
s.SetValue( "r1", r1.X, r1.Y );
|
||||
s.SetValue( "r2", r2.X, r2.Y );
|
||||
s.Commit();
|
||||
}
|
||||
|
||||
public void EndFrame()
|
||||
{
|
||||
device.End();
|
||||
device.Present();
|
||||
}
|
||||
|
||||
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
|
||||
Range<int> vertexRange, Range<int> indexRange, ITexture texture, PrimitiveType type, IShader shader)
|
||||
where T : struct
|
||||
{
|
||||
shader.SetValue("DiffuseTexture", texture);
|
||||
shader.Commit();
|
||||
|
||||
vertices.Bind();
|
||||
indices.Bind();
|
||||
|
||||
device.DrawIndexedPrimitives(type, vertexRange, indexRange);
|
||||
|
||||
PerfHistory.Increment("batches", 1);
|
||||
}
|
||||
|
||||
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
|
||||
int vertexPool, int numPrimitives, ITexture texture, PrimitiveType type)
|
||||
where T : struct
|
||||
{
|
||||
SpriteShader.SetValue("DiffuseTexture", texture);
|
||||
SpriteShader.Commit();
|
||||
|
||||
vertices.Bind();
|
||||
indices.Bind();
|
||||
|
||||
device.DrawIndexedPrimitives(type, vertexPool, numPrimitives);
|
||||
|
||||
PerfHistory.Increment("batches", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
70
OpenRA.Game/Graphics/Sequence.cs
Normal file
70
OpenRA.Game/Graphics/Sequence.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Xml;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sequence
|
||||
{
|
||||
readonly Sprite[] sprites;
|
||||
readonly int start, length, facings;
|
||||
|
||||
public readonly string Name;
|
||||
public int Start { get { return start; } }
|
||||
public int End { get { return start + length; } }
|
||||
public int Length { get { return length; } }
|
||||
public int Facings { get { return facings; } }
|
||||
|
||||
public Sequence(string unit, XmlElement e)
|
||||
{
|
||||
string srcOverride = e.GetAttribute("src");
|
||||
Name = e.GetAttribute("name");
|
||||
|
||||
sprites = SpriteSheetBuilder.LoadAllSprites(string.IsNullOrEmpty(srcOverride) ? unit : srcOverride );
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
|
||||
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||
length = sprites.Length - Start;
|
||||
else if (e.HasAttribute("length"))
|
||||
length = int.Parse(e.GetAttribute("length"));
|
||||
else if (e.HasAttribute("end"))
|
||||
length = int.Parse(e.GetAttribute("end")) - int.Parse(e.GetAttribute("start"));
|
||||
else
|
||||
length = 1;
|
||||
|
||||
if( e.HasAttribute( "facings" ) )
|
||||
facings = int.Parse( e.GetAttribute( "facings" ) );
|
||||
else
|
||||
facings = 1;
|
||||
}
|
||||
|
||||
public Sprite GetSprite( int frame )
|
||||
{
|
||||
return GetSprite( frame, 0 );
|
||||
}
|
||||
|
||||
public Sprite GetSprite(int frame, int facing)
|
||||
{
|
||||
var f = Traits.Util.QuantizeFacing( facing, facings );
|
||||
return sprites[ (f * length) + ( frame % length ) + start ];
|
||||
}
|
||||
}
|
||||
}
|
||||
101
OpenRA.Game/Graphics/SequenceProvider.cs
Normal file
101
OpenRA.Game/Graphics/SequenceProvider.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class SequenceProvider
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, Sequence>> units;
|
||||
static Dictionary<string, CursorSequence> cursors;
|
||||
|
||||
public static void Initialize(params string[] sequenceFiles)
|
||||
{
|
||||
units = new Dictionary<string, Dictionary<string, Sequence>>();
|
||||
cursors = new Dictionary<string, CursorSequence>();
|
||||
|
||||
foreach (var f in sequenceFiles)
|
||||
LoadSequenceSource(f);
|
||||
}
|
||||
|
||||
static void LoadSequenceSource(string filename)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
|
||||
foreach (XmlElement eUnit in document.SelectNodes("/sequences/unit"))
|
||||
LoadSequencesForUnit(eUnit);
|
||||
|
||||
foreach (XmlElement eCursor in document.SelectNodes("/sequences/cursor"))
|
||||
LoadSequencesForCursor(eCursor);
|
||||
}
|
||||
|
||||
static void LoadSequencesForCursor(XmlElement eCursor)
|
||||
{
|
||||
string cursorSrc = eCursor.GetAttribute("src");
|
||||
|
||||
foreach (XmlElement eSequence in eCursor.SelectNodes("./sequence"))
|
||||
cursors.Add(eSequence.GetAttribute("name"), new CursorSequence(cursorSrc, eSequence));
|
||||
|
||||
Log.Write("* LoadSequencesForCursor() done");
|
||||
}
|
||||
|
||||
static void LoadSequencesForUnit(XmlElement eUnit)
|
||||
{
|
||||
string unitName = eUnit.GetAttribute("name");
|
||||
Log.Write("Loading sequence {0}", unitName);
|
||||
var sequences = eUnit.SelectNodes("./sequence").OfType<XmlElement>()
|
||||
.Select(e => new Sequence(unitName, e))
|
||||
.ToDictionary(s => s.Name);
|
||||
|
||||
units.Add(unitName, sequences);
|
||||
}
|
||||
|
||||
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
try { return units[unitName][sequenceName]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
||||
}
|
||||
}
|
||||
|
||||
public static bool HasSequence(string unit, string seq)
|
||||
{
|
||||
return units[unit].ContainsKey(seq);
|
||||
}
|
||||
|
||||
public static CursorSequence GetCursorSequence(string cursor)
|
||||
{
|
||||
try { return cursors[cursor]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Cursor does not have a sequence `{0}`".F(cursor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
72
OpenRA.Game/Graphics/Sheet.cs
Normal file
72
OpenRA.Game/Graphics/Sheet.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sheet
|
||||
{
|
||||
readonly Renderer renderer;
|
||||
protected readonly Bitmap bitmap;
|
||||
|
||||
ITexture texture;
|
||||
|
||||
internal Sheet(Renderer renderer, Size size)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.bitmap = new Bitmap(size.Width, size.Height);
|
||||
}
|
||||
|
||||
internal Sheet(Renderer renderer, string filename)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename));
|
||||
}
|
||||
|
||||
void Resolve()
|
||||
{
|
||||
texture = renderer.Device.CreateTexture(bitmap);
|
||||
}
|
||||
|
||||
public ITexture Texture
|
||||
{
|
||||
get
|
||||
{
|
||||
if (texture == null)
|
||||
Resolve();
|
||||
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
public Size Size { get { return bitmap.Size; } }
|
||||
|
||||
protected Color this[Point p]
|
||||
{
|
||||
get { return bitmap.GetPixel(p.X, p.Y); }
|
||||
set { bitmap.SetPixel(p.X, p.Y, value); }
|
||||
}
|
||||
|
||||
public Bitmap Bitmap { get { return bitmap; } } // for perf
|
||||
}
|
||||
}
|
||||
119
OpenRA.Game/Graphics/SheetBuilder.cs
Normal file
119
OpenRA.Game/Graphics/SheetBuilder.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class SheetBuilder
|
||||
{
|
||||
public static SheetBuilder SharedInstance;
|
||||
public static void Initialize(Renderer r)
|
||||
{
|
||||
SharedInstance = new SheetBuilder(r, TextureChannel.Red);
|
||||
}
|
||||
|
||||
public SheetBuilder(Renderer r, TextureChannel ch)
|
||||
{
|
||||
renderer = r;
|
||||
current = null;
|
||||
rowHeight = 0;
|
||||
channel = null;
|
||||
initialChannel = ch;
|
||||
}
|
||||
|
||||
public Sprite Add(byte[] src, Size size)
|
||||
{
|
||||
Sprite rect = Allocate(size);
|
||||
Util.FastCopyIntoChannel(rect, src);
|
||||
return rect;
|
||||
}
|
||||
|
||||
public Sprite Add(Size size, byte paletteIndex)
|
||||
{
|
||||
byte[] data = new byte[size.Width * size.Height];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
data[i] = paletteIndex;
|
||||
|
||||
return Add(data, size);
|
||||
}
|
||||
|
||||
Sheet NewSheet() { return new Sheet( renderer, new Size( Renderer.SheetSize, Renderer.SheetSize ) ); }
|
||||
|
||||
Renderer renderer;
|
||||
Sheet current = null;
|
||||
int rowHeight = 0;
|
||||
Point p;
|
||||
TextureChannel? channel = null;
|
||||
TextureChannel initialChannel;
|
||||
|
||||
TextureChannel? NextChannel(TextureChannel? t)
|
||||
{
|
||||
if (t == null)
|
||||
return initialChannel;
|
||||
|
||||
switch (t.Value)
|
||||
{
|
||||
case TextureChannel.Red: return TextureChannel.Green;
|
||||
case TextureChannel.Green: return TextureChannel.Blue;
|
||||
case TextureChannel.Blue: return TextureChannel.Alpha;
|
||||
case TextureChannel.Alpha: return null;
|
||||
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Sprite Allocate(Size imageSize)
|
||||
{
|
||||
if (current == null)
|
||||
{
|
||||
current = NewSheet();
|
||||
channel = NextChannel(null);
|
||||
}
|
||||
|
||||
if (imageSize.Width + p.X > current.Size.Width)
|
||||
{
|
||||
p = new Point(0, p.Y + rowHeight);
|
||||
rowHeight = imageSize.Height;
|
||||
}
|
||||
|
||||
if (imageSize.Height > rowHeight)
|
||||
rowHeight = imageSize.Height;
|
||||
|
||||
if (p.Y + imageSize.Height > current.Size.Height)
|
||||
{
|
||||
|
||||
if (null == (channel = NextChannel(channel)))
|
||||
{
|
||||
current = NewSheet();
|
||||
channel = NextChannel(channel);
|
||||
}
|
||||
|
||||
rowHeight = imageSize.Height;
|
||||
p = new Point(0,0);
|
||||
}
|
||||
|
||||
Sprite rect = new Sprite(current, new Rectangle(p, imageSize), channel.Value);
|
||||
p.X += imageSize.Width;
|
||||
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
71
OpenRA.Game/Graphics/Sprite.cs
Normal file
71
OpenRA.Game/Graphics/Sprite.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sprite
|
||||
{
|
||||
public readonly Rectangle bounds;
|
||||
public readonly Sheet sheet;
|
||||
public readonly TextureChannel channel;
|
||||
public readonly RectangleF uv;
|
||||
public readonly float2 size;
|
||||
|
||||
readonly float2[] uvhax;
|
||||
|
||||
internal Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel)
|
||||
{
|
||||
this.bounds = bounds;
|
||||
this.sheet = sheet;
|
||||
this.channel = channel;
|
||||
|
||||
uv = new RectangleF(
|
||||
(float)(bounds.Left) / sheet.Size.Width,
|
||||
(float)(bounds.Top) / sheet.Size.Height,
|
||||
(float)(bounds.Width) / sheet.Size.Width,
|
||||
(float)(bounds.Height) / sheet.Size.Height);
|
||||
|
||||
uvhax = new float2[]
|
||||
{
|
||||
new float2( uv.Left, uv.Top ),
|
||||
new float2( uv.Right, uv.Top ),
|
||||
new float2( uv.Left, uv.Bottom ),
|
||||
new float2( uv.Right, uv.Bottom ),
|
||||
};
|
||||
|
||||
this.size = new float2(bounds.Size);
|
||||
}
|
||||
|
||||
public float2 FastMapTextureCoords( int k )
|
||||
{
|
||||
return uvhax[ k ];
|
||||
}
|
||||
}
|
||||
|
||||
public enum TextureChannel
|
||||
{
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Blue = 2,
|
||||
Alpha = 3,
|
||||
}
|
||||
}
|
||||
116
OpenRA.Game/Graphics/SpriteFont.cs
Normal file
116
OpenRA.Game/Graphics/SpriteFont.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using Tao.FreeType;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class SpriteFont
|
||||
{
|
||||
int size;
|
||||
public SpriteFont(Renderer r, string name, int size)
|
||||
{
|
||||
this.size = size;
|
||||
|
||||
if (0 != FT.FT_New_Face(library, name, 0, out face))
|
||||
throw new InvalidOperationException("FT_New_Face failed");
|
||||
|
||||
FT.FT_Set_Pixel_Sizes(face, 0, (uint)size);
|
||||
glyphs = new Cache<char, GlyphInfo>(CreateGlyph);
|
||||
|
||||
// setup a 1-channel SheetBuilder for our private use
|
||||
if (builder == null) builder = new SheetBuilder(r, TextureChannel.Alpha);
|
||||
|
||||
// precache glyphs for U+0020 - U+007f
|
||||
for (var n = (char)0x20; n < (char)0x7f; n++)
|
||||
if (glyphs[n] == null)
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
public void DrawText(SpriteRenderer r, string text, float2 location, Color c)
|
||||
{
|
||||
location.Y += size; // baseline vs top
|
||||
|
||||
var p = location;
|
||||
foreach (var s in text)
|
||||
{
|
||||
if (s == '\n')
|
||||
{
|
||||
location.Y += size;
|
||||
p = location;
|
||||
continue;
|
||||
}
|
||||
|
||||
var g = glyphs[s];
|
||||
r.DrawSprite(g.Sprite,
|
||||
new float2(
|
||||
(int)Math.Round(p.X + g.Offset.X, 0),
|
||||
p.Y + g.Offset.Y),
|
||||
"chrome");
|
||||
p.X += g.Advance;
|
||||
}
|
||||
|
||||
r.Flush();
|
||||
}
|
||||
|
||||
public int2 Measure(string text)
|
||||
{
|
||||
return new int2((int)text.Split( '\n' ).Max( s => s.Sum(a => glyphs[a].Advance)), size);
|
||||
}
|
||||
|
||||
Cache<char, GlyphInfo> glyphs;
|
||||
IntPtr face;
|
||||
|
||||
GlyphInfo CreateGlyph(char c)
|
||||
{
|
||||
var index = FT.FT_Get_Char_Index(face, (uint)c);
|
||||
FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER);
|
||||
|
||||
var _face = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
|
||||
var _glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(_face.glyph, typeof(FT_GlyphSlotRec));
|
||||
|
||||
var s = builder.Allocate(new Size(_glyph.metrics.width >> 6, _glyph.metrics.height >> 6));
|
||||
|
||||
var g = new GlyphInfo
|
||||
{
|
||||
Sprite = s,
|
||||
Advance = _glyph.metrics.horiAdvance / 64f,
|
||||
Offset = { X = _glyph.bitmap_left, Y = -_glyph.bitmap_top }
|
||||
};
|
||||
|
||||
unsafe
|
||||
{
|
||||
var p = (byte*)_glyph.bitmap.buffer;
|
||||
|
||||
for (var j = 0; j < s.size.Y; j++)
|
||||
{
|
||||
for (var i = 0; i < s.size.X; i++)
|
||||
if (p[i] != 0)
|
||||
s.sheet.Bitmap.SetPixel(i + s.bounds.Left, j + s.bounds.Top,
|
||||
Color.FromArgb(p[i], 0xff, 0xff, 0xff));
|
||||
|
||||
p += _glyph.bitmap.pitch;
|
||||
}
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
static SpriteFont()
|
||||
{
|
||||
FT.FT_Init_FreeType(out library);
|
||||
}
|
||||
|
||||
static IntPtr library;
|
||||
static SheetBuilder builder;
|
||||
}
|
||||
|
||||
class GlyphInfo
|
||||
{
|
||||
public float Advance;
|
||||
public int2 Offset;
|
||||
public Sprite Sprite;
|
||||
}
|
||||
}
|
||||
91
OpenRA.Game/Graphics/SpriteRenderer.cs
Normal file
91
OpenRA.Game/Graphics/SpriteRenderer.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class SpriteRenderer
|
||||
{
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer;
|
||||
Renderer renderer;
|
||||
IShader shader;
|
||||
|
||||
const int spritesPerBatch = 1024;
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * spritesPerBatch];
|
||||
ushort[] indices = new ushort[6 * spritesPerBatch];
|
||||
Sheet currentSheet = null;
|
||||
int sprites = 0;
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
public SpriteRenderer(Renderer renderer, bool allowAlpha, IShader shader)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.shader = shader;
|
||||
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
}
|
||||
|
||||
public SpriteRenderer(Renderer renderer, bool allowAlpha)
|
||||
: this(renderer, allowAlpha, renderer.SpriteShader) { }
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if (sprites > 0)
|
||||
{
|
||||
shader.SetValue( "DiffuseTexture", currentSheet.Texture );
|
||||
shader.Render(() =>
|
||||
{
|
||||
vertexBuffer.SetData(vertices);
|
||||
indexBuffer.SetData(indices);
|
||||
renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||
new Range<int>(0, nv),
|
||||
new Range<int>(0, ni),
|
||||
currentSheet.Texture, PrimitiveType.TriangleList,
|
||||
shader);
|
||||
});
|
||||
|
||||
nv = 0; ni = 0;
|
||||
currentSheet = null;
|
||||
sprites = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette)
|
||||
{
|
||||
DrawSprite(s, location, palette, s.size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette, float2 size)
|
||||
{
|
||||
if (s.sheet != currentSheet)
|
||||
Flush();
|
||||
|
||||
currentSheet = s.sheet;
|
||||
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, Game.world.WorldRenderer.GetPaletteIndex(palette), nv, ni, size);
|
||||
nv += 4; ni += 6;
|
||||
if (++sprites >= spritesPerBatch)
|
||||
Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
50
OpenRA.Game/Graphics/SpriteSheetBuilder.cs
Normal file
50
OpenRA.Game/Graphics/SpriteSheetBuilder.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class SpriteSheetBuilder
|
||||
{
|
||||
public static void Initialize( Map map )
|
||||
{
|
||||
exts = new[] {
|
||||
"." + map.Theater.Substring( 0, 3 ).ToLowerInvariant(),
|
||||
".shp",
|
||||
".tem",
|
||||
".sno",
|
||||
".int" };
|
||||
sprites = new Cache<string, Sprite[]>( LoadSprites );
|
||||
}
|
||||
|
||||
static Cache<string, Sprite[]> sprites;
|
||||
static string[] exts;
|
||||
|
||||
static Sprite[] LoadSprites(string filename)
|
||||
{
|
||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||
}
|
||||
|
||||
public static Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
|
||||
}
|
||||
}
|
||||
110
OpenRA.Game/Graphics/TerrainRenderer.cs
Normal file
110
OpenRA.Game/Graphics/TerrainRenderer.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class TerrainRenderer
|
||||
{
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer;
|
||||
Sheet terrainSheet;
|
||||
|
||||
Renderer renderer;
|
||||
Map map;
|
||||
OverlayRenderer overlayRenderer;
|
||||
|
||||
public TerrainRenderer(World world, Renderer renderer, WorldRenderer wr)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.map = world.Map;
|
||||
|
||||
Size tileSize = new Size( Game.CellSize, Game.CellSize );
|
||||
|
||||
var tileMapping = new Cache<TileReference, Sprite>(
|
||||
x => SheetBuilder.SharedInstance.Add(world.TileSet.GetBytes(x), tileSize));
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * map.Height * map.Width];
|
||||
ushort[] indices = new ushort[6 * map.Height * map.Width];
|
||||
|
||||
int nv = 0;
|
||||
int ni = 0;
|
||||
for( int j = map.YOffset ; j < map.YOffset + map.Height ; j++ )
|
||||
for( int i = map.XOffset ; i < map.XOffset + map.Width; i++ )
|
||||
{
|
||||
Sprite tile = tileMapping[map.MapTiles[i, j]];
|
||||
// TODO: The zero below should explicitly refer to the terrain palette, but this code is called
|
||||
// before the palettes are created
|
||||
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, 0, nv, ni, tile.size);
|
||||
nv += 4;
|
||||
ni += 6;
|
||||
}
|
||||
|
||||
terrainSheet = tileMapping[map.MapTiles[map.XOffset, map.YOffset]].sheet;
|
||||
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||
vertexBuffer.SetData( vertices );
|
||||
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
indexBuffer.SetData( indices );
|
||||
|
||||
overlayRenderer = new OverlayRenderer( renderer, map );
|
||||
}
|
||||
|
||||
public void Draw( Viewport viewport )
|
||||
{
|
||||
int indicesPerRow = map.Width * 6;
|
||||
int verticesPerRow = map.Width * 4;
|
||||
|
||||
int visibleRows = (int)(viewport.Height / 24.0f + 2);
|
||||
|
||||
int firstRow = (int)((viewport.Location.Y) / 24.0f - map.YOffset);
|
||||
int lastRow = firstRow + visibleRows;
|
||||
|
||||
if (lastRow < 0 || firstRow > map.Height)
|
||||
return;
|
||||
|
||||
if (firstRow < 0) firstRow = 0;
|
||||
if (lastRow > map.Height) lastRow = map.Height;
|
||||
|
||||
if (!Game.world.LocalPlayer.Shroud.HasGPS && Game.world.LocalPlayer.Shroud.bounds.HasValue)
|
||||
{
|
||||
var r = Game.world.LocalPlayer.Shroud.bounds.Value;
|
||||
if (firstRow < r.Top - map.YOffset)
|
||||
firstRow = r.Top - map.YOffset;
|
||||
|
||||
if (firstRow > r.Bottom - map.YOffset)
|
||||
firstRow = r.Bottom - map.YOffset;
|
||||
}
|
||||
|
||||
renderer.SpriteShader.SetValue( "DiffuseTexture", terrainSheet.Texture );
|
||||
renderer.SpriteShader.Render(() =>
|
||||
renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||
new Range<int>(verticesPerRow * firstRow, verticesPerRow * lastRow),
|
||||
new Range<int>(indicesPerRow * firstRow, indicesPerRow * lastRow),
|
||||
terrainSheet.Texture, PrimitiveType.TriangleList, renderer.SpriteShader));
|
||||
|
||||
overlayRenderer.Draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
131
OpenRA.Game/Graphics/Util.cs
Normal file
131
OpenRA.Game/Graphics/Util.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class Util
|
||||
{
|
||||
public static string[] ReadAllLines(Stream s)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
using (StreamReader reader = new StreamReader(s))
|
||||
while(!reader.EndOfStream)
|
||||
{
|
||||
var line = reader.ReadLine();
|
||||
if( !string.IsNullOrEmpty( line ) && line[0] != '#' )
|
||||
result.Add( line );
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public static T[] MakeArray<T>(int count, Converter<int, T> f)
|
||||
{
|
||||
T[] result = new T[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
result[i] = f(i);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
|
||||
|
||||
public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni, float2 size)
|
||||
{
|
||||
var attrib = new float2(palette / (float)HardwarePalette.MaxPalettes, channelSelect[(int)r.channel]);
|
||||
|
||||
vertices[nv] = new Vertex(o,
|
||||
r.FastMapTextureCoords(0), attrib);
|
||||
vertices[nv + 1] = new Vertex(new float2(o.X + size.X, o.Y),
|
||||
r.FastMapTextureCoords(1), attrib);
|
||||
vertices[nv + 2] = new Vertex(new float2(o.X, o.Y + size.Y),
|
||||
r.FastMapTextureCoords(2), attrib);
|
||||
vertices[nv + 3] = new Vertex(new float2(o.X + size.X, o.Y + size.Y),
|
||||
r.FastMapTextureCoords(3), attrib);
|
||||
|
||||
indices[ni] = (ushort)(nv);
|
||||
indices[ni + 1] = indices[ni + 3] = (ushort)(nv + 1);
|
||||
indices[ni + 2] = indices[ni + 5] = (ushort)(nv + 2);
|
||||
indices[ni + 4] = (ushort)(nv + 3);
|
||||
}
|
||||
|
||||
public static void FastCopyIntoChannel(Sprite dest, byte[] src)
|
||||
{
|
||||
var bitmap = dest.sheet.Bitmap;
|
||||
BitmapData bits = null;
|
||||
uint[] channelMasks = { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
|
||||
int[] shifts = { 16, 8, 0, 24 };
|
||||
|
||||
uint mask = channelMasks[(int)dest.channel];
|
||||
int shift = shifts[(int)dest.channel];
|
||||
|
||||
try
|
||||
{
|
||||
bits = bitmap.LockBits(dest.bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
int width = dest.bounds.Width;
|
||||
int height = dest.bounds.Height;
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* srcbase = &src[0])
|
||||
{
|
||||
byte* s = srcbase;
|
||||
uint* t = (uint*)bits.Scan0.ToPointer();
|
||||
int stride = bits.Stride >> 2;
|
||||
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
uint* p = t;
|
||||
for (int i = 0; i < width; i++, p++)
|
||||
*p = (*p & ~mask) | ((mask & ((uint)*s++) << shift));
|
||||
t += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmap.UnlockBits(bits);
|
||||
}
|
||||
}
|
||||
|
||||
public static Color Lerp(float t, Color a, Color b)
|
||||
{
|
||||
return Color.FromArgb(
|
||||
LerpChannel(t, a.A, b.A),
|
||||
LerpChannel(t, a.R, b.R),
|
||||
LerpChannel(t, a.G, b.G),
|
||||
LerpChannel(t, a.B, b.B));
|
||||
}
|
||||
|
||||
public static int LerpChannel(float t, int a, int b)
|
||||
{
|
||||
return (int)((1 - t) * a + t * b);
|
||||
}
|
||||
}
|
||||
}
|
||||
151
OpenRA.Game/Graphics/Viewport.cs
Normal file
151
OpenRA.Game/Graphics/Viewport.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
interface IHandleInput
|
||||
{
|
||||
bool HandleInput(World world, MouseInput mi);
|
||||
}
|
||||
|
||||
class Viewport
|
||||
{
|
||||
readonly float2 screenSize;
|
||||
float2 scrollPosition;
|
||||
readonly Renderer renderer;
|
||||
|
||||
public float2 Location { get { return scrollPosition; } }
|
||||
|
||||
public int Width { get { return (int)screenSize.X; } }
|
||||
public int Height { get { return (int)screenSize.Y; } }
|
||||
|
||||
SpriteRenderer cursorRenderer;
|
||||
int2 mousePos;
|
||||
float cursorFrame = 0f;
|
||||
|
||||
public void Scroll(float2 delta)
|
||||
{
|
||||
scrollPosition = scrollPosition + delta;
|
||||
}
|
||||
|
||||
public IEnumerable<IHandleInput> regions { get { return new IHandleInput[] { Game.chrome, Game.controller }; } }
|
||||
|
||||
public Viewport(float2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer)
|
||||
{
|
||||
this.screenSize = screenSize;
|
||||
this.renderer = renderer;
|
||||
cursorRenderer = new SpriteRenderer(renderer, true);
|
||||
|
||||
this.scrollPosition = Game.CellSize* mapStart;
|
||||
}
|
||||
|
||||
public void DrawRegions( World world )
|
||||
{
|
||||
world.WorldRenderer.palette.Update(world.Queries.WithTraitMultiple<IPaletteModifier>().Select(t=>t.Trait));
|
||||
|
||||
float2 r1 = new float2(2, -2) / screenSize;
|
||||
float2 r2 = new float2(-1, 1);
|
||||
|
||||
renderer.BeginFrame(r1, r2, scrollPosition);
|
||||
|
||||
if( Game.orderManager.GameStarted )
|
||||
{
|
||||
world.WorldRenderer.Draw();
|
||||
Game.chrome.Draw( world );
|
||||
|
||||
|
||||
if( Game.orderManager.Connection.ConnectionState == ConnectionState.NotConnected )
|
||||
Game.chrome.DrawDialog("Connection lost.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// what a hack. as soon as we have some real chrome stuff...
|
||||
|
||||
switch( Game.orderManager.Connection.ConnectionState )
|
||||
{
|
||||
case ConnectionState.Connecting:
|
||||
Game.chrome.DrawDialog("Connecting to {0}:{1}...".F( Game.Settings.NetworkHost, Game.Settings.NetworkPort ));
|
||||
break;
|
||||
case ConnectionState.NotConnected:
|
||||
Game.chrome.DrawDialog("Connection failed.");
|
||||
break;
|
||||
case ConnectionState.Connected:
|
||||
Game.chrome.DrawLobby( world );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var cursorName = Game.chrome.HitTest(mousePos) ? "default" : Game.controller.ChooseCursor( world );
|
||||
var c = new Cursor(cursorName);
|
||||
cursorRenderer.DrawSprite(c.GetSprite((int)cursorFrame), mousePos + Location - c.GetHotspot(), "cursor");
|
||||
cursorRenderer.Flush();
|
||||
|
||||
renderer.EndFrame();
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
cursorFrame += 0.5f;
|
||||
}
|
||||
|
||||
IHandleInput dragRegion = null;
|
||||
public void DispatchMouseInput(World world, MouseInput mi)
|
||||
{
|
||||
if (mi.Event == MouseInputEvent.Move)
|
||||
mousePos = mi.Location;
|
||||
|
||||
if (dragRegion != null) {
|
||||
dragRegion.HandleInput( world, mi );
|
||||
if (mi.Event == MouseInputEvent.Up) dragRegion = null;
|
||||
return;
|
||||
}
|
||||
|
||||
dragRegion = regions.FirstOrDefault(r => r.HandleInput(world, mi));
|
||||
if (mi.Event != MouseInputEvent.Down)
|
||||
dragRegion = null;
|
||||
}
|
||||
|
||||
public float2 ViewToWorld(MouseInput mi)
|
||||
{
|
||||
return (1 / 24.0f) * (new float2(mi.Location.X, mi.Location.Y) + Location);
|
||||
}
|
||||
|
||||
public void Center(IEnumerable<Actor> actors)
|
||||
{
|
||||
if (!actors.Any()) return;
|
||||
|
||||
var avgPos = (1f / actors.Count()) * actors
|
||||
.Select(a => a.CenterLocation)
|
||||
.Aggregate((a, b) => a + b);
|
||||
|
||||
scrollPosition = (avgPos - .5f * new float2(Width, Height)).ToInt2();
|
||||
}
|
||||
|
||||
public void GoToStartLocation( Player player )
|
||||
{
|
||||
Center( player.World.Queries.OwnedBy[ player ].WithTrait<Selectable>().Select( a => a.Actor ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
315
OpenRA.Game/Graphics/WorldRenderer.cs
Normal file
315
OpenRA.Game/Graphics/WorldRenderer.cs
Normal file
@@ -0,0 +1,315 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class WorldRenderer
|
||||
{
|
||||
readonly World world;
|
||||
internal readonly TerrainRenderer terrainRenderer;
|
||||
internal readonly SpriteRenderer spriteRenderer;
|
||||
internal readonly LineRenderer lineRenderer;
|
||||
internal readonly UiOverlay uiOverlay;
|
||||
internal readonly Renderer renderer;
|
||||
internal readonly HardwarePalette palette;
|
||||
|
||||
public static bool ShowUnitPaths = false;
|
||||
|
||||
internal WorldRenderer(World world, Renderer renderer)
|
||||
{
|
||||
this.world = world;
|
||||
this.renderer = renderer;
|
||||
|
||||
terrainRenderer = new TerrainRenderer(world, renderer, this);
|
||||
spriteRenderer = new SpriteRenderer(renderer, true);
|
||||
lineRenderer = new LineRenderer(renderer);
|
||||
uiOverlay = new UiOverlay(spriteRenderer);
|
||||
palette = new HardwarePalette(renderer, world.Map);
|
||||
Log.Write("Created worldrenderer");
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name)
|
||||
{
|
||||
return palette.GetPaletteIndex(name);
|
||||
}
|
||||
|
||||
public Palette GetPalette(string name)
|
||||
{
|
||||
return palette.GetPalette(name);
|
||||
}
|
||||
|
||||
public void AddPalette(string name, Palette pal)
|
||||
{
|
||||
palette.AddPalette(name, pal);
|
||||
}
|
||||
|
||||
void DrawSpriteList(RectangleF rect,
|
||||
IEnumerable<Renderable> images)
|
||||
{
|
||||
foreach (var image in images)
|
||||
{
|
||||
var loc = image.Pos;
|
||||
|
||||
if (loc.X > rect.Right || loc.X < rect.Left - image.Sprite.bounds.Width)
|
||||
continue;
|
||||
if (loc.Y > rect.Bottom || loc.Y < rect.Top - image.Sprite.bounds.Height)
|
||||
continue;
|
||||
|
||||
spriteRenderer.DrawSprite(image.Sprite, loc, image.Palette);
|
||||
}
|
||||
}
|
||||
|
||||
class SpriteComparer : IComparer<Renderable>
|
||||
{
|
||||
public int Compare(Renderable x, Renderable y)
|
||||
{
|
||||
var result = x.ZOffset.CompareTo(y.ZOffset);
|
||||
if (result == 0)
|
||||
result = x.Pos.Y.CompareTo(y.Pos.Y);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle GetBoundsRect()
|
||||
{
|
||||
if (!world.LocalPlayer.Shroud.HasGPS && world.LocalPlayer.Shroud.bounds.HasValue)
|
||||
{
|
||||
var r = world.LocalPlayer.Shroud.bounds.Value;
|
||||
|
||||
var left = (int)(Game.CellSize * r.Left - Game.viewport.Location.X);
|
||||
var top = (int)(Game.CellSize * r.Top - Game.viewport.Location.Y);
|
||||
var right = left + (int)(Game.CellSize * r.Width);
|
||||
var bottom = top + (int)(Game.CellSize * r.Height);
|
||||
|
||||
if (left < 0) left = 0;
|
||||
if (top < 0) top = 0;
|
||||
if (right > Game.viewport.Width) right = Game.viewport.Width;
|
||||
if (bottom > Game.viewport.Height) bottom = Game.viewport.Height;
|
||||
|
||||
return new Rectangle(left, top, right - left, bottom - top);
|
||||
}
|
||||
else
|
||||
return new Rectangle(0, 0, Game.viewport.Width, Game.viewport.Height);
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var bounds = GetBoundsRect();
|
||||
renderer.Device.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
|
||||
|
||||
terrainRenderer.Draw(Game.viewport);
|
||||
|
||||
var comparer = new SpriteComparer();
|
||||
|
||||
bounds.Offset((int)Game.viewport.Location.X, (int)Game.viewport.Location.Y);
|
||||
|
||||
var renderables = world.Actors.SelectMany(a => a.Render())
|
||||
.OrderBy(r => r, comparer);
|
||||
|
||||
DrawSpriteList(bounds, renderables);
|
||||
|
||||
foreach (var e in world.Effects)
|
||||
DrawSpriteList(bounds, e.Render());
|
||||
|
||||
uiOverlay.Draw( world );
|
||||
|
||||
spriteRenderer.Flush();
|
||||
|
||||
DrawBandBox();
|
||||
|
||||
if (Game.controller.orderGenerator != null)
|
||||
Game.controller.orderGenerator.Render( world );
|
||||
|
||||
world.LocalPlayer.Shroud.Draw(spriteRenderer);
|
||||
|
||||
lineRenderer.Flush();
|
||||
spriteRenderer.Flush();
|
||||
}
|
||||
|
||||
void DrawBandBox()
|
||||
{
|
||||
var selbox = Game.controller.SelectionBox;
|
||||
if (selbox == null) return;
|
||||
|
||||
var a = selbox.Value.First;
|
||||
var b = new float2(selbox.Value.Second.X - a.X, 0);
|
||||
var c = new float2(0, selbox.Value.Second.Y - a.Y);
|
||||
|
||||
lineRenderer.DrawLine(a, a + b, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a + b, a + b + c, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a + b + c, a + c, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a, a + c, Color.White, Color.White);
|
||||
|
||||
foreach (var u in world.SelectActorsInBox(selbox.Value.First, selbox.Value.Second))
|
||||
DrawSelectionBox(u, Color.Yellow, false);
|
||||
}
|
||||
|
||||
public void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar)
|
||||
{
|
||||
var bounds = selectedUnit.GetBounds(true);
|
||||
|
||||
var xy = new float2(bounds.Left, bounds.Top);
|
||||
var Xy = new float2(bounds.Right, bounds.Top);
|
||||
var xY = new float2(bounds.Left, bounds.Bottom);
|
||||
var XY = new float2(bounds.Right, bounds.Bottom);
|
||||
|
||||
lineRenderer.DrawLine(xy, xy + new float2(4, 0), c, c);
|
||||
lineRenderer.DrawLine(xy, xy + new float2(0, 4), c, c);
|
||||
lineRenderer.DrawLine(Xy, Xy + new float2(-4, 0), c, c);
|
||||
lineRenderer.DrawLine(Xy, Xy + new float2(0, 4), c, c);
|
||||
|
||||
lineRenderer.DrawLine(xY, xY + new float2(4, 0), c, c);
|
||||
lineRenderer.DrawLine(xY, xY + new float2(0, -4), c, c);
|
||||
lineRenderer.DrawLine(XY, XY + new float2(-4, 0), c, c);
|
||||
lineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c);
|
||||
|
||||
if (drawHealthBar)
|
||||
{
|
||||
DrawHealthBar(selectedUnit, xy, Xy);
|
||||
DrawControlGroup(selectedUnit, xy);
|
||||
|
||||
// Only display pips and tags to the owner
|
||||
if (selectedUnit.Owner == world.LocalPlayer)
|
||||
{
|
||||
DrawPips(selectedUnit, xY);
|
||||
DrawTags(selectedUnit, new float2(.5f * (bounds.Left + bounds.Right ), xy.Y));
|
||||
}
|
||||
}
|
||||
|
||||
if (ShowUnitPaths)
|
||||
{
|
||||
var mobile = selectedUnit.traits.GetOrDefault<Mobile>();
|
||||
if (mobile != null)
|
||||
{
|
||||
var path = mobile.GetCurrentPath();
|
||||
var start = selectedUnit.Location;
|
||||
|
||||
foreach (var step in path)
|
||||
{
|
||||
lineRenderer.DrawLine(
|
||||
Game.CellSize * start + new float2(12, 12),
|
||||
Game.CellSize * step + new float2(12, 12),
|
||||
Color.Red, Color.Red);
|
||||
start = step;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawHealthBar(Actor selectedUnit, float2 xy, float2 Xy)
|
||||
{
|
||||
var c = Color.Gray;
|
||||
lineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c);
|
||||
lineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c);
|
||||
|
||||
var healthAmount = (float)selectedUnit.Health / selectedUnit.Info.Traits.Get<OwnedActorInfo>().HP;
|
||||
var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red
|
||||
: (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow
|
||||
: Color.LimeGreen;
|
||||
|
||||
var healthColor2 = Color.FromArgb(
|
||||
255,
|
||||
healthColor.R / 2,
|
||||
healthColor.G / 2,
|
||||
healthColor.B / 2);
|
||||
|
||||
var z = float2.Lerp(xy, Xy, healthAmount);
|
||||
|
||||
lineRenderer.DrawLine(z + new float2(0, -4), Xy + new float2(0, -4), c, c);
|
||||
lineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c);
|
||||
|
||||
lineRenderer.DrawLine(xy + new float2(0, -3), z + new float2(0, -3), healthColor, healthColor);
|
||||
lineRenderer.DrawLine(xy + new float2(0, -2), z + new float2(0, -2), healthColor2, healthColor2);
|
||||
lineRenderer.DrawLine(xy + new float2(0, -4), z + new float2(0, -4), healthColor2, healthColor2);
|
||||
}
|
||||
|
||||
// depends on the order of pips in TraitsInterfaces.cs!
|
||||
static readonly string[] pipStrings = { "pip-empty", "pip-green", "pip-yellow", "pip-red", "pip-gray" };
|
||||
static readonly string[] tagStrings = { "", "tag-fake", "tag-primary" };
|
||||
|
||||
void DrawControlGroup(Actor selectedUnit, float2 basePosition)
|
||||
{
|
||||
var group = Game.controller.selection.GetControlGroupForActor(selectedUnit);
|
||||
if (group == null) return;
|
||||
|
||||
var pipImages = new Animation("pips");
|
||||
pipImages.PlayFetchIndex("groups", () => (int)group);
|
||||
pipImages.Tick();
|
||||
spriteRenderer.DrawSprite(pipImages.Image, basePosition + new float2(-8, 1), "chrome");
|
||||
}
|
||||
|
||||
void DrawPips(Actor selectedUnit, float2 basePosition)
|
||||
{
|
||||
// If a mod wants to implement a unit with multiple pip sources, then they are placed on multiple rows
|
||||
var pipxyBase = basePosition + new float2(-12, -7); // Correct for the offset in the shp file
|
||||
var pipxyOffset = new float2(0, 0); // Correct for offset due to multiple columns/rows
|
||||
|
||||
foreach (var pips in selectedUnit.traits.WithInterface<IPips>())
|
||||
{
|
||||
foreach (var pip in pips.GetPips(selectedUnit))
|
||||
{
|
||||
var pipImages = new Animation("pips");
|
||||
pipImages.PlayRepeating(pipStrings[(int)pip]);
|
||||
spriteRenderer.DrawSprite(pipImages.Image, pipxyBase + pipxyOffset, "chrome");
|
||||
pipxyOffset += new float2(4, 0);
|
||||
|
||||
if (pipxyOffset.X+5 > selectedUnit.GetBounds(false).Width)
|
||||
{
|
||||
pipxyOffset.X = 0;
|
||||
pipxyOffset.Y -= 4;
|
||||
}
|
||||
}
|
||||
// Increment row
|
||||
pipxyOffset.X = 0;
|
||||
pipxyOffset.Y -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTags(Actor selectedUnit, float2 basePosition)
|
||||
{
|
||||
// If a mod wants to implement a unit with multiple tags, then they are placed on multiple rows
|
||||
var tagxyBase = basePosition + new float2(-16, 2); // Correct for the offset in the shp file
|
||||
var tagxyOffset = new float2(0, 0); // Correct for offset due to multiple rows
|
||||
|
||||
foreach (var tags in selectedUnit.traits.WithInterface<ITags>())
|
||||
{
|
||||
foreach (var tag in tags.GetTags())
|
||||
{
|
||||
if (tag == TagType.None)
|
||||
continue;
|
||||
|
||||
var tagImages = new Animation("pips");
|
||||
tagImages.PlayRepeating(tagStrings[(int)tag]);
|
||||
spriteRenderer.DrawSprite(tagImages.Image, tagxyBase + tagxyOffset, "chrome");
|
||||
|
||||
// Increment row
|
||||
tagxyOffset.Y += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user