123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // The Command & Conquer Map Editor and corresponding source code 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.
- // The Command & Conquer Map Editor and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- using MobiusEditor.Interface;
- using MobiusEditor.Model;
- using MobiusEditor.Utility;
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Linq;
- namespace MobiusEditor.Render
- {
- public static class MapRenderer
- {
- private static readonly int[] Facing16 = new int[256]
- {
- 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,
- 2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,
- 4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,
- 10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,
- 12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,
- 14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,0,0,0,0,0,0
- };
- private static readonly int[] Facing32 = new int[256]
- {
- 0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,
- 3,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7,7,7,7,7,7,7,8,8,8,8,
- 8,8,8,9,9,9,9,9,9,9,10,10,10,10,10,10,10,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,
- 13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,
- 16,16,16,16,16,17,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,19,
- 19,20,20,20,20,20,20,21,21,21,21,21,21,21,22,22,22,22,22,22,22,23,23,23,23,23,23,23,24,24,24,24,
- 24,24,24,25,25,25,25,25,25,25,26,26,26,26,26,26,26,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,
- 29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,31,31,31,31,31,31,31,31,31,0,0,0,0,0,0
- };
- private static readonly int[] HumanShape = new int[32]
- {
- 0,0,7,7,7,7,6,6,6,6,5,5,5,5,5,4,4,4,3,3,3,3,2,2,2,2,1,1,1,1,1,0
- };
- private static readonly int[] BodyShape = new int[32]
- {
- 0,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1
- };
- private static readonly Point[] TurretAdjust = new Point[]
- {
- new Point(1, 2), // N
- new Point(-1, 1),
- new Point(-2, 0),
- new Point(-3, 0),
- new Point(-3, 1), // NW
- new Point(-4, -1),
- new Point(-4, -1),
- new Point(-5, -2),
- new Point(-5, -3), // W
- new Point(-5, -3),
- new Point(-3, -3),
- new Point(-3, -4),
- new Point(-3, -4), // SW
- new Point(-3, -5),
- new Point(-2, -5),
- new Point(-1, -5),
- new Point(0, -5), // S
- new Point(1, -6),
- new Point(2, -5),
- new Point(3, -5),
- new Point(4, -5), // SE
- new Point(6, -4),
- new Point(6, -3),
- new Point(6, -3),
- new Point(6, -3), // E
- new Point(5, -1),
- new Point(5, -1),
- new Point(4, 0),
- new Point(3, 0), // NE
- new Point(2, 0),
- new Point(2, 1),
- new Point(1, 2)
- };
- private static readonly int[] tiberiumCounts = new int[] { 0, 1, 3, 4, 6, 7, 8, 10, 11 };
- private static readonly int randomSeed;
- static MapRenderer()
- {
- randomSeed = Guid.NewGuid().GetHashCode();
- }
- public static void Render(GameType gameType, Map map, Graphics graphics, ISet<Point> locations, MapLayerFlag layers, int tileScale)
- {
- var tileSize = new Size(Globals.OriginalTileWidth / tileScale, Globals.OriginalTileHeight / tileScale);
- var tiberiumOrGoldTypes = map.OverlayTypes.Where(t => t.IsTiberiumOrGold).Select(t => t).ToArray();
- var gemTypes = map.OverlayTypes.Where(t => t.IsGem).ToArray();
- var overlappingRenderList = new List<(Rectangle, Action<Graphics>)>();
- Func<IEnumerable<Point>> renderLocations = null;
- if (locations != null)
- {
- renderLocations = () => locations;
- }
- else
- {
- IEnumerable<Point> allCells()
- {
- for (var y = 0; y < map.Metrics.Height; ++y)
- {
- for (var x = 0; x < map.Metrics.Width; ++x)
- {
- yield return new Point(x, y);
- }
- }
- }
- renderLocations = allCells;
- }
- if ((layers & MapLayerFlag.Template) != MapLayerFlag.None)
- {
- foreach (var topLeft in renderLocations())
- {
- map.Metrics.GetCell(topLeft, out int cell);
- var template = map.Templates[topLeft];
- var name = template?.Type.Name ?? map.TemplateTypes.Where(t => t.Equals("clear1")).FirstOrDefault().Name;
- var icon = template?.Icon ?? ((cell & 0x03) | ((cell >> 4) & 0x0C));
- if (Globals.TheTilesetManager.GetTileData(map.Theater.Tilesets, name, icon, out Tile tile))
- {
- var renderBounds = new Rectangle(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height, tileSize.Width, tileSize.Height);
- graphics.DrawImage(tile.Image, renderBounds);
- }
- else
- {
- Debug.Print(string.Format("Template {0} ({1}) not found", name, icon));
- }
- }
- }
- if ((layers & MapLayerFlag.Smudge) != MapLayerFlag.None)
- {
- foreach (var topLeft in renderLocations())
- {
- var smudge = map.Smudge[topLeft];
- if (smudge != null)
- {
- Render(map.Theater, topLeft, tileSize, smudge).Item2(graphics);
- }
- }
- }
- if ((layers & MapLayerFlag.OverlayAll) != MapLayerFlag.None)
- {
- foreach (var topLeft in renderLocations())
- {
- var overlay = map.Overlay[topLeft];
- if (overlay == null)
- {
- continue;
- }
- if ((overlay.Type.IsResource && ((layers & MapLayerFlag.Resources) != MapLayerFlag.None)) ||
- (overlay.Type.IsWall && ((layers & MapLayerFlag.Walls) != MapLayerFlag.None)) ||
- ((layers & MapLayerFlag.Overlay) != MapLayerFlag.None))
- {
- Render(map.Theater, tiberiumOrGoldTypes, gemTypes, topLeft, tileSize, tileScale, overlay).Item2(graphics);
- }
- }
- }
- if ((layers & MapLayerFlag.Terrain) != MapLayerFlag.None)
- {
- foreach (var (topLeft, terrain) in map.Technos.OfType<Terrain>())
- {
- if ((locations != null) && !locations.Contains(topLeft))
- {
- continue;
- }
- string tileName = terrain.Type.Name;
- if ((terrain.Type.TemplateType & TemplateTypeFlag.OreMine) != TemplateTypeFlag.None)
- {
- tileName = "OREMINE";
- }
- if (Globals.TheTilesetManager.GetTileData(map.Theater.Tilesets, tileName, terrain.Icon, out Tile tile))
- {
- var tint = terrain.Tint;
- var imageAttributes = new ImageAttributes();
- if (tint != Color.White)
- {
- var colorMatrix = new ColorMatrix(new float[][]
- {
- new float[] {tint.R / 255.0f, 0, 0, 0, 0},
- new float[] {0, tint.G / 255.0f, 0, 0, 0},
- new float[] {0, 0, tint.B / 255.0f, 0, 0},
- new float[] {0, 0, 0, tint.A / 255.0f, 0},
- new float[] {0, 0, 0, 0, 1},
- }
- );
- imageAttributes.SetColorMatrix(colorMatrix);
- }
- var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);
- var size = new Size(tile.Image.Width / tileScale, tile.Image.Height / tileScale);
- var terrainBounds = new Rectangle(location, size);
- overlappingRenderList.Add((terrainBounds, g => g.DrawImage(tile.Image, terrainBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes)));
- }
- else
- {
- Debug.Print(string.Format("Terrain {0} ({1}) not found", tileName, terrain.Icon));
- }
- }
- }
- if ((layers & MapLayerFlag.Buildings) != MapLayerFlag.None)
- {
- foreach (var (topLeft, building) in map.Buildings.OfType<Building>())
- {
- if ((locations != null) && !locations.Contains(topLeft))
- {
- continue;
- }
- overlappingRenderList.Add(Render(gameType, map.Theater, topLeft, tileSize, tileScale, building));
- }
- }
- if ((layers & MapLayerFlag.Infantry) != MapLayerFlag.None)
- {
- foreach (var (topLeft, infantryGroup) in map.Technos.OfType<InfantryGroup>())
- {
- if ((locations != null) && !locations.Contains(topLeft))
- {
- continue;
- }
- for (int i = 0; i < infantryGroup.Infantry.Length; ++i)
- {
- var infantry = infantryGroup.Infantry[i];
- if (infantry == null)
- {
- continue;
- }
- overlappingRenderList.Add(Render(map.Theater, topLeft, tileSize, infantry, (InfantryStoppingType)i));
- }
- }
- }
- if ((layers & MapLayerFlag.Units) != MapLayerFlag.None)
- {
- foreach (var (topLeft, unit) in map.Technos.OfType<Unit>())
- {
- if ((locations != null) && !locations.Contains(topLeft))
- {
- continue;
- }
- overlappingRenderList.Add(Render(gameType, map.Theater, topLeft, tileSize, unit));
- }
- }
- foreach (var (location, renderer) in overlappingRenderList.Where(x => !x.Item1.IsEmpty).OrderBy(x => x.Item1.Bottom))
- {
- renderer(graphics);
- }
- }
- public static void Render(GameType gameType, Map map, Graphics graphics, ISet<Point> locations, MapLayerFlag layers)
- {
- Render(gameType, map, graphics, locations, layers, Globals.TileScale);
- }
- public static (Rectangle, Action<Graphics>) Render(TheaterType theater, Point topLeft, Size tileSize, Smudge smudge)
- {
- var tint = smudge.Tint;
- var imageAttributes = new ImageAttributes();
- if (tint != Color.White)
- {
- var colorMatrix = new ColorMatrix(new float[][]
- {
- new float[] {tint.R / 255.0f, 0, 0, 0, 0},
- new float[] {0, tint.G / 255.0f, 0, 0, 0},
- new float[] {0, 0, tint.B / 255.0f, 0, 0},
- new float[] {0, 0, 0, tint.A / 255.0f, 0},
- new float[] {0, 0, 0, 0, 1},
- }
- );
- imageAttributes.SetColorMatrix(colorMatrix);
- }
- if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, smudge.Type.Name, smudge.Icon, out Tile tile))
- {
- var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);
- var smudgeBounds = new Rectangle(location, smudge.Type.RenderSize);
- void render(Graphics g)
- {
- g.DrawImage(tile.Image, smudgeBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
- }
- return (smudgeBounds, render);
- }
- else
- {
- Debug.Print(string.Format("Smudge {0} ({1}) not found", smudge.Type.Name, smudge.Icon));
- return (Rectangle.Empty, (g) => { });
- }
- }
- public static (Rectangle, Action<Graphics>) Render(TheaterType theater, OverlayType[] tiberiumOrGoldTypes, OverlayType[] gemTypes, Point topLeft, Size tileSize, int tileScale, Overlay overlay)
- {
- var name = overlay.Type.Name;
- if (overlay.Type.IsGem)
- {
- name = gemTypes[new Random(randomSeed ^ topLeft.GetHashCode()).Next(tiberiumOrGoldTypes.Length)].Name;
- }
- else if (overlay.Type.IsTiberiumOrGold)
- {
- name = tiberiumOrGoldTypes[new Random(randomSeed ^ topLeft.GetHashCode()).Next(tiberiumOrGoldTypes.Length)].Name;
- }
- if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, name, overlay.Icon, out Tile tile))
- {
- var size = (overlay.Type.IsCrate || overlay.Type.IsFlag) ? new Size(tile.Image.Width / tileScale, tile.Image.Height / tileScale) : tileSize;
- var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height)
- + new Size(tileSize.Width / 2, tileSize.Height / 2)
- - new Size(size.Width / 2, size.Height / 2);
- var overlayBounds = new Rectangle(location, size);
- var tint = overlay.Tint;
- void render(Graphics g)
- {
- var imageAttributes = new ImageAttributes();
- if (tint != Color.White)
- {
- var colorMatrix = new ColorMatrix(new float[][]
- {
- new float[] {tint.R / 255.0f, 0, 0, 0, 0},
- new float[] {0, tint.G / 255.0f, 0, 0, 0},
- new float[] {0, 0, tint.B / 255.0f, 0, 0},
- new float[] {0, 0, 0, tint.A / 255.0f, 0},
- new float[] {0, 0, 0, 0, 1},
- }
- );
- imageAttributes.SetColorMatrix(colorMatrix);
- }
- g.DrawImage(tile.Image, overlayBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
- }
- return (overlayBounds, render);
- }
- else
- {
- Debug.Print(string.Format("Overlay {0} ({1}) not found", overlay.Type.Name, overlay.Icon));
- return (Rectangle.Empty, (g) => { });
- }
- }
- public static (Rectangle, Action<Graphics>) Render(GameType gameType, TheaterType theater, Point topLeft, Size tileSize, int tileScale, Building building)
- {
- var tint = building.Tint;
- var stringFormat = new StringFormat
- {
- Alignment = StringAlignment.Center,
- LineAlignment = StringAlignment.Center
- };
- var fakeBackgroundBrush = new SolidBrush(Color.FromArgb(building.Tint.A / 2, Color.Black));
- var fakeTextBrush = new SolidBrush(Color.FromArgb(building.Tint.A, Color.White));
- var baseBackgroundBrush = new SolidBrush(Color.FromArgb(building.Tint.A / 2, Color.Black));
- var baseTextBrush = new SolidBrush(Color.FromArgb(building.Tint.A, Color.Red));
- var icon = 0;
- if (building.Type.HasTurret)
- {
- icon = BodyShape[Facing32[building.Direction.ID]];
- if (building.Strength < 128)
- {
- switch (gameType)
- {
- case GameType.TiberianDawn:
- icon += 64;
- break;
- case GameType.RedAlert:
- icon += building.Type.Equals("sam") ? 35 : 64;
- break;
- }
- }
- }
- else
- {
- if (building.Strength <= 1)
- {
- icon = -1;
- }
- else if (building.Strength < 128)
- {
- icon = -2;
- if (building.Type.Equals("weap") || building.Type.Equals("weaf"))
- {
- icon = 1;
- }
- else if ((gameType == GameType.TiberianDawn) && building.Type.Equals("proc"))
- {
- icon = 30;
- }
- else if (building.Type.Equals("eye"))
- {
- icon = 16;
- }
- else if (building.Type.Equals("silo"))
- {
- icon = 5;
- }
- else if (building.Type.Equals("fix"))
- {
- icon = 7;
- }
- else if (building.Type.Equals("v19"))
- {
- icon = 14;
- }
- }
- }
- if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, building.Type.Tilename, icon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out Tile tile))
- {
- var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);
- var size = new Size(tile.Image.Width / tileScale, tile.Image.Height / tileScale);
- var maxSize = new Size(building.Type.Size.Width * tileSize.Width, building.Type.Size.Height * tileSize.Height);
- if ((size.Width >= size.Height) && (size.Width > maxSize.Width))
- {
- size.Height = size.Height * maxSize.Width / size.Width;
- size.Width = maxSize.Width;
- }
- else if ((size.Height >= size.Width) && (size.Height > maxSize.Height))
- {
- size.Width = size.Width * maxSize.Height / size.Height;
- size.Height = maxSize.Height;
- }
- var buildingBounds = new Rectangle(location, size);
- Tile factoryOverlayTile = null;
- if (building.Type.FactoryOverlay != null)
- {
- int overlayIcon = 0;
- if (building.Strength < 128)
- {
- switch (gameType)
- {
- case GameType.TiberianDawn:
- overlayIcon = 10;
- break;
- case GameType.RedAlert:
- overlayIcon = 4;
- break;
- }
- }
- Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, building.Type.FactoryOverlay, overlayIcon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out factoryOverlayTile);
- }
- void render(Graphics g)
- {
- var imageAttributes = new ImageAttributes();
- if (tint != Color.White)
- {
- var colorMatrix = new ColorMatrix(new float[][]
- {
- new float[] {tint.R / 255.0f, 0, 0, 0, 0},
- new float[] {0, tint.G / 255.0f, 0, 0, 0},
- new float[] {0, 0, tint.B / 255.0f, 0, 0},
- new float[] {0, 0, 0, tint.A / 255.0f, 0},
- new float[] {0, 0, 0, 0, 1},
- }
- );
- imageAttributes.SetColorMatrix(colorMatrix);
- }
- if (factoryOverlayTile != null)
- {
- g.DrawImage(tile.Image, buildingBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
- g.DrawImage(factoryOverlayTile.Image, buildingBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
- }
- else
- {
- g.DrawImage(tile.Image, buildingBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
- }
- if (building.Type.IsFake)
- {
- var text = Globals.TheGameTextManager["TEXT_UI_FAKE"];
- var textSize = g.MeasureString(text, SystemFonts.CaptionFont) + new SizeF(6.0f, 6.0f);
- var textBounds = new RectangleF(buildingBounds.Location, textSize);
- g.FillRectangle(fakeBackgroundBrush, textBounds);
- g.DrawString(text, SystemFonts.CaptionFont, fakeTextBrush, textBounds, stringFormat);
- }
- if (building.BasePriority >= 0)
- {
- var text = building.BasePriority.ToString();
- var textSize = g.MeasureString(text, SystemFonts.CaptionFont) + new SizeF(6.0f, 6.0f);
- var textBounds = new RectangleF(buildingBounds.Location +
- new Size((int)((buildingBounds.Width - textSize.Width) / 2.0f), (int)(buildingBounds.Height - textSize.Height)),
- textSize
- );
- g.FillRectangle(baseBackgroundBrush, textBounds);
- g.DrawString(text, SystemFonts.CaptionFont, baseTextBrush, textBounds, stringFormat);
- }
- }
- return (buildingBounds, render);
- }
- else
- {
- Debug.Print(string.Format("Building {0} (0) not found", building.Type.Name));
- return (Rectangle.Empty, (g) => { });
- }
- }
- public static (Rectangle, Action<Graphics>) Render(TheaterType theater, Point topLeft, Size tileSize, Infantry infantry, InfantryStoppingType infantryStoppingType)
- {
- var icon = HumanShape[Facing32[infantry.Direction.ID]];
- string teamColor = infantry.House?.UnitTeamColor;
- if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, infantry.Type.Name, icon, Globals.TheTeamColorManager[teamColor], out Tile tile))
- {
- var baseLocation = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height)
- + new Size(tileSize.Width / 2, tileSize.Height / 2);
- var offset = Point.Empty;
- switch (infantryStoppingType)
- {
- case InfantryStoppingType.UpperLeft:
- offset.X = -tileSize.Width / 4;
- offset.Y = -tileSize.Height / 4;
- break;
- case InfantryStoppingType.UpperRight:
- offset.X = tileSize.Width / 4;
- offset.Y = -tileSize.Height / 4;
- break;
- case InfantryStoppingType.LowerLeft:
- offset.X = -tileSize.Width / 4;
- offset.Y = tileSize.Height / 4;
- break;
- case InfantryStoppingType.LowerRight:
- offset.X = tileSize.Width / 4;
- offset.Y = tileSize.Height / 4;
- break;
- }
- baseLocation.Offset(offset);
- var virtualBounds = new Rectangle(
- new Point(baseLocation.X - (tile.OpaqueBounds.Width / 2), baseLocation.Y - tile.OpaqueBounds.Height),
- tile.OpaqueBounds.Size
- );
- var renderBounds = new Rectangle(
- baseLocation - new Size(infantry.Type.RenderSize.Width / 2, infantry.Type.RenderSize.Height / 2),
- infantry.Type.RenderSize
- );
- var tint = infantry.Tint;
- void render(Graphics g)
- {
- var imageAttributes = new ImageAttributes();
- if (tint != Color.White)
- {
- var colorMatrix = new ColorMatrix(new float[][]
- {
- new float[] {tint.R / 255.0f, 0, 0, 0, 0},
- new float[] {0, tint.G / 255.0f, 0, 0, 0},
- new float[] {0, 0, tint.B / 255.0f, 0, 0},
- new float[] {0, 0, 0, tint.A / 255.0f, 0},
- new float[] {0, 0, 0, 0, 1},
- }
- );
- imageAttributes.SetColorMatrix(colorMatrix);
- }
- g.DrawImage(tile.Image, renderBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
- }
- return (virtualBounds, render);
- }
- else
- {
- Debug.Print(string.Format("Infantry {0} ({1}) not found", infantry.Type.Name, icon));
- return (Rectangle.Empty, (g) => { });
- }
- }
- public static (Rectangle, Action<Graphics>) Render(GameType gameType, TheaterType theater, Point topLeft, Size tileSize, Unit unit)
- {
- int icon = 0;
- if (gameType == GameType.TiberianDawn)
- {
- if (unit.Type == TiberianDawn.UnitTypes.GunBoat)
- {
- switch (unit.Direction.Facing)
- {
- case FacingType.NorthEast:
- case FacingType.East:
- case FacingType.SouthEast:
- icon = 96;
- break;
- default:
- icon = 0;
- break;
- }
- }
- else if ((unit.Type == TiberianDawn.UnitTypes.Tric) ||
- (unit.Type == TiberianDawn.UnitTypes.Trex) ||
- (unit.Type == TiberianDawn.UnitTypes.Rapt) ||
- (unit.Type == TiberianDawn.UnitTypes.Steg))
- {
- var facing = ((unit.Direction.ID + 0x10) & 0xFF) >> 5;
- icon = BodyShape[facing + ((facing > 0) ? 24 : 0)];
- }
- else if ((unit.Type == TiberianDawn.UnitTypes.Hover) ||
- (unit.Type == TiberianDawn.UnitTypes.Visceroid))
- {
- icon = 0;
- }
- else
- {
- icon = BodyShape[Facing32[unit.Direction.ID]];
- }
- }
- else if (gameType == GameType.RedAlert)
- {
- if (unit.Type.IsAircraft)
- {
- if ((unit.Type == RedAlert.UnitTypes.Tran) ||
- (unit.Type == RedAlert.UnitTypes.Heli) ||
- (unit.Type == RedAlert.UnitTypes.Hind))
- {
- icon = BodyShape[Facing32[unit.Direction.ID]];
- }
- else
- {
- icon = BodyShape[Facing16[unit.Direction.ID] * 2] / 2;
- }
- }
- else if (unit.Type.IsVessel)
- {
- if ((unit.Type == RedAlert.UnitTypes.Transport) ||
- (unit.Type == RedAlert.UnitTypes.Carrier))
- {
- icon = 0;
- }
- else
- {
- icon = BodyShape[Facing16[unit.Direction.ID] * 2] >> 1;
- }
- }
- else
- {
- if ((unit.Type == RedAlert.UnitTypes.Ant1) ||
- (unit.Type == RedAlert.UnitTypes.Ant2) ||
- (unit.Type == RedAlert.UnitTypes.Ant3))
- {
- icon = ((BodyShape[Facing32[unit.Direction.ID]] + 2) / 4) & 0x07;
- }
- else
- {
- icon = BodyShape[Facing32[unit.Direction.ID]];
- }
- }
- }
- string teamColor = null;
- if (unit.House != null)
- {
- if (!unit.House.OverrideTeamColors.TryGetValue(unit.Type.Name, out teamColor))
- {
- teamColor = unit.House.UnitTeamColor;
- }
- }
- if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, unit.Type.Name, icon, Globals.TheTeamColorManager[teamColor], out Tile tile))
- {
- var location =
- new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height) +
- new Size(tileSize.Width / 2, tileSize.Height / 2);
- var renderBounds = new Rectangle(
- location - new Size(unit.Type.RenderSize.Width / 2, unit.Type.RenderSize.Height / 2),
- unit.Type.RenderSize
- );
- Tile radarTile = null;
- if ((unit.Type == RedAlert.UnitTypes.MGG) ||
- (unit.Type == RedAlert.UnitTypes.MRJammer) ||
- (unit.Type == RedAlert.UnitTypes.Tesla))
- {
- Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, unit.Type.Name, 32, Globals.TheTeamColorManager[teamColor], out radarTile);
- }
- Tile turretTile = null;
- if (unit.Type.HasTurret)
- {
- var turretName = unit.Type.Name;
- var turretIcon = icon + 32;
- if (unit.Type == RedAlert.UnitTypes.Phase)
- {
- turretIcon += 6;
- }
- #if TODO
- else if (unit.Type == RedAlert.UnitTypes.Cruiser)
- {
- turretName = "TURR";
- turretIcon = BodyShape[Facing32[unit.Direction.ID]];
- }
- else if (unit.Type == RedAlert.UnitTypes.Destroyer)
- {
- turretName = "SSAM";
- turretIcon = BodyShape[Facing32[unit.Direction.ID]];
- }
- else if (unit.Type == RedAlert.UnitTypes.PTBoat)
- {
- turretName = "MGUN";
- turretIcon = BodyShape[Facing32[unit.Direction.ID]];
- }
- #endif
- Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, turretName, turretIcon, Globals.TheTeamColorManager[teamColor], out turretTile);
- }
- var tint = unit.Tint;
- void render(Graphics g)
- {
- var imageAttributes = new ImageAttributes();
- if (tint != Color.White)
- {
- var colorMatrix = new ColorMatrix(new float[][]
- {
- new float[] {tint.R / 255.0f, 0, 0, 0, 0},
- new float[] {0, tint.G / 255.0f, 0, 0, 0},
- new float[] {0, 0, tint.B / 255.0f, 0, 0},
- new float[] {0, 0, 0, tint.A / 255.0f, 0},
- new float[] {0, 0, 0, 0, 1},
- }
- );
- imageAttributes.SetColorMatrix(colorMatrix);
- }
- g.DrawImage(tile.Image, renderBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
- if (radarTile != null)
- {
- Point turretAdjust = Point.Empty;
- if (unit.Type == RedAlert.UnitTypes.MGG)
- {
- turretAdjust = TurretAdjust[Facing32[unit.Direction.ID]];
- }
- else if (unit.Type != RedAlert.UnitTypes.Tesla)
- {
- turretAdjust.Y = -5;
- }
- var radarBounds = renderBounds;
- radarBounds.Offset(
- turretAdjust.X * tileSize.Width / Globals.PixelWidth,
- turretAdjust.Y * tileSize.Height / Globals.PixelHeight
- );
- g.DrawImage(radarTile.Image, radarBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
- }
- if (turretTile != null)
- {
- Point turretAdjust = Point.Empty;
- if (gameType == GameType.RedAlert)
- {
- if (unit.Type.IsVessel)
- {
- }
- else if (unit.Type == RedAlert.UnitTypes.Jeep)
- {
- turretAdjust.Y = -4;
- }
- }
- else if (gameType == GameType.TiberianDawn)
- {
- if ((unit.Type == TiberianDawn.UnitTypes.Jeep) ||
- (unit.Type == TiberianDawn.UnitTypes.Buggy))
- {
- turretAdjust.Y = -4;
- }
- else if ((unit.Type == TiberianDawn.UnitTypes.SAM) ||
- (unit.Type == TiberianDawn.UnitTypes.MLRS))
- {
- turretAdjust = TurretAdjust[Facing32[unit.Direction.ID]];
- }
- }
- var turretBounds = renderBounds;
- turretBounds.Offset(
- turretAdjust.X * tileSize.Width / Globals.PixelWidth,
- turretAdjust.Y * tileSize.Height / Globals.PixelHeight
- );
- g.DrawImage(turretTile.Image, turretBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
- }
- }
- return (renderBounds, render);
- }
- else
- {
- Debug.Print(string.Format("Unit {0} ({1}) not found", unit.Type.Name, icon));
- return (Rectangle.Empty, (g) => { });
- }
- }
- }
- }
|