Added classic font rendering for techno triggers.
* Fixed overlap detection of walls in both TD and RA; they can only be obstructed by buildings now. * Fixed bug where editing properties of an object would clear its trigger in the dropdown. * Replaced usages of "6point.fnt" in RA by "editfnt.fnt", because it is constant, while "6point.fnt" differs in lores.mix and hires.mix.
This commit is contained in:
parent
2ff36fbb7c
commit
d14a46cb79
@ -151,7 +151,6 @@ namespace MobiusEditor.Controls
|
||||
captureUnknownImage = ToolStripRenderer.CreateDisabledImage(captureImage);
|
||||
houseComboBox.DataSource = plugin.Map.Houses.Select(t => new TypeItem<HouseType>(t.Type.Name, t.Type)).ToArray();
|
||||
missionComboBox.DataSource = plugin.Map.MissionTypes;
|
||||
UpdateDataSource();
|
||||
Disposed += (sender, e) =>
|
||||
{
|
||||
Object = null;
|
||||
@ -166,14 +165,22 @@ namespace MobiusEditor.Controls
|
||||
|
||||
private void UpdateDataSource()
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
string selected = triggerComboBox.SelectedItem as string;
|
||||
triggerComboBox.DataBindings.Clear();
|
||||
triggerComboBox.SelectedIndexChanged -= this.TriggerComboBox_SelectedIndexChanged;
|
||||
triggerComboBox.DataSource = null;
|
||||
triggerComboBox.Items.Clear();
|
||||
string[] items;
|
||||
Boolean isAircraft = obj is Unit un && un.Type.IsAircraft;
|
||||
Boolean isOnMap = true;
|
||||
bool isAircraft = obj is Unit un && un.Type.IsAircraft;
|
||||
bool isOnMap = true;
|
||||
if (selected == null && obj is ITechno tch)
|
||||
{
|
||||
selected = tch.Trigger;
|
||||
}
|
||||
switch (obj)
|
||||
{
|
||||
case Infantry infantry:
|
||||
@ -206,7 +213,6 @@ namespace MobiusEditor.Controls
|
||||
int sel = triggerComboBox.SelectedIndex;
|
||||
triggerComboBox.SelectedIndexChanged += this.TriggerComboBox_SelectedIndexChanged;
|
||||
triggerComboBox.SelectedItem = items[selectIndex];
|
||||
TriggerComboBox_SelectedIndexChanged(triggerComboBox, new EventArgs());
|
||||
if (sel == selectIndex)
|
||||
{
|
||||
TriggerComboBox_SelectedIndexChanged(triggerComboBox, new EventArgs());
|
||||
|
@ -12,7 +12,8 @@
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.namespace MobiusEditor
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
namespace MobiusEditor
|
||||
{
|
||||
partial class GameInstallationPathForm
|
||||
{
|
||||
|
@ -260,16 +260,16 @@ namespace MobiusEditor.Model
|
||||
|
||||
public enum ClassicFont
|
||||
{
|
||||
/// <summary>Font used for Waypoints</summary>
|
||||
/// <summary>Font used for Waypoints.</summary>
|
||||
Waypoints,
|
||||
/// <summary>Font used for waypoints with longer names. Separate because it needs a smaller font to fit inside one cell.</summary>
|
||||
WaypointsLong,
|
||||
/// <summary>Font used for cell triggers</summary>
|
||||
/// <summary>Font used for cell triggers.</summary>
|
||||
CellTriggers,
|
||||
/// <summary>Font used for techno triggers, except infantry</summary>
|
||||
/// <summary>Font used for techno triggers on multi-cell objects.</summary>
|
||||
TechnoTriggers,
|
||||
/// <summary>Font used for infantry techno triggers. Separate because it might need to be smaller.</summary>
|
||||
InfantryTriggers,
|
||||
/// <summary>Font used for one-cell techno triggers. Separate because it might need to be smaller.</summary>
|
||||
TechnoTriggersSmall,
|
||||
/// <summary>Font used for rebuild priority numbers on buildings.</summary>
|
||||
RebuildPriority,
|
||||
/// <summary>Font used for "FAKE" labels on buildings.</summary>
|
||||
|
@ -252,7 +252,7 @@ namespace MobiusEditor.RedAlert
|
||||
break;
|
||||
case ClassicFont.WaypointsLong:
|
||||
crop = true;
|
||||
fontName = "6point.fnt";
|
||||
fontName = "editfnt.fnt";
|
||||
remap = GetClassicFontRemapSimple(fontName, tsmc, trm, textColor, 2, 3);
|
||||
break;
|
||||
case ClassicFont.CellTriggers:
|
||||
@ -266,14 +266,18 @@ namespace MobiusEditor.RedAlert
|
||||
remap = GetClassicFontRemapSimple(fontName, tsmc, trm, textColor);
|
||||
break;
|
||||
case ClassicFont.TechnoTriggers:
|
||||
case ClassicFont.InfantryTriggers:
|
||||
crop = true;
|
||||
fontName = "editfnt.fnt";
|
||||
remap = GetClassicFontRemapSimple(fontName, tsmc, trm, textColor, 2, 3);
|
||||
break;
|
||||
case ClassicFont.TechnoTriggersSmall:
|
||||
crop = true;
|
||||
fontName = "3point.fnt";
|
||||
remap = GetClassicFontRemapSimple(fontName, tsmc, trm, textColor);
|
||||
break;
|
||||
case ClassicFont.FakeLabels:
|
||||
crop = true;
|
||||
fontName = "6point.fnt";
|
||||
fontName = "editfnt.fnt";
|
||||
remap = GetClassicFontRemapSimple(fontName, tsmc, trm, textColor, 2, 3);
|
||||
break;
|
||||
}
|
||||
|
@ -2476,7 +2476,7 @@ namespace MobiusEditor.RedAlert
|
||||
modified = true;
|
||||
continue;
|
||||
}
|
||||
if ((overlayType.IsWall || overlayType.IsSolid) && Map.Technos.ObjectAt(i, out ICellOccupier techno))
|
||||
if ((overlayType.IsWall || overlayType.IsSolid) && Map.Buildings.ObjectAt(i, out ICellOccupier techno))
|
||||
{
|
||||
string desc = overlayType.IsWall ? "Wall" : "Solid overlay";
|
||||
if (techno is Building building)
|
||||
@ -2484,21 +2484,6 @@ namespace MobiusEditor.RedAlert
|
||||
errors.Add(string.Format("{0} '{1}' overlaps structure '{2}' at cell {3}; skipping.", desc, overlayType.Name, building.Type.Name, i));
|
||||
modified = true;
|
||||
}
|
||||
else if (techno is Terrain terrain)
|
||||
{
|
||||
errors.Add(string.Format("{0} '{1}' overlaps terrain '{2}' at cell {3}; skipping.", desc, overlayType.Name, terrain.Type.Name, i));
|
||||
modified = true;
|
||||
}
|
||||
else if (techno is Unit unit)
|
||||
{
|
||||
errors.Add(string.Format("{0} '{1}' overlaps unit '{2}' at cell {3}; skipping.", desc, overlayType.Name, unit.Type.Name, i));
|
||||
modified = true;
|
||||
}
|
||||
else if (techno is InfantryGroup)
|
||||
{
|
||||
errors.Add(string.Format("{0} '{1}' overlaps infantry at cell {2}; skipping.", desc, overlayType.Name, i));
|
||||
modified = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
errors.Add(string.Format("{0} '{1}' overlaps unknown techno in cell {2}; skipping.", desc, overlayType.Name, i));
|
||||
|
@ -2025,16 +2025,16 @@ namespace MobiusEditor.Render
|
||||
|
||||
public static void RenderAllTechnoTriggers(Graphics graphics, GameInfo gameInfo, OccupierSet<ICellOccupier> mapTechnos, OccupierSet<ICellOccupier> mapBuildings, Rectangle visibleCells, Size tileSize, MapLayerFlag layersToRender, Color color, string toPick, bool excludePick)
|
||||
{
|
||||
string classicFont = null;
|
||||
bool cropClassicFont = false;
|
||||
string classicFontInf = null;
|
||||
bool cropClassicFontInf = false;
|
||||
TeamRemap remapClassicFont = null;
|
||||
TeamRemap remapClassicFontInf = null;
|
||||
string classicFontLarge = null;
|
||||
bool cropClassicFontLarge = false;
|
||||
string classicFontSmall = null;
|
||||
bool cropClassicFontSmall = false;
|
||||
TeamRemap remapClassicFontLarge = null;
|
||||
TeamRemap remapClassicFontSmall = null;
|
||||
if (Globals.TheTilesetManager is TilesetManagerClassic tsmc && Globals.TheTeamColorManager is TeamRemapManager trm)
|
||||
{
|
||||
classicFont = gameInfo.GetClassicFontInfo(ClassicFont.TechnoTriggers, tsmc, trm, color, out cropClassicFont, out remapClassicFont);
|
||||
classicFontInf = gameInfo.GetClassicFontInfo(ClassicFont.InfantryTriggers, tsmc, trm, color, out cropClassicFontInf, out remapClassicFontInf);
|
||||
classicFontLarge = gameInfo.GetClassicFontInfo(ClassicFont.TechnoTriggers, tsmc, trm, color, out cropClassicFontLarge, out remapClassicFontLarge);
|
||||
classicFontSmall = gameInfo.GetClassicFontInfo(ClassicFont.TechnoTriggersSmall, tsmc, trm, color, out cropClassicFontSmall, out remapClassicFontSmall);
|
||||
}
|
||||
double tileScaleHor = tileSize.Width / 128.0;
|
||||
float borderSize = Math.Max(0.5f, tileSize.Width / 60.0f);
|
||||
@ -2051,8 +2051,9 @@ namespace MobiusEditor.Render
|
||||
{
|
||||
if (visibleCells.IntersectsWith(new Rectangle(topLeft, terrain.Type.Size)))
|
||||
{
|
||||
Size size = new Size(terrain.Type.Size.Width * tileSize.Width, terrain.Type.Size.Height * tileSize.Height);
|
||||
triggers = new (string, Rectangle, int)[] { (terrain.Trigger, new Rectangle(location, size), terrain.IsPreview ? Globals.PreviewAlphaInt : 255) };
|
||||
Size size = new Size(terrain.Type.Size.Width * Globals.OriginalTileWidth, terrain.Type.Size.Height * Globals.OriginalTileHeight);
|
||||
triggers = new (string, Rectangle, int)[] { (terrain.Trigger, new Rectangle(location, size),
|
||||
terrain.IsPreview ? Globals.PreviewAlphaInt : 256) };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2062,7 +2063,8 @@ namespace MobiusEditor.Render
|
||||
{
|
||||
if (visibleCells.Contains(topLeft))
|
||||
{
|
||||
triggers = new (string, Rectangle, int)[] { (unit.Trigger, new Rectangle(location, tileSize), unit.IsPreview ? Globals.PreviewAlphaInt : 255) };
|
||||
triggers = new (string, Rectangle, int)[] { (unit.Trigger, new Rectangle(location, Globals.OriginalTileSize),
|
||||
unit.IsPreview ? Globals.PreviewAlphaInt : 256) };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2082,7 +2084,7 @@ namespace MobiusEditor.Render
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Size size = tileSize;
|
||||
Size size = Globals.OriginalTileSize;
|
||||
Size offset = Size.Empty;
|
||||
switch ((InfantryStoppingType)i)
|
||||
{
|
||||
@ -2104,7 +2106,7 @@ namespace MobiusEditor.Render
|
||||
break;
|
||||
}
|
||||
Rectangle bounds = new Rectangle(location + offset, size);
|
||||
infantryTriggers.Add((infantry.Trigger, bounds, infantry.IsPreview ? Globals.PreviewAlphaInt : 255));
|
||||
infantryTriggers.Add((infantry.Trigger, bounds, infantry.IsPreview ? Globals.PreviewAlphaInt : 256));
|
||||
}
|
||||
triggers = infantryTriggers.ToArray();
|
||||
}
|
||||
@ -2126,8 +2128,9 @@ namespace MobiusEditor.Render
|
||||
{
|
||||
if (visibleCells.IntersectsWith(new Rectangle(topLeft, building.Type.Size)))
|
||||
{
|
||||
Size size = new Size(building.Type.Size.Width * tileSize.Width, building.Type.Size.Height * tileSize.Height);
|
||||
allTriggers.Add((building.Trigger, new Rectangle(location, size), building.IsPreview ? Globals.PreviewAlphaInt : 255));
|
||||
Size size = new Size(building.Type.Size.Width * Globals.OriginalTileWidth, building.Type.Size.Height * Globals.OriginalTileHeight);
|
||||
allTriggers.Add((building.Trigger, new Rectangle(location, size),
|
||||
building.IsPreview ? Globals.PreviewAlphaInt : 256));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2142,19 +2145,56 @@ namespace MobiusEditor.Render
|
||||
|| (excludePick && !x.trigger.Equals(toPick, StringComparison.OrdinalIgnoreCase))
|
||||
|| (!excludePick && x.trigger.Equals(toPick, StringComparison.OrdinalIgnoreCase))))
|
||||
{
|
||||
Color alphaColor = Color.FromArgb(alpha, color);
|
||||
using (SolidBrush technoTriggerBackgroundBrush = new SolidBrush(Color.FromArgb(96 * alpha / 256, Color.Black)))
|
||||
using (SolidBrush technoTriggerBrush = new SolidBrush(alphaColor))
|
||||
using (Pen technoTriggerPen = new Pen(alphaColor, borderSize))
|
||||
using (Font font = graphics.GetAdjustedFont(trigger, SystemFonts.DefaultFont, bounds.Width, bounds.Height,
|
||||
Math.Max(1, (int)Math.Round(12 * tileScaleHor)), Math.Max(1, (int)Math.Round(24 * tileScaleHor)), stringFormat, true))
|
||||
// Larger than a single cell.
|
||||
bool isLarge = bounds.Width > Globals.OriginalTileWidth;
|
||||
string classicFont = isLarge ? classicFontLarge : classicFontSmall;
|
||||
bool cropClassicFont = isLarge ? cropClassicFontLarge : cropClassicFontSmall;
|
||||
TeamRemap remapClassicFont = isLarge ? remapClassicFontLarge : remapClassicFontSmall;
|
||||
Color alphaColor = Color.FromArgb(alpha.Restrict(0,255), color);
|
||||
if (classicFont == null)
|
||||
{
|
||||
SizeF textBounds = graphics.MeasureString(trigger, font, bounds.Width, stringFormat);
|
||||
RectangleF backgroundBounds = new RectangleF(bounds.Location, textBounds);
|
||||
backgroundBounds.Offset((bounds.Width - textBounds.Width) / 2.0f, (bounds.Height - textBounds.Height) / 2.0f);
|
||||
graphics.FillRectangle(technoTriggerBackgroundBrush, backgroundBounds);
|
||||
graphics.DrawRectangle(technoTriggerPen, Rectangle.Round(backgroundBounds));
|
||||
graphics.DrawString(trigger, font, technoTriggerBrush, bounds, stringFormat);
|
||||
int width = bounds.Width * tileSize.Width / Globals.OriginalTileWidth;
|
||||
int height = bounds.Height * tileSize.Height / Globals.OriginalTileHeight;
|
||||
Rectangle realBounds = new Rectangle(bounds.Location, new Size(width, height));
|
||||
using (SolidBrush technoTriggerBackgroundBrush = new SolidBrush(Color.FromArgb((96 * alpha / 256).Restrict(0, 255), Color.Black)))
|
||||
using (SolidBrush technoTriggerBrush = new SolidBrush(alphaColor))
|
||||
using (Pen technoTriggerPen = new Pen(alphaColor, borderSize))
|
||||
using (Font font = graphics.GetAdjustedFont(trigger, SystemFonts.DefaultFont, width, height,
|
||||
Math.Max(1, (int)Math.Round(12 * tileScaleHor)), Math.Max(1, (int)Math.Round(24 * tileScaleHor)), stringFormat, true))
|
||||
{
|
||||
SizeF textBounds = graphics.MeasureString(trigger, font, width, stringFormat);
|
||||
RectangleF backgroundBounds = new RectangleF(bounds.Location, textBounds);
|
||||
backgroundBounds.Offset((width - textBounds.Width) / 2.0f, (height - textBounds.Height) / 2.0f);
|
||||
graphics.FillRectangle(technoTriggerBackgroundBrush, backgroundBounds);
|
||||
graphics.DrawRectangle(technoTriggerPen, Rectangle.Round(backgroundBounds));
|
||||
graphics.DrawString(trigger, font, technoTriggerBrush, realBounds, stringFormat);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] indices = Encoding.ASCII.GetBytes(trigger).Select(x => (int)x).ToArray();
|
||||
using (SolidBrush technoTriggerBackgroundBrush = new SolidBrush(Color.FromArgb(96, Color.Black)))
|
||||
using (Pen technoTriggerPen = new Pen(color, 1))
|
||||
using (Bitmap txt = RenderTextFromSprite(classicFont, remapClassicFont, Size.Empty, indices, false, cropClassicFont))
|
||||
using (Bitmap txt2 = new Bitmap(txt.Width + 4, txt.Height + 4))
|
||||
using (ImageAttributes imageAttributes = new ImageAttributes())
|
||||
{
|
||||
txt2.SetResolution(96, 96);
|
||||
using (Graphics txt2g = Graphics.FromImage(txt2))
|
||||
{
|
||||
txt2g.FillRectangle(technoTriggerBackgroundBrush, new Rectangle(1, 1, txt2.Width - 2, txt2.Height - 2));
|
||||
txt2g.DrawRectangle(technoTriggerPen, new Rectangle(0, 0, txt2.Width - 1, txt2.Height - 1));
|
||||
txt2g.DrawImage(txt, new Rectangle(2, 2, txt.Width, txt.Height));
|
||||
}
|
||||
imageAttributes.SetColorMatrix(GetColorMatrix(Color.White, 1.0f, alpha / 256.0f));
|
||||
int paintOffsX = (bounds.Width - txt2.Width) / 2 * tileSize.Width / Globals.OriginalTileWidth;
|
||||
int paintOffsY = (bounds.Height - txt2.Height) / 2 * tileSize.Width / Globals.OriginalTileWidth;
|
||||
int textWidth = txt2.Width * tileSize.Width / Globals.OriginalTileWidth;
|
||||
int textHeight = txt2.Height * tileSize.Width / Globals.OriginalTileWidth;
|
||||
Rectangle paintBounds = new Rectangle(bounds.Location, new Size(textWidth, textHeight));
|
||||
paintBounds.Offset(new Point(paintOffsX, paintOffsY));
|
||||
graphics.DrawImage(txt2, paintBounds, 0, 0, txt2.Width, txt2.Height, GraphicsUnit.Pixel, imageAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2244,7 +2284,6 @@ namespace MobiusEditor.Render
|
||||
Globals.TheShapeCacheManager.AddImage(wpId, wpBm);
|
||||
Rectangle paintRect = new Rectangle(paintBounds.Location.X, paintBounds.Location.Y, wpBm.Width, wpBm.Height);
|
||||
graphics.DrawImage(wpBm, paintRect, 0, 0, wpBm.Width, wpBm.Height, GraphicsUnit.Pixel, imageAttributes);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2883,12 +2922,13 @@ namespace MobiusEditor.Render
|
||||
}
|
||||
else
|
||||
{
|
||||
// Solid overlays in the buildings list.
|
||||
isBuilding = building != null;
|
||||
}
|
||||
bool isTechno = techno != null || isBuilding;
|
||||
// Skip if it's the techno-loop and there's no techno,
|
||||
// or if it's not the techno-loop and there is a techno (to avoid overlap).
|
||||
if ((isTechno && !forTechnos) || (!isTechno && forTechnos))
|
||||
// Skip if it's a techno-loop and there's no techno,
|
||||
// or if it's not a techno-loop and there is a techno (to avoid overlap).
|
||||
if ((forTechnos && !isTechno) || (!forTechnos && isTechno))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -3165,9 +3205,12 @@ namespace MobiusEditor.Render
|
||||
int curWidth = 0;
|
||||
if (lineLength == 0 || maxHeight - minTop == 0)
|
||||
{
|
||||
return new Bitmap(2, 2);
|
||||
Bitmap bm = new Bitmap(2, 2);
|
||||
bm.SetResolution(96, 96);
|
||||
return bm;
|
||||
}
|
||||
Bitmap bitmap = new Bitmap(lineLength, maxHeight - minTop, PixelFormat.Format32bppArgb);
|
||||
bitmap.SetResolution(96, 96);
|
||||
using (Graphics g = Graphics.FromImage(bitmap))
|
||||
{
|
||||
for (int i = 0; i < nrOfChars; ++i)
|
||||
|
@ -179,7 +179,11 @@ namespace MobiusEditor.TiberianDawn
|
||||
remap = GetClassicFontRemapSimple(fontName, tsmc, trm, textColor);
|
||||
break;
|
||||
case ClassicFont.TechnoTriggers:
|
||||
case ClassicFont.InfantryTriggers:
|
||||
crop = true;
|
||||
fontName = "scorefnt.fnt";
|
||||
remap = GetClassicFontRemapSimple(fontName, tsmc, trm, textColor);
|
||||
break;
|
||||
case ClassicFont.TechnoTriggersSmall:
|
||||
crop = true;
|
||||
fontName = "3point.fnt";
|
||||
remap = GetClassicFontRemapSimple(fontName, tsmc, trm, textColor);
|
||||
|
@ -2117,7 +2117,7 @@ namespace MobiusEditor.TiberianDawn
|
||||
modified = true;
|
||||
continue;
|
||||
}
|
||||
if ((overlayType.IsWall || overlayType.IsSolid) && Map.Technos.ObjectAt(cell, out ICellOccupier techno))
|
||||
if ((overlayType.IsWall || overlayType.IsSolid) && Map.Buildings.ObjectAt(cell, out ICellOccupier techno))
|
||||
{
|
||||
string desc = overlayType.IsWall ? "Wall" : "Solid overlay";
|
||||
if (techno is Building building)
|
||||
@ -2125,19 +2125,9 @@ namespace MobiusEditor.TiberianDawn
|
||||
errors.Add(string.Format("{0} '{1}' overlaps structure '{2}' at cell {3}; skipping.", desc, overlayType.Name, building.Type.Name, cell));
|
||||
modified = true;
|
||||
}
|
||||
else if (techno is Terrain terrain)
|
||||
else if (techno is Overlay ovl)
|
||||
{
|
||||
errors.Add(string.Format("{0} '{1}' overlaps terrain '{2}' at cell {3}; skipping.", desc, overlayType.Name, terrain.Type.Name, cell));
|
||||
modified = true;
|
||||
}
|
||||
else if (techno is Unit unit)
|
||||
{
|
||||
errors.Add(string.Format("{0} '{1}' overlaps unit '{2}' at cell {3}; skipping.", desc, overlayType.Name, unit.Type.Name, cell));
|
||||
modified = true;
|
||||
}
|
||||
else if (techno is InfantryGroup)
|
||||
{
|
||||
errors.Add(string.Format("{0} '{1}' overlaps infantry at cell {2}; skipping.", desc, overlayType.Name, cell));
|
||||
errors.Add(string.Format("{0} '{1}' overlaps overlay '{2}' at cell {3}; skipping.", desc, overlayType.Name, ovl.Type.Name, cell));
|
||||
modified = true;
|
||||
}
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user