Cleaner loading of dummy data.

This commit is contained in:
Nyeguds 2022-08-01 18:20:48 +02:00
parent b830a1df52
commit 2000c8c99d
6 changed files with 166 additions and 59 deletions

View File

@ -47,6 +47,10 @@ namespace MobiusEditor.Model
public Image Thumbnail { get; set; } public Image Thumbnail { get; set; }
public String GraphicsSource { get; private set; }
public int ForceTileNr { get; private set; }
public bool[,] OccupyMask => new bool[1, 1] { { true } }; public bool[,] OccupyMask => new bool[1, 1] { { true } };
public bool IsResource => (Flag & (OverlayTypeFlag.TiberiumOrGold | OverlayTypeFlag.Gems)) != OverlayTypeFlag.None; public bool IsResource => (Flag & (OverlayTypeFlag.TiberiumOrGold | OverlayTypeFlag.Gems)) != OverlayTypeFlag.None;
@ -64,15 +68,22 @@ namespace MobiusEditor.Model
// No reason not to allow placing decorations and flag pedestal. // No reason not to allow placing decorations and flag pedestal.
public bool IsPlaceable => (Flag & (OverlayTypeFlag.Crate | OverlayTypeFlag.Decoration | OverlayTypeFlag.Flag)) != OverlayTypeFlag.None; public bool IsPlaceable => (Flag & (OverlayTypeFlag.Crate | OverlayTypeFlag.Decoration | OverlayTypeFlag.Flag)) != OverlayTypeFlag.None;
public OverlayType(sbyte id, string name, string textId, TheaterType[] theaters, OverlayTypeFlag flag) public OverlayType(sbyte id, string name, string textId, TheaterType[] theaters, OverlayTypeFlag flag, String graphicsLoadOverride, int forceTileNr)
{ {
ID = id; ID = id;
Name = name; Name = name;
DisplayName = Globals.TheGameTextManager[textId] + " (" + Name.ToUpperInvariant() + ")"; GraphicsSource = graphicsLoadOverride == null ? name : graphicsLoadOverride;
ForceTileNr = forceTileNr;
DisplayName = Globals.TheGameTextManager[textId] + " (" + GraphicsSource.ToUpperInvariant() + ")";
Theaters = theaters; Theaters = theaters;
Flag = flag; Flag = flag;
} }
public OverlayType(sbyte id, string name, string textId, TheaterType[] theaters, OverlayTypeFlag flag)
:this(id, name, textId, theaters, flag, null, -1)
{
}
public OverlayType(sbyte id, string name, string textId, OverlayTypeFlag flag) public OverlayType(sbyte id, string name, string textId, OverlayTypeFlag flag)
: this(id, name, textId, null, flag) : this(id, name, textId, null, flag)
{ {
@ -124,7 +135,8 @@ namespace MobiusEditor.Model
public void Init(TheaterType theater) public void Init(TheaterType theater)
{ {
var oldImage = Thumbnail; var oldImage = Thumbnail;
if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, Name, 0, out Tile tile, (Flag & OverlayTypeFlag.Decoration) != 0)) int tilenr = ForceTileNr == -1 ? 0 : ForceTileNr;
if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, GraphicsSource, tilenr, out Tile tile, (Flag & OverlayTypeFlag.Decoration) != 0))
{ {
var size = tile.Image.Size; var size = tile.Image.Size;
var maxSize = new Size(Globals.OriginalTileWidth, Globals.OriginalTileWidth); var maxSize = new Size(Globals.OriginalTileWidth, Globals.OriginalTileWidth);

View File

@ -47,7 +47,12 @@ namespace MobiusEditor.Model
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public object Clone() public object ICloneable.Clone()
{
return Clone();
}
public Smudge Clone()
{ {
return new Smudge() return new Smudge()
{ {

View File

@ -109,9 +109,7 @@ namespace MobiusEditor.Render
var tileSize = new Size(Globals.OriginalTileWidth / tileScale, Globals.OriginalTileHeight / tileScale); var tileSize = new Size(Globals.OriginalTileWidth / tileScale, Globals.OriginalTileHeight / tileScale);
var tiberiumOrGoldTypes = map.OverlayTypes.Where(t => t.IsTiberiumOrGold).Select(t => t).ToArray(); var tiberiumOrGoldTypes = map.OverlayTypes.Where(t => t.IsTiberiumOrGold).Select(t => t).ToArray();
var gemTypes = map.OverlayTypes.Where(t => t.IsGem).ToArray(); var gemTypes = map.OverlayTypes.Where(t => t.IsGem).ToArray();
var overlappingRenderList = new List<(Rectangle, Action<Graphics>)>(); var overlappingRenderList = new List<(Rectangle, Action<Graphics>)>();
Func<IEnumerable<Point>> renderLocations = null; Func<IEnumerable<Point>> renderLocations = null;
if (locations != null) if (locations != null)
{ {
@ -131,18 +129,15 @@ namespace MobiusEditor.Render
} }
renderLocations = allCells; renderLocations = allCells;
} }
if ((layers & MapLayerFlag.Template) != MapLayerFlag.None) if ((layers & MapLayerFlag.Template) != MapLayerFlag.None)
{ {
foreach (var topLeft in renderLocations()) foreach (var topLeft in renderLocations())
{ {
map.Metrics.GetCell(topLeft, out int cell); map.Metrics.GetCell(topLeft, out int cell);
var template = map.Templates[topLeft]; var template = map.Templates[topLeft];
TemplateType ttype = template?.Type ?? map.TemplateTypes.Where(t => t.Flag == TemplateTypeFlag.Clear).FirstOrDefault(); TemplateType ttype = template?.Type ?? map.TemplateTypes.Where(t => t.Flag == TemplateTypeFlag.Clear).FirstOrDefault();
var name = ttype.Name; var name = ttype.Name;
var icon = template?.Icon ?? ((cell & 0x03) | ((cell >> 4) & 0x0C)); var icon = template?.Icon ?? ((cell & 0x03) | ((cell >> 4) & 0x0C));
if (Globals.TheTilesetManager.GetTileData(map.Theater.Tilesets, name, icon, out Tile tile)) 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); var renderBounds = new Rectangle(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height, tileSize.Width, tileSize.Height);
@ -176,7 +171,6 @@ namespace MobiusEditor.Render
{ {
continue; continue;
} }
if ((overlay.Type.IsResource && ((layers & MapLayerFlag.Resources) != MapLayerFlag.None)) || if ((overlay.Type.IsResource && ((layers & MapLayerFlag.Resources) != MapLayerFlag.None)) ||
(overlay.Type.IsWall && ((layers & MapLayerFlag.Walls) != MapLayerFlag.None)) || (overlay.Type.IsWall && ((layers & MapLayerFlag.Walls) != MapLayerFlag.None)) ||
((layers & MapLayerFlag.Overlay) != MapLayerFlag.None)) ((layers & MapLayerFlag.Overlay) != MapLayerFlag.None))
@ -194,13 +188,11 @@ namespace MobiusEditor.Render
{ {
continue; continue;
} }
string tileName = terrain.Type.Name; string tileName = terrain.Type.Name;
if ((terrain.Type.TemplateType & TemplateTypeFlag.OreMine) != TemplateTypeFlag.None) if ((terrain.Type.TemplateType & TemplateTypeFlag.OreMine) != TemplateTypeFlag.None)
{ {
tileName = "OREMINE"; tileName = "OREMINE";
} }
if (Globals.TheTilesetManager.GetTileData(map.Theater.Tilesets, tileName, terrain.Icon, out Tile tile)) if (Globals.TheTilesetManager.GetTileData(map.Theater.Tilesets, tileName, terrain.Icon, out Tile tile))
{ {
var tint = terrain.Tint; var tint = terrain.Tint;
@ -218,7 +210,6 @@ namespace MobiusEditor.Render
); );
imageAttributes.SetColorMatrix(colorMatrix); imageAttributes.SetColorMatrix(colorMatrix);
} }
var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height); 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 size = new Size(tile.Image.Width / tileScale, tile.Image.Height / tileScale);
var maxSize = new Size(terrain.Type.Size.Width * tileSize.Width, terrain.Type.Size.Height * tileSize.Height); var maxSize = new Size(terrain.Type.Size.Width * tileSize.Width, terrain.Type.Size.Height * tileSize.Height);
@ -246,7 +237,6 @@ namespace MobiusEditor.Render
} }
} }
} }
if ((layers & MapLayerFlag.Buildings) != MapLayerFlag.None) if ((layers & MapLayerFlag.Buildings) != MapLayerFlag.None)
{ {
foreach (var (topLeft, building) in map.Buildings.OfType<Building>()) foreach (var (topLeft, building) in map.Buildings.OfType<Building>())
@ -255,11 +245,9 @@ namespace MobiusEditor.Render
{ {
continue; continue;
} }
overlappingRenderList.Add(Render(gameType, map.Theater, topLeft, tileSize, tileScale, building)); overlappingRenderList.Add(Render(gameType, map.Theater, topLeft, tileSize, tileScale, building));
} }
} }
if ((layers & MapLayerFlag.Infantry) != MapLayerFlag.None) if ((layers & MapLayerFlag.Infantry) != MapLayerFlag.None)
{ {
foreach (var (topLeft, infantryGroup) in map.Technos.OfType<InfantryGroup>()) foreach (var (topLeft, infantryGroup) in map.Technos.OfType<InfantryGroup>())
@ -268,7 +256,6 @@ namespace MobiusEditor.Render
{ {
continue; continue;
} }
for (int i = 0; i < infantryGroup.Infantry.Length; ++i) for (int i = 0; i < infantryGroup.Infantry.Length; ++i)
{ {
var infantry = infantryGroup.Infantry[i]; var infantry = infantryGroup.Infantry[i];
@ -276,12 +263,10 @@ namespace MobiusEditor.Render
{ {
continue; continue;
} }
overlappingRenderList.Add(Render(map.Theater, topLeft, tileSize, infantry, (InfantryStoppingType)i)); overlappingRenderList.Add(Render(map.Theater, topLeft, tileSize, infantry, (InfantryStoppingType)i));
} }
} }
} }
if ((layers & MapLayerFlag.Units) != MapLayerFlag.None) if ((layers & MapLayerFlag.Units) != MapLayerFlag.None)
{ {
foreach (var (topLeft, unit) in map.Technos.OfType<Unit>()) foreach (var (topLeft, unit) in map.Technos.OfType<Unit>())
@ -290,11 +275,9 @@ namespace MobiusEditor.Render
{ {
continue; continue;
} }
overlappingRenderList.Add(Render(gameType, map.Theater, topLeft, tileSize, unit)); 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)) foreach (var (location, renderer) in overlappingRenderList.Where(x => !x.Item1.IsEmpty).OrderBy(x => x.Item1.Bottom))
{ {
renderer(graphics); renderer(graphics);
@ -323,17 +306,14 @@ namespace MobiusEditor.Render
); );
imageAttributes.SetColorMatrix(colorMatrix); imageAttributes.SetColorMatrix(colorMatrix);
} }
if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, smudge.Type.Name, smudge.Icon, out Tile tile)) 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 location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);
var smudgeBounds = new Rectangle(location, smudge.Type.RenderSize); var smudgeBounds = new Rectangle(location, smudge.Type.RenderSize);
void render(Graphics g) void render(Graphics g)
{ {
g.DrawImage(tile.Image, smudgeBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes); g.DrawImage(tile.Image, smudgeBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
} }
return (smudgeBounds, render); return (smudgeBounds, render);
} }
else else
@ -345,7 +325,7 @@ namespace MobiusEditor.Render
public static (Rectangle, Action<Graphics>) Render(TheaterType theater, OverlayType[] tiberiumOrGoldTypes, OverlayType[] gemTypes, Point topLeft, Size tileSize, int tileScale, Overlay overlay) 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; string name;
if (overlay.Type.IsGem) if (overlay.Type.IsGem)
{ {
name = gemTypes[new Random(randomSeed ^ topLeft.GetHashCode()).Next(tiberiumOrGoldTypes.Length)].Name; name = gemTypes[new Random(randomSeed ^ topLeft.GetHashCode()).Next(tiberiumOrGoldTypes.Length)].Name;
@ -354,15 +334,19 @@ namespace MobiusEditor.Render
{ {
name = tiberiumOrGoldTypes[new Random(randomSeed ^ topLeft.GetHashCode()).Next(tiberiumOrGoldTypes.Length)].Name; name = tiberiumOrGoldTypes[new Random(randomSeed ^ topLeft.GetHashCode()).Next(tiberiumOrGoldTypes.Length)].Name;
} }
else
{
name = overlay.Type.GraphicsSource;
}
// For Decoration types, generate dummy if not found. // For Decoration types, generate dummy if not found.
if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, name, overlay.Icon, out Tile tile, (overlay.Type.Flag & OverlayTypeFlag.Decoration) != 0)) int icon = overlay.Type.ForceTileNr == -1 ? overlay.Icon : overlay.Type.ForceTileNr;
if (Globals.TheTilesetManager.GetTileData(theater.Tilesets, name, icon, out Tile tile, (overlay.Type.Flag & OverlayTypeFlag.Decoration) != 0))
{ {
var size = (overlay.Type.IsCrate || overlay.Type.IsFlag) ? new Size(tile.Image.Width / tileScale, tile.Image.Height / tileScale) : tileSize; 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) var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height)
+ new Size(tileSize.Width / 2, tileSize.Height / 2) + new Size(tileSize.Width / 2, tileSize.Height / 2)
- new Size(size.Width / 2, size.Height / 2); - new Size(size.Width / 2, size.Height / 2);
var overlayBounds = new Rectangle(location, size); var overlayBounds = new Rectangle(location, size);
var tint = overlay.Tint; var tint = overlay.Tint;
void render(Graphics g) void render(Graphics g)
{ {
@ -380,15 +364,13 @@ namespace MobiusEditor.Render
); );
imageAttributes.SetColorMatrix(colorMatrix); imageAttributes.SetColorMatrix(colorMatrix);
} }
g.DrawImage(tile.Image, overlayBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes); g.DrawImage(tile.Image, overlayBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
} }
return (overlayBounds, render); return (overlayBounds, render);
} }
else else
{ {
Debug.Print(string.Format("Overlay {0} ({1}) not found", overlay.Type.Name, overlay.Icon)); Debug.Print(string.Format("Overlay {0} ({1}) not found", name, icon));
return (Rectangle.Empty, (g) => { }); return (Rectangle.Empty, (g) => { });
} }
} }
@ -396,7 +378,6 @@ namespace MobiusEditor.Render
public static (Rectangle, Action<Graphics>) Render(GameType gameType, TheaterType theater, Point topLeft, Size tileSize, int tileScale, Building building) public static (Rectangle, Action<Graphics>) Render(GameType gameType, TheaterType theater, Point topLeft, Size tileSize, int tileScale, Building building)
{ {
var tint = building.Tint; var tint = building.Tint;
var stringFormat = new StringFormat var stringFormat = new StringFormat
{ {
Alignment = StringAlignment.Center, Alignment = StringAlignment.Center,
@ -434,7 +415,6 @@ namespace MobiusEditor.Render
icon = damageIcon; icon = damageIcon;
} }
} }
if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, building.Type.Tilename, icon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out Tile tile)) 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 location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);
@ -443,7 +423,6 @@ namespace MobiusEditor.Render
// Graphics are too large. Scale them down using the largest dimension. // Graphics are too large. Scale them down using the largest dimension.
if ((size.Width >= size.Height) && (size.Width > maxSize.Width)) if ((size.Width >= size.Height) && (size.Width > maxSize.Width))
{ {
size.Height = size.Height * maxSize.Width / size.Width; size.Height = size.Height * maxSize.Width / size.Width;
size.Width = maxSize.Width; size.Width = maxSize.Width;
} }
@ -457,7 +436,6 @@ namespace MobiusEditor.Render
int locY = (maxSize.Height - size.Height) / 2 + location.Y; int locY = (maxSize.Height - size.Height) / 2 + location.Y;
var paintBounds = new Rectangle(locX, locY, size.Width, size.Height); var paintBounds = new Rectangle(locX, locY, size.Width, size.Height);
var buildingBounds = new Rectangle(location, maxSize); var buildingBounds = new Rectangle(location, maxSize);
Tile factoryOverlayTile = null; Tile factoryOverlayTile = null;
// Draw no factory overlay over the collapse frame. // Draw no factory overlay over the collapse frame.
if (building.Type.FactoryOverlay != null && (building.Strength > 1 || !hasCollapseFrame)) if (building.Type.FactoryOverlay != null && (building.Strength > 1 || !hasCollapseFrame))
@ -470,7 +448,6 @@ namespace MobiusEditor.Render
} }
Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, building.Type.FactoryOverlay, overlayIcon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out factoryOverlayTile); Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, building.Type.FactoryOverlay, overlayIcon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out factoryOverlayTile);
} }
void render(Graphics g) void render(Graphics g)
{ {
var imageAttributes = new ImageAttributes(); var imageAttributes = new ImageAttributes();
@ -504,7 +481,6 @@ namespace MobiusEditor.Render
g.DrawString(text, SystemFonts.CaptionFont, fakeTextBrush, textBounds, stringFormat); g.DrawString(text, SystemFonts.CaptionFont, fakeTextBrush, textBounds, stringFormat);
} }
} }
if (building.BasePriority >= 0) if (building.BasePriority >= 0)
{ {
var text = building.BasePriority.ToString(); var text = building.BasePriority.ToString();
@ -521,26 +497,23 @@ namespace MobiusEditor.Render
} }
} }
} }
return (buildingBounds, render); return (buildingBounds, render);
} }
else else
{ {
Debug.Print(string.Format("Building {0} (0) not found", building.Type.Name)); Debug.Print(string.Format("Building {0} (0) not found", building.Type.Name));
return (Rectangle.Empty, (g) => { }); return (Rectangle.Empty, (g) => { });
} }
} }
public static (Rectangle, Action<Graphics>) Render(TheaterType theater, Point topLeft, Size tileSize, Infantry infantry, InfantryStoppingType infantryStoppingType) public static (Rectangle, Action<Graphics>) Render(TheaterType theater, Point topLeft, Size tileSize, Infantry infantry, InfantryStoppingType infantryStoppingType)
{ {
var icon = HumanShape[Facing32[infantry.Direction.ID]]; var icon = HumanShape[Facing32[infantry.Direction.ID]];
string teamColor = infantry.House?.UnitTeamColor; string teamColor = infantry.House?.UnitTeamColor;
if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, infantry.Type.Name, icon, Globals.TheTeamColorManager[teamColor], out Tile tile)) 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) var baseLocation = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height)
+ new Size(tileSize.Width / 2, tileSize.Height / 2); + new Size(tileSize.Width / 2, tileSize.Height / 2);
var offset = Point.Empty; var offset = Point.Empty;
switch (infantryStoppingType) switch (infantryStoppingType)
{ {
@ -562,7 +535,6 @@ namespace MobiusEditor.Render
break; break;
} }
baseLocation.Offset(offset); baseLocation.Offset(offset);
var virtualBounds = new Rectangle( var virtualBounds = new Rectangle(
new Point(baseLocation.X - (tile.OpaqueBounds.Width / 2), baseLocation.Y - tile.OpaqueBounds.Height), new Point(baseLocation.X - (tile.OpaqueBounds.Width / 2), baseLocation.Y - tile.OpaqueBounds.Height),
tile.OpaqueBounds.Size tile.OpaqueBounds.Size
@ -571,7 +543,6 @@ namespace MobiusEditor.Render
baseLocation - new Size(infantry.Type.RenderSize.Width / 2, infantry.Type.RenderSize.Height / 2), baseLocation - new Size(infantry.Type.RenderSize.Width / 2, infantry.Type.RenderSize.Height / 2),
infantry.Type.RenderSize infantry.Type.RenderSize
); );
var tint = infantry.Tint; var tint = infantry.Tint;
void render(Graphics g) void render(Graphics g)
{ {
@ -591,7 +562,6 @@ namespace MobiusEditor.Render
} }
g.DrawImage(tile.Image, renderBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes); g.DrawImage(tile.Image, renderBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
} }
return (virtualBounds, render); return (virtualBounds, render);
} }
else else
@ -692,7 +662,6 @@ namespace MobiusEditor.Render
location - new Size(unit.Type.RenderSize.Width / 2, unit.Type.RenderSize.Height / 2), location - new Size(unit.Type.RenderSize.Width / 2, unit.Type.RenderSize.Height / 2),
unit.Type.RenderSize unit.Type.RenderSize
); );
Tile radarTile = null; Tile radarTile = null;
if ((unit.Type == RedAlert.UnitTypes.MGG) || if ((unit.Type == RedAlert.UnitTypes.MGG) ||
(unit.Type == RedAlert.UnitTypes.MRJammer) || (unit.Type == RedAlert.UnitTypes.MRJammer) ||
@ -700,7 +669,6 @@ namespace MobiusEditor.Render
{ {
Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, unit.Type.Name, 32, Globals.TheTeamColorManager[teamColor], out radarTile); Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, unit.Type.Name, 32, Globals.TheTeamColorManager[teamColor], out radarTile);
} }
Tile turretTile = null; Tile turretTile = null;
if (unit.Type.HasTurret) if (unit.Type.HasTurret)
{ {
@ -777,7 +745,7 @@ namespace MobiusEditor.Render
{ {
if (unit.Type.IsVessel) if (unit.Type.IsVessel)
{ {
// TODO
} }
else if (unit.Type == RedAlert.UnitTypes.Jeep) else if (unit.Type == RedAlert.UnitTypes.Jeep)
{ {
@ -798,17 +766,14 @@ namespace MobiusEditor.Render
turretAdjust = TurretAdjust[Facing32[unit.Direction.ID]]; turretAdjust = TurretAdjust[Facing32[unit.Direction.ID]];
} }
} }
var turretBounds = renderBounds; var turretBounds = renderBounds;
turretBounds.Offset( turretBounds.Offset(
turretAdjust.X * tileSize.Width / Globals.PixelWidth, turretAdjust.X * tileSize.Width / Globals.PixelWidth,
turretAdjust.Y * tileSize.Height / Globals.PixelHeight turretAdjust.Y * tileSize.Height / Globals.PixelHeight
); );
g.DrawImage(turretTile.Image, turretBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes); g.DrawImage(turretTile.Image, turretBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
} }
} }
return (renderBounds, render); return (renderBounds, render);
} }
else else

View File

@ -188,7 +188,8 @@ namespace MobiusEditor.TiberianDawn
using (var iniReader = new StreamReader(iniPath)) using (var iniReader = new StreamReader(iniPath))
using (var binReader = new BinaryReader(new FileStream(binPath, FileMode.Open, FileAccess.Read))) using (var binReader = new BinaryReader(new FileStream(binPath, FileMode.Open, FileAccess.Read)))
{ {
ini.Parse(iniReader); string iniText = FixRoad2Load(iniReader);
ini.Parse(iniText);
errors.AddRange(LoadINI(ini)); errors.AddRange(LoadINI(ini));
LoadBinary(binReader); LoadBinary(binReader);
} }
@ -221,6 +222,78 @@ namespace MobiusEditor.TiberianDawn
return errors; return errors;
} }
private string FixRoad2Load(StreamReader iniReader)
{
string iniText = iniReader.ReadToEnd();
string[] iniTextArr = iniText.Replace("\r\n", "\n").Replace('\r', '\n').Split('\n');
Dictionary<int, int> dupeRoadDetect = new Dictionary<int, int>();
Regex roadRegex = new Regex("^\\s*(\\d+)\\s*=\\s*" + OverlayTypes.Road.Name + "\\s*$", RegexOptions.IgnoreCase);
string road2dummy = "=" + OverlayTypes.Road2.Name.ToUpper();
bool inOverlay = false;
for (int i = 0; i < iniTextArr.Length; ++i)
{
string currLine = iniTextArr[i].Trim();
if (currLine.StartsWith("["))
{
inOverlay = "[Overlay]".Equals(currLine, StringComparison.InvariantCultureIgnoreCase);
continue;
}
if (inOverlay)
{
Match match = roadRegex.Match(currLine);
if (match.Success)
{
int cellNumber = Int32.Parse(match.Groups[1].Value);
int cur = dupeRoadDetect.TryGetValue(cellNumber, out int curVal) ? curVal : 0;
dupeRoadDetect[cellNumber] = cur + 1;
}
}
}
if (dupeRoadDetect.Any(k => k.Value > 1))
{
inOverlay = false;
List<string> newIniText = new List<string>();
for (int i = 0; i < iniTextArr.Length; ++i)
{
string currLine = iniTextArr[i].Trim();
if (currLine.StartsWith("["))
{
inOverlay = "[Overlay]".Equals(currLine, StringComparison.InvariantCultureIgnoreCase);
}
Match match;
if (!inOverlay || !(match = roadRegex.Match(iniTextArr[i])).Success)
{
newIniText.Add(currLine);
}
else
{
int cellNumber = Int32.Parse(match.Groups[1].Value);
int roadAmount;
if (dupeRoadDetect.TryGetValue(cellNumber, out roadAmount))
{
if (roadAmount == 1)
{
newIniText.Add(currLine);
}
else if (roadAmount > 1)
{
newIniText.Add(cellNumber + road2dummy);
// Ensures TryGetValue succeeds, but nothing is written for any following matches.
dupeRoadDetect[cellNumber] = -1;
}
}
}
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < newIniText.Count; ++i)
{
sb.Append(newIniText[i]).Append("\r\n");
}
iniText = sb.ToString();
}
return iniText;
}
private IEnumerable<string> LoadINI(INI ini) private IEnumerable<string> LoadINI(INI ini)
{ {
var errors = new List<string>(); var errors = new List<string>();
@ -878,7 +951,7 @@ namespace MobiusEditor.TiberianDawn
Dictionary<string, string> correctedEdges = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); Dictionary<string, string> correctedEdges = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var edge in Globals.Edges) foreach (var edge in Globals.Edges)
correctedEdges.Add(edge, edge); correctedEdges.Add(edge, edge);
String defaultEdge = Globals.Edges.FirstOrDefault() ?? String.Empty; string defaultEdge = Globals.Edges.FirstOrDefault() ?? string.Empty;
foreach (var house in Map.Houses) foreach (var house in Map.Houses)
{ {
if (house.Type.ID < 0) if (house.Type.ID < 0)
@ -956,7 +1029,8 @@ namespace MobiusEditor.TiberianDawn
SaveINI(ini, fileType); SaveINI(ini, fileType);
using (var iniWriter = new StreamWriter(iniPath)) using (var iniWriter = new StreamWriter(iniPath))
{ {
iniWriter.Write(ini.ToString()); //iniWriter.Write(ini.ToString());
FixRoad2Save(ini, iniWriter);
} }
using (var binStream = new FileStream(binPath, FileMode.Create)) using (var binStream = new FileStream(binPath, FileMode.Create))
@ -1026,6 +1100,36 @@ namespace MobiusEditor.TiberianDawn
return true; return true;
} }
private void FixRoad2Save(INI ini, StreamWriter iniWriter)
{
// Special code to make the second state of ROAD cells work.
string roadLine = "=" + OverlayTypes.Road.Name.ToUpperInvariant() + "\r\n";
Regex roadDetect = new Regex("^\\s*(\\d+)\\s*=\\s*" + OverlayTypes.Road2.Name + "\\s*$", RegexOptions.IgnoreCase);
string[] iniString = ini.ToString().Replace("\r\n", "\n").Replace('\r', '\n').Split('\n');
bool inOverlay = false;
for (int i = 0; i < iniString.Length; i++)
{
string currLine = iniString[i].Trim();
if (currLine.StartsWith("["))
{
inOverlay = "[Overlay]".Equals(currLine, StringComparison.InvariantCultureIgnoreCase);
}
Match match;
if (inOverlay && (match = roadDetect.Match(currLine)).Success)
{
string newRoad = match.Groups[1].Value + roadLine;
// Write twice to achieve second state.
iniWriter.Write(newRoad);
iniWriter.Write(newRoad);
}
else
{
iniWriter.Write(currLine);
iniWriter.Write("\r\n");
}
}
}
private void SaveINI(INI ini, FileType fileType) private void SaveINI(INI ini, FileType fileType)
{ {
if (extraSections != null) if (extraSections != null)
@ -1245,7 +1349,7 @@ namespace MobiusEditor.TiberianDawn
Random rd = new Random(); Random rd = new Random();
foreach (var (cell, overlay) in Map.Overlay) foreach (var (cell, overlay) in Map.Overlay)
{ {
String overlayName = overlay.Type.Name; string overlayName = overlay.Type.Name;
if (tiberium.IsMatch(overlayName)) if (tiberium.IsMatch(overlayName))
overlayName = "TI" + rd.Next(1, 13); overlayName = "TI" + rd.Next(1, 13);
overlaySection[cell.ToString()] = overlayName.ToUpperInvariant(); overlaySection[cell.ToString()] = overlayName.ToUpperInvariant();

View File

@ -41,6 +41,7 @@ namespace MobiusEditor.TiberianDawn
public static readonly OverlayType Tiberium11 = new OverlayType(16, "ti11", OverlayTypeFlag.TiberiumOrGold); public static readonly OverlayType Tiberium11 = new OverlayType(16, "ti11", OverlayTypeFlag.TiberiumOrGold);
public static readonly OverlayType Tiberium12 = new OverlayType(17, "ti12", OverlayTypeFlag.TiberiumOrGold); public static readonly OverlayType Tiberium12 = new OverlayType(17, "ti12", OverlayTypeFlag.TiberiumOrGold);
public static readonly OverlayType Road = new OverlayType(18, "road", "Concrete Road", OverlayTypeFlag.Decoration); public static readonly OverlayType Road = new OverlayType(18, "road", "Concrete Road", OverlayTypeFlag.Decoration);
public static readonly OverlayType Road2 = new OverlayType(19, "road2", "Concrete Road (full)", null, OverlayTypeFlag.Decoration, "road", 1);
// Not available to place down sadly. // Not available to place down sadly.
//public static readonly OverlayType Squishy = new OverlayType(19, "SQUISH", OverlayTypeFlag.Decoration); //public static readonly OverlayType Squishy = new OverlayType(19, "SQUISH", OverlayTypeFlag.Decoration);
public static readonly OverlayType V12 = new OverlayType(20, "v12", "TEXT_STRUCTURE_TITLE_CIV12", new TheaterType[] { TheaterTypes.Temperate }); public static readonly OverlayType V12 = new OverlayType(20, "v12", "TEXT_STRUCTURE_TITLE_CIV12", new TheaterType[] { TheaterTypes.Temperate });

View File

@ -41,6 +41,8 @@ namespace MobiusEditor.Utility
public class Tileset public class Tileset
{ {
private static string DummyFormatTga = "DATA\\ART\\TEXTURES\\SRGB\\FALLBACK_DUMMY\\{0}_{1:D4}.tga";
private class TileData private class TileData
{ {
public int FPS { get; set; } public int FPS { get; set; }
@ -119,27 +121,45 @@ namespace MobiusEditor.Utility
{ {
return false; return false;
} }
if (!this.tiles.TryGetValue(name, out Dictionary<int, TileData> shapes) && !generateFallback) Dictionary<int, TileData> shapes;
if (!this.tiles.TryGetValue(name, out shapes) && !generateFallback)
{ {
return false; return false;
} }
name = name.ToUpperInvariant();
if (shapes == null && generateFallback) if (shapes == null && generateFallback)
{ {
if (shape < 0)
{
shape = 0;
}
string dummy = String.Format(DummyFormatTga, name, shape);
shapes = new Dictionary<int, TileData>(); shapes = new Dictionary<int, TileData>();
TileData dummyData = new TileData(); TileData dummyData = new TileData();
dummyData.Frames = new string[] { "DATA\\ART\\TEXTURES\\SRGB\\FALLBACK_DUMMY\\" + name + "_" + shape.ToString("D4") + ".tga" }; dummyData.Frames = new string[] { dummy };
shapes.Add(0, dummyData); shapes.Add(shape, dummyData);
// Add it, so it's present for the next lookup.
this.tiles[name] = shapes;
} }
if (shape < 0) if (shape < 0)
{ {
shape = Math.Max(0, shapes.Max(kv => kv.Key) + shape + 1); shape = Math.Max(0, shapes.Max(kv => kv.Key) + shape + 1);
} }
if (!shapes.TryGetValue(shape, out TileData tileData)) if (!shapes.TryGetValue(shape, out TileData tileData))
{ {
return false; if (generateFallback)
{
// Shape was found, but specific frame was not. Add it.
string dummy = String.Format(DummyFormatTga, name, shape);
tileData = new TileData();
tileData.Frames = new string[] { dummy };
shapes.Add(shape, tileData);
}
else
{
return false;
}
} }
var key = teamColor?.Name ?? string.Empty; var key = teamColor?.Name ?? string.Empty;
if (!tileData.TeamColorTiles.TryGetValue(key, out Tile[] tileDataTiles)) if (!tileData.TeamColorTiles.TryGetValue(key, out Tile[] tileDataTiles))
{ {