Finished classic graphics mode (besides RA mix encryption).
* Added RA template reading. * Added support for RA infantry remapping. * Fixed bugs in text indicator scaling. * Added separate scaling factors for classic mode. * Added automatic extra scaling to tool list preview graphics to compensate for the smaller classic graphics. * Fixed swapped power usage and production of RA Gap Generator. * Set correct preview House for the Ants and Queen Ant (and larvae). * Fixed logic to load mix files from inside other mix files. * Fixed logic to only apply remap to a specific rectangle inside an image. * Fixed logic to load TD remap schemes. * Added logic to give classic dummy image semitransparent edges. * Fixed logic to check the amount of frames of a sprite in classic mode without side effects. * Fixed bug where the Template tool and the "new from image" dialog used a tile size derived from the map scale factor instead of the preview scale factor to determine in which cell the user clicks.
This commit is contained in:
parent
b611342c18
commit
3f673f8ace
@ -393,6 +393,7 @@
|
||||
<Compile Include="RedAlert\GamePluginRA.cs" />
|
||||
<Compile Include="RedAlert\House.cs" />
|
||||
<Compile Include="RedAlert\HouseTypes.cs" />
|
||||
<Compile Include="RedAlert\InfantryClassicRemap.cs" />
|
||||
<Compile Include="RedAlert\InfantryTypes.cs" />
|
||||
<Compile Include="RedAlert\MissionTypes.cs" />
|
||||
<Compile Include="RedAlert\OverlayTypes.cs" />
|
||||
|
@ -405,6 +405,7 @@ namespace MobiusEditor.Controls
|
||||
|
||||
PreRender?.Invoke(this, new RenderEventArgs(pe.Graphics, fullInvalidation ? null : invalidateCells));
|
||||
Image mapImg = mapImage;
|
||||
MapRenderer.SetRenderSettings(pe.Graphics, SmoothScale);
|
||||
if (mapImg != null)
|
||||
{
|
||||
pe.Graphics.Transform = compositeTransform;
|
||||
@ -412,7 +413,6 @@ namespace MobiusEditor.Controls
|
||||
var oldCompositingQuality = pe.Graphics.CompositingQuality;
|
||||
var oldInterpolationMode = pe.Graphics.InterpolationMode;
|
||||
var oldPixelOffsetMode = pe.Graphics.PixelOffsetMode;
|
||||
MapRenderer.SetRenderSettings(pe.Graphics, SmoothScale);
|
||||
pe.Graphics.DrawImage(mapImg, 0, 0);
|
||||
pe.Graphics.CompositingMode = oldCompositingMode;
|
||||
pe.Graphics.CompositingQuality = oldCompositingQuality;
|
||||
|
@ -360,7 +360,7 @@ namespace MobiusEditor.Dialogs
|
||||
}
|
||||
templateTypeMapPanel.MapImage = selected.Thumbnail;
|
||||
var templateTypeMetrics = new CellMetrics(selected.ThumbnailIconWidth, selected.ThumbnailIconHeight);
|
||||
templateTypeNavigationWidget = new NavigationWidget(templateTypeMapPanel, templateTypeMetrics, Globals.OriginalTileSize, false);
|
||||
templateTypeNavigationWidget = new NavigationWidget(templateTypeMapPanel, templateTypeMetrics, Globals.PreviewTileSize, false);
|
||||
templateTypeNavigationWidget.MouseoverSize = Size.Empty;
|
||||
templateTypeNavigationWidget.Activate();
|
||||
}
|
||||
|
@ -24,8 +24,6 @@ namespace MobiusEditor
|
||||
{
|
||||
static Globals()
|
||||
{
|
||||
SetTileSize(false);
|
||||
double minScale = 1.0 / Math.Min(OriginalTileWidth, OriginalTileHeight);
|
||||
// Startup options
|
||||
UseClassicGraphics = Properties.Settings.Default.UseClassicGraphics;
|
||||
// Defaults
|
||||
@ -36,16 +34,10 @@ namespace MobiusEditor
|
||||
OutlineAllCrates = Properties.Settings.Default.DefaultOutlineAllCrates;
|
||||
CratesOnTop = Properties.Settings.Default.DefaultCratesOnTop;
|
||||
ShowMapGrid = Properties.Settings.Default.DefaultShowMapGrid;
|
||||
ExportTileScale = Math.Min(1, Math.Max(minScale, Math.Abs(Properties.Settings.Default.DefaultExportScale)));
|
||||
ExportSmoothScale = Properties.Settings.Default.DefaultExportScale < 0;
|
||||
// Fine tuning
|
||||
ZoomToBoundsOnLoad = Properties.Settings.Default.ZoomToBoundsOnLoad;
|
||||
MapGridColor = Properties.Settings.Default.MapGridColor;
|
||||
MapBackColor = Color.FromArgb(255, Properties.Settings.Default.MapBackColor);
|
||||
MapTileScale = Math.Min(1, Math.Max(minScale, Math.Abs(Properties.Settings.Default.MapScale)));
|
||||
MapSmoothScale = Properties.Settings.Default.MapScale < 0;
|
||||
PreviewTileScale = Math.Min(1, Math.Max(minScale, Math.Abs(Properties.Settings.Default.PreviewScale)));
|
||||
PreviewSmoothScale = Properties.Settings.Default.PreviewScale < 0;
|
||||
UndoRedoStackSize = Properties.Settings.Default.UndoRedoStackSize;
|
||||
MinimumClampSize = Properties.Settings.Default.MinimumClampSize;
|
||||
// Behavior tweaks
|
||||
@ -69,14 +61,8 @@ namespace MobiusEditor
|
||||
public const string MegafilePath = @"DATA";
|
||||
public const string GameTextFilenameFormat = @"DATA\TEXT\MASTERTEXTFILE_{0}.LOC";
|
||||
|
||||
public static void SetTileSize(bool classic)
|
||||
{
|
||||
OriginalTileWidth = classic ? 24 : 128;
|
||||
OriginalTileHeight = classic ? 24 : 128;
|
||||
}
|
||||
|
||||
public static int OriginalTileWidth { get; private set; }
|
||||
public static int OriginalTileHeight { get; private set; }
|
||||
public static int OriginalTileWidth { get { return UseClassicGraphics ? 24 : 128; } }
|
||||
public static int OriginalTileHeight { get { return UseClassicGraphics ? 24 : 128; } }
|
||||
public static Size OriginalTileSize => new Size(OriginalTileWidth, OriginalTileHeight);
|
||||
|
||||
public const int PixelWidth = 24;
|
||||
@ -92,21 +78,50 @@ namespace MobiusEditor
|
||||
public static bool CratesOnTop { get; set; }
|
||||
public static bool OutlineAllCrates { get; set; }
|
||||
public static bool ShowMapGrid { get; set; }
|
||||
public static double ExportTileScale { get; private set; }
|
||||
public static bool ExportSmoothScale { get; private set; }
|
||||
|
||||
public static double ExportTileScale
|
||||
{
|
||||
get
|
||||
{
|
||||
double defExpScale = UseClassicGraphics ? Properties.Settings.Default.DefaultExportScaleClassic : Properties.Settings.Default.DefaultExportScale;
|
||||
return Math.Max(GetMinScale(), Math.Abs(defExpScale));
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ExportSmoothScale
|
||||
{
|
||||
get
|
||||
{
|
||||
return (UseClassicGraphics ? Properties.Settings.Default.DefaultExportScaleClassic : Properties.Settings.Default.DefaultExportScale) < 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ZoomToBoundsOnLoad { get; private set; }
|
||||
public static Color MapGridColor { get; private set; }
|
||||
public static Color MapBackColor { get; private set; }
|
||||
|
||||
public static double MapTileScale { get; private set; }
|
||||
public static bool MapSmoothScale { get; private set; }
|
||||
private static double GetMinScale(){ return 1.0 / Math.Min(OriginalTileWidth, OriginalTileHeight); }
|
||||
public static double MapTileScale => Math.Max(GetMinScale(), Math.Abs(UseClassicGraphics ? Properties.Settings.Default.MapScaleClassic : Properties.Settings.Default.MapScale));
|
||||
public static bool MapSmoothScale => (UseClassicGraphics ? Properties.Settings.Default.MapScaleClassic : Properties.Settings.Default.MapScale) < 0;
|
||||
public static int MapTileWidth => Math.Max(1, (int)(OriginalTileWidth * MapTileScale));
|
||||
public static int MapTileHeight => Math.Max(1, (int)(OriginalTileHeight * MapTileScale));
|
||||
public static Size MapTileSize => new Size(MapTileWidth, MapTileHeight);
|
||||
|
||||
public static double PreviewTileScale { get; private set; }
|
||||
public static bool PreviewSmoothScale { get; private set; }
|
||||
public static double PreviewTileScale
|
||||
{
|
||||
get
|
||||
{
|
||||
double prevTileScale = Math.Max(GetMinScale(), Math.Abs(Properties.Settings.Default.PreviewScale));
|
||||
if (UseClassicGraphics)
|
||||
{
|
||||
// Adjust to classic graphics' considerably smaller overall size
|
||||
prevTileScale = prevTileScale * 128 / 24;
|
||||
}
|
||||
return prevTileScale;
|
||||
|
||||
}
|
||||
}
|
||||
public static bool PreviewSmoothScale => Properties.Settings.Default.PreviewScale < 0;
|
||||
public static int PreviewTileWidth => Math.Max(1, (int)(OriginalTileWidth * PreviewTileScale));
|
||||
public static int PreviewTileHeight => (int)(OriginalTileHeight * PreviewTileScale);
|
||||
public static Size PreviewTileSize => new Size(PreviewTileWidth, PreviewTileHeight);
|
||||
|
@ -28,5 +28,7 @@ namespace MobiusEditor.Interface
|
||||
bool IsFixedWing { get; }
|
||||
/// <summary>True if this object can harvest resources. This affects the default orders for placing it on the map.</summary>
|
||||
bool IsHarvester { get; }
|
||||
/// <summary>True if this techno type adapts to its house colors.</summary>
|
||||
bool CanRemap { get; }
|
||||
}
|
||||
}
|
||||
|
@ -2435,9 +2435,14 @@ namespace MobiusEditor
|
||||
if (!gotBeacon)
|
||||
{
|
||||
// Beacon only exists in rematered graphics. Get fallback.
|
||||
Globals.TheTilesetManager.GetTileData("armor", 6, out waypoint);
|
||||
int icn = plugin.GameType == GameType.RedAlert ? 15 : 12;
|
||||
Globals.TheTilesetManager.GetTileData("mouse", icn, out waypoint);
|
||||
}
|
||||
Globals.TheTilesetManager.GetTileData("mine.shp", 3, out Tile cellTrigger);
|
||||
if (cellTrigger == null)
|
||||
{
|
||||
Globals.TheTilesetManager.GetTileData("mine", 3, out cellTrigger);
|
||||
}
|
||||
Globals.TheTilesetManager.GetTileData("mine", 3, out Tile cellTrigger);
|
||||
LoadNewIcon(mapToolStripButton, templateTile?.Image, plugin, 0);
|
||||
LoadNewIcon(smudgeToolStripButton, smudge?.Thumbnail, plugin, 1);
|
||||
//LoadNewIcon(overlayToolStripButton, overlayTile?.Image, plugin, 2);
|
||||
|
@ -267,7 +267,7 @@ namespace MobiusEditor.Model
|
||||
render.Item2(g);
|
||||
if (this.IsFake)
|
||||
{
|
||||
MapRenderer.RenderFakeBuildingLabel(g, mockBuilding, Point.Empty, Globals.PreviewTileSize, Globals.PreviewTileScale, false);
|
||||
MapRenderer.RenderFakeBuildingLabel(g, mockBuilding, Point.Empty, Globals.PreviewTileSize, false);
|
||||
}
|
||||
}
|
||||
this.Thumbnail = th;
|
||||
|
@ -32,6 +32,10 @@ namespace MobiusEditor.Model
|
||||
public bool IsFixedWing => false;
|
||||
public bool IsExpansionUnit => (Flag & UnitTypeFlag.IsExpansionUnit) == UnitTypeFlag.IsExpansionUnit;
|
||||
public bool IsHarvester => false;
|
||||
public bool CanRemap => (this.Flag & UnitTypeFlag.NoRemap) != UnitTypeFlag.NoRemap;
|
||||
public string ClassicGraphicsSource { get; private set; }
|
||||
public Byte[] ClassicGraphicsRemap { get; private set; }
|
||||
|
||||
private Size _RenderSize;
|
||||
public Size GetRenderSize(Size cellSize)
|
||||
{
|
||||
@ -41,17 +45,23 @@ namespace MobiusEditor.Model
|
||||
public Bitmap Thumbnail { get; set; }
|
||||
private string nameId;
|
||||
|
||||
public InfantryType(sbyte id, string name, string textId, string ownerHouse, UnitTypeFlag flags)
|
||||
public InfantryType(sbyte id, string name, string textId, string ownerHouse, string remappedFrom, byte[] remapTable, UnitTypeFlag flags)
|
||||
{
|
||||
this.ID = id;
|
||||
this.Name = name;
|
||||
this.nameId = textId;
|
||||
this.OwnerHouse = ownerHouse;
|
||||
this.Flag = flags;
|
||||
this.ClassicGraphicsSource = remappedFrom;
|
||||
this.ClassicGraphicsRemap = remapTable;
|
||||
}
|
||||
|
||||
public InfantryType(sbyte id, string name, string textId, string ownerHouse, UnitTypeFlag flags)
|
||||
: this(id, name, textId, ownerHouse, null, null, flags)
|
||||
{
|
||||
}
|
||||
public InfantryType(sbyte id, string name, string textId, string ownerHouse)
|
||||
: this(id, name, textId, ownerHouse, UnitTypeFlag.None)
|
||||
: this(id, name, textId, ownerHouse, null, null, UnitTypeFlag.None)
|
||||
{
|
||||
}
|
||||
|
||||
@ -89,7 +99,17 @@ namespace MobiusEditor.Model
|
||||
? Globals.TheGameTextManager[nameId] + " (" + Name.ToUpperInvariant() + ")"
|
||||
: Name.ToUpperInvariant();
|
||||
Bitmap oldImage = Thumbnail;
|
||||
if (Globals.TheTilesetManager.GetTileData(Name, 4, out Tile tile))
|
||||
Tile tile;
|
||||
// RA classic infantry remap support.
|
||||
if (this.ClassicGraphicsSource != null && Globals.TheTilesetManager is TilesetManagerClassic tsmc)
|
||||
{
|
||||
tsmc.GetTeamColorTileData(this.Name, 4, null, out tile, true, false, this.ClassicGraphicsSource, this.ClassicGraphicsRemap);
|
||||
}
|
||||
else
|
||||
{
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(this.Name, 4, null, out tile, true, false);
|
||||
}
|
||||
if (tile != null && tile.Image != null)
|
||||
{
|
||||
_RenderSize = tile.Image.Size;
|
||||
}
|
||||
|
@ -1412,7 +1412,7 @@ namespace MobiusEditor.Model
|
||||
}
|
||||
using (Graphics g = Graphics.FromImage(croppedBitmap))
|
||||
{
|
||||
MapRenderer.SetRenderSettings(g, true);
|
||||
MapRenderer.SetRenderSettings(g, smooth);
|
||||
Matrix transform = new Matrix();
|
||||
transform.Scale(previewScale, previewScale);
|
||||
transform.Translate((scaledSize.Width - mapBounds.Width) / 2, (scaledSize.Height - mapBounds.Height) / 2);
|
||||
|
@ -37,6 +37,7 @@ namespace MobiusEditor.Model
|
||||
public bool IsAircraft => false;
|
||||
public bool IsFixedWing => false;
|
||||
public bool IsHarvester => false;
|
||||
public bool CanRemap => false;
|
||||
private string nameId;
|
||||
|
||||
public Size GetRenderSize(Size cellSize)
|
||||
@ -186,7 +187,14 @@ namespace MobiusEditor.Model
|
||||
: Name.ToUpperInvariant();
|
||||
var oldImage = Thumbnail;
|
||||
string tileName = GraphicsSource;
|
||||
if (Globals.TheTilesetManager.GetTileData(tileName, DisplayIcon, out Tile tile))
|
||||
Tile tile;
|
||||
// If the graphics source doesn't yield a result, fall back on actual name.
|
||||
// This fixes the graphics source override for the ore mine not working in classic mode.
|
||||
if (!Globals.TheTilesetManager.GetTileData(tileName, DisplayIcon, out tile))
|
||||
{
|
||||
Globals.TheTilesetManager.GetTileData(this.Name, DisplayIcon, out tile);
|
||||
}
|
||||
if (tile != null)
|
||||
{
|
||||
var tileSize = Globals.PreviewTileSize;
|
||||
var renderSize = new Size(tileSize.Width * Size.Width, tileSize.Height * Size.Height);
|
||||
|
@ -35,12 +35,14 @@ namespace MobiusEditor.Model
|
||||
IsArmed = 1 << 3,
|
||||
/// <summary>Can harvest resources. This affects the default orders for placing it on the map.</summary>
|
||||
IsHarvester = 1 << 4,
|
||||
/// <summary>Can attack units. This affects the default orders for placing it on the map.</summary>
|
||||
NoRemap = 1 << 5,
|
||||
/// <summary>Is a unit that is filtered out of the lists if expansion units are disabled.</summary>
|
||||
IsExpansionUnit = 1 << 5,
|
||||
IsExpansionUnit = 1 << 6,
|
||||
/// <summary>Can show a mobile gap area-of-effect radius indicator.</summary>
|
||||
IsGapGenerator = 1 << 6,
|
||||
IsGapGenerator = 1 << 7,
|
||||
/// <summary>Can show a radar jamming area-of-effect radius indicator.</summary>
|
||||
IsJammer = 1 << 7,
|
||||
IsJammer = 1 << 8,
|
||||
}
|
||||
|
||||
public static class UnitTypeIDMask
|
||||
@ -72,6 +74,7 @@ namespace MobiusEditor.Model
|
||||
public bool IsArmed => (this.Flag & UnitTypeFlag.IsArmed) == UnitTypeFlag.IsArmed;
|
||||
public bool IsHarvester => (this.Flag & UnitTypeFlag.IsHarvester) == UnitTypeFlag.IsHarvester;
|
||||
public bool IsExpansionUnit => (this.Flag & UnitTypeFlag.IsExpansionUnit) == UnitTypeFlag.IsExpansionUnit;
|
||||
public bool CanRemap => (this.Flag & UnitTypeFlag.NoRemap) != UnitTypeFlag.NoRemap;
|
||||
private Size _RenderSize;
|
||||
private string nameId;
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
// GNU General Public License along with permitted additional restrictions
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
|
||||
//#define CLASSICIMPLEMENTED
|
||||
#define CLASSICIMPLEMENTED
|
||||
|
||||
using MobiusEditor.Dialogs;
|
||||
using MobiusEditor.Interface;
|
||||
@ -133,7 +133,6 @@ namespace MobiusEditor
|
||||
|
||||
private static void LoadEditorClassic()
|
||||
{
|
||||
Globals.SetTileSize(true);
|
||||
// The system should scan all mix archives for known filenames of other mix archives so it can do recursive searches.
|
||||
// Mix files should be given in order or depth, so first give ones that are in the folder, then ones that may occur inside others.
|
||||
// The order of load determines the file priority; only the first found occurrence of a file is used.
|
||||
|
20
CnCTDRAMapEditor/Properties/Settings.Designer.cs
generated
20
CnCTDRAMapEditor/Properties/Settings.Designer.cs
generated
@ -12,7 +12,7 @@ namespace MobiusEditor.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@ -131,6 +131,15 @@ namespace MobiusEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("1.0")]
|
||||
public double DefaultExportScaleClassic {
|
||||
get {
|
||||
return ((double)(this["DefaultExportScaleClassic"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
@ -167,6 +176,15 @@ namespace MobiusEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("1.0")]
|
||||
public double MapScaleClassic {
|
||||
get {
|
||||
return ((double)(this["MapScaleClassic"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("1")]
|
||||
|
@ -38,6 +38,9 @@
|
||||
<Setting Name="DefaultExportScale" Type="System.Double" Scope="Application">
|
||||
<Value Profile="(Default)">-0.5</Value>
|
||||
</Setting>
|
||||
<Setting Name="DefaultExportScaleClassic" Type="System.Double" Scope="Application">
|
||||
<Value Profile="(Default)">1.0</Value>
|
||||
</Setting>
|
||||
<Setting Name="ZoomToBoundsOnLoad" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
@ -50,6 +53,9 @@
|
||||
<Setting Name="MapScale" Type="System.Double" Scope="Application">
|
||||
<Value Profile="(Default)">0.5</Value>
|
||||
</Setting>
|
||||
<Setting Name="MapScaleClassic" Type="System.Double" Scope="Application">
|
||||
<Value Profile="(Default)">1.0</Value>
|
||||
</Setting>
|
||||
<Setting Name="PreviewScale" Type="System.Double" Scope="Application">
|
||||
<Value Profile="(Default)">1</Value>
|
||||
</Setting>
|
||||
|
@ -30,7 +30,7 @@ namespace MobiusEditor.RedAlert
|
||||
public static readonly BuildingType Pillbox = new BuildingType(4, "pbox", "TEXT_STRUCTURE_RA_PBOX", 0, 15, 1, 1, null, "Greece");
|
||||
public static readonly BuildingType CamoPillbox = new BuildingType(5, "hbox", "TEXT_STRUCTURE_RA_HBOX", 0, 15, 1, 1, null, "Greece");
|
||||
public static readonly BuildingType Command = new BuildingType(6, "dome", "TEXT_STRUCTURE_RA_DOME", 0, 40, 2, 2, null, "Greece", BuildingTypeFlag.Bib);
|
||||
public static readonly BuildingType GapGenerator = new BuildingType(7, "gap", "TEXT_STRUCTURE_RA_GAP", 60, 0, 1, 2, "0 1", "Greece", 13, BuildingTypeFlag.IsGapGenerator);
|
||||
public static readonly BuildingType GapGenerator = new BuildingType(7, "gap", "TEXT_STRUCTURE_RA_GAP", 0, 60, 1, 2, "0 1", "Greece", 13, BuildingTypeFlag.IsGapGenerator);
|
||||
public static readonly BuildingType Turret = new BuildingType(8, "gun", "TEXT_STRUCTURE_RA_GUN", 0, 40, 1, 1, null, "Greece", BuildingTypeFlag.Turret);
|
||||
public static readonly BuildingType AAGun = new BuildingType(9, "agun", "TEXT_STRUCTURE_RA_AGUN", 0, 50, 1, 2, "0 1", "Greece", BuildingTypeFlag.Turret);
|
||||
public static readonly BuildingType FlameTurret = new BuildingType(10, "ftur", "TEXT_STRUCTURE_RA_FTUR", 0, 20, 1, 1, null, "USSR");
|
||||
@ -52,7 +52,7 @@ namespace MobiusEditor.RedAlert
|
||||
public static readonly BuildingType Mission = new BuildingType(26, "miss", "TEXT_STRUCTURE_RA_MISS", 0, 0, 3, 2, null, "Greece", BuildingTypeFlag.Bib);
|
||||
public static readonly BuildingType ShipYard = new BuildingType(27, "syrd", "TEXT_STRUCTURE_RA_SYRD", 0, 30, 3, 3, null, "Greece");
|
||||
public static readonly BuildingType SubPen = new BuildingType(28, "spen", "TEXT_STRUCTURE_RA_SPEN", 0, 30, 3, 3, null, "USSR");
|
||||
public static readonly BuildingType MissileSilo = new BuildingType(29, "mslo", "TEXT_STRUCTURE_RA_MSLO", 0, 100, 2, 1, null, "Greece", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType MissileSilo = new BuildingType(29, "mslo", "TEXT_STRUCTURE_RA_MSLO", 0, 100, 2, 1, null, "Greece");
|
||||
public static readonly BuildingType ForwardCom = new BuildingType(30, "fcom", "TEXT_STRUCTURE_RA_FCOM", 0, 200, 2, 2, "00 11", "USSR", BuildingTypeFlag.Bib);
|
||||
public static readonly BuildingType Tesla = new BuildingType(31, "tsla", "TEXT_STRUCTURE_RA_TSLA", 0, 150, 1, 2, "0 1", "USSR");
|
||||
public static readonly BuildingType FakeWeapon = new BuildingType(32, "weaf", "TEXT_STRUCTURE_RA_WEAF", 0, 2, 3, 2, null, "Greece", "weap2", "weap", BuildingTypeFlag.Bib | BuildingTypeFlag.Fake);
|
||||
@ -103,9 +103,9 @@ namespace MobiusEditor.RedAlert
|
||||
|
||||
public static readonly BuildingType Barrel = new BuildingType(82, "barl", "TEXT_STRUCTURE_RA_BARL", 0, 0, 1, 1, null, "Neutral", BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType Barrel3 = new BuildingType(83, "brl3", "TEXT_STRUCTURE_RA_BRL3", 0, 0, 1, 1, null, "Neutral", BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType Queen = new BuildingType(84, "quee", "TEXT_STRUCTURE_RA_QUEE", 0, 0, 2, 1, null, "Special");
|
||||
public static readonly BuildingType Larva1 = new BuildingType(85, "lar1", "TEXT_STRUCTURE_RA_LAR1", 0, 0, 1, 1, null, "Special", BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType Larva2 = new BuildingType(86, "lar2", "TEXT_STRUCTURE_RA_LAR2", 0, 0, 1, 1, null, "Special", BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType Queen = new BuildingType(84, "quee", "TEXT_STRUCTURE_RA_QUEE", 0, 0, 2, 1, null, "BadGuy");
|
||||
public static readonly BuildingType Larva1 = new BuildingType(85, "lar1", "TEXT_STRUCTURE_RA_LAR1", 0, 0, 1, 1, null, "BadGuy", BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType Larva2 = new BuildingType(86, "lar2", "TEXT_STRUCTURE_RA_LAR2", 0, 0, 1, 1, null, "BadGuy", BuildingTypeFlag.NoRemap);
|
||||
|
||||
private static readonly BuildingType[] Types;
|
||||
|
||||
|
@ -442,6 +442,7 @@ namespace MobiusEditor.RedAlert
|
||||
{
|
||||
Bitmap mapImg = new Bitmap(Map.Metrics.Width * Globals.MapTileWidth, Map.Metrics.Height * Globals.MapTileHeight);
|
||||
mapImg.SetResolution(96, 96);
|
||||
mapImg.RemoveAlphaOnCurrent();
|
||||
MapImage = mapImg;
|
||||
}
|
||||
}
|
||||
|
154
CnCTDRAMapEditor/RedAlert/InfantryClassicRemap.cs
Normal file
154
CnCTDRAMapEditor/RedAlert/InfantryClassicRemap.cs
Normal file
@ -0,0 +1,154 @@
|
||||
namespace MobiusEditor.RedAlert
|
||||
{
|
||||
/// <summary>
|
||||
/// Split off into its own thing to avoid creating clutter in the InfantryTypes class file.
|
||||
/// </summary>
|
||||
public static class InfantryClassicRemap
|
||||
{
|
||||
public static byte[] RemapCiv2 =
|
||||
{
|
||||
0,1,2,3,4,5,6,209,8,9,10,11,12,13,12,15, // 0..15
|
||||
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 16..31
|
||||
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, // 32..47
|
||||
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, // 48..63
|
||||
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, // 64..79
|
||||
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, // 80..95
|
||||
96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, // 96..111
|
||||
112,113,114,115,116,117,187,188,120,121,122,123,124,125,126,127, // 112..127
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 128..143
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,209, // 144..159
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // 160..175
|
||||
176,177,178,179,180,181,182,183,184,185,186,167, 13,189,190,191, // 176..191
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // 192..207
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // 208..223
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // 224..239
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // 240..255
|
||||
};
|
||||
public static byte[] RemapCiv4 = {
|
||||
0,1,2,3,4,5,6,187,8,9,10,11,12,13,14,15, // 0..15
|
||||
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 16..31
|
||||
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, // 32..47
|
||||
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, // 48..63
|
||||
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, // 64..79
|
||||
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, // 80..95
|
||||
96,97,98,99,100,101,102,103,104,105,106,107,108,118,110,119, // 96..111
|
||||
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, // 112..127
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 128..143
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 144..159
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // 160..175
|
||||
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // 176..191
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,188,207, // 192..207
|
||||
208,209,182,211,212,213,214,215,216,217,218,219,220,221,222,223, // 208..223
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // 224..239
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // 240..255
|
||||
};
|
||||
public static byte[] RemapCiv5 = {
|
||||
0,1,2,3,4,5,6,109,8,9,10,11,131,13,14,15, // 0..15
|
||||
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 16..31
|
||||
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, // 32..47
|
||||
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, // 48..63
|
||||
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, // 64..79
|
||||
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, // 80..95
|
||||
96,97,98,99,100,101,102,103,104,105,106,107,108,177,110,178, // 96..111
|
||||
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, // 112..127
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 128..143
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 144..159
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // 160..175
|
||||
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // 176..191
|
||||
192,193,194,195,196,197,198,199,111,201,202,203,204,205,111,207, // 192..207
|
||||
208,209,182,211,212,213,214,215,216,217,218,219,220,221,222,223, // 208..223
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // 224..239
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // 240..255
|
||||
};
|
||||
public static byte[] RemapCiv6 = {
|
||||
0,1,2,3,4,5,6,120,8,9,10,11,12,13,238,15, // 0..15
|
||||
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 16..31
|
||||
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, // 32..47
|
||||
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, // 48..63
|
||||
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, // 64..79
|
||||
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, // 80..95
|
||||
96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, // 96..111
|
||||
112,113,114,115,116,117,236,206,120,121,122,123,124,125,126,127, // 112..127
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 128..143
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,111, // 144..159
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // 160..175
|
||||
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // 176..191
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // 192..207
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // 208..223
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // 224..239
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // 240..255
|
||||
};
|
||||
public static byte[] RemapCiv7 = {
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,12,13,131,15, // 0..15
|
||||
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 16..31
|
||||
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, // 32..47
|
||||
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, // 48..63
|
||||
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, // 64..79
|
||||
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, // 80..95
|
||||
96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, // 96..111
|
||||
112,113,114,115,116,117,157,212,120,121,122,123,124,125,126,127, // 112..127
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 128..143
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,7, // 144..159
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // 160..175
|
||||
176,177,178,179,180,181,182,183,184,185,186,118,119,189,190,191, // 176..191
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // 192..207
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // 208..223
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // 224..239
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // 240..255
|
||||
};
|
||||
public static byte[] RemapCiv8 = {
|
||||
0,1,2,3,4,5,6,182,8,9,10,11,12,13,131,15, // 0..15
|
||||
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 16..31
|
||||
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, // 32..47
|
||||
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, // 48..63
|
||||
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, // 64..79
|
||||
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, // 80..95
|
||||
96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, // 96..111
|
||||
112,113,114,115,116,117,215,7,120,121,122,123,124,125,126,127, // 112..127
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 128..143
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,182, // 144..159
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // 160..175
|
||||
176,177,178,179,180,181,182,183,184,185,186,198,199,189,190,191, // 176..191
|
||||
192,193,194,195,196,197,198,199,111,201,202,203,204,205,206,207, // 192..207
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // 208..223
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // 224..239
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // 240..255
|
||||
};
|
||||
public static byte[] RemapCiv9 = {
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,12,13,7,15, // 0..15
|
||||
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 16..31
|
||||
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, // 32..47
|
||||
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, // 48..63
|
||||
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, // 64..79
|
||||
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, // 80..95
|
||||
96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, // 96..111
|
||||
112,113,114,115,116,117,163,165,120,121,122,123,124,125,126,127, // 112..127
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 128..143
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,200, // 144..159
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // 160..175
|
||||
176,177,178,179,180,181,182,183,184,185,186,111,13,189,190,191, // 176..191
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // 192..207
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // 208..223
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // 224..239
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // 240..255
|
||||
};
|
||||
public static byte[] RemapCiv10 = {
|
||||
0,1,2,3,4,5,6,137,8,9,10,11,12,13,15,15, // 0..15
|
||||
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 16..31
|
||||
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, // 32..47
|
||||
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, // 48..63
|
||||
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, // 64..79
|
||||
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, // 80..95
|
||||
96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, // 96..111
|
||||
112,113,114,115,116,117,129,131,120,121,122,123,124,125,126,127, // 112..127
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 128..143
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,137, // 144..159
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // 160..175
|
||||
176,177,178,179,180,181,182,183,184,185,186,163,165,189,190,191, // 176..191
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // 192..207
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // 208..223
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // 224..239
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // 240..255
|
||||
};
|
||||
}
|
||||
}
|
@ -32,19 +32,19 @@ namespace MobiusEditor.RedAlert
|
||||
public static readonly InfantryType Medic = new InfantryType(8, "medi", "TEXT_UNIT_RA_MEDI", "Greece", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType General = new InfantryType(9, "gnrl", "TEXT_UNIT_RA_GNRL", "Greece", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType Dog = new InfantryType(10, "dog", "TEXT_UNIT_RA_DOG", "USSR", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType C1 = new InfantryType(11, "c1", "TEXT_UNIT_TITLE_CIV1", "Neutral", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType C2 = new InfantryType(12, "c2", "TEXT_UNIT_TITLE_CIV10", "Neutral");
|
||||
public static readonly InfantryType C3 = new InfantryType(13, "c3", "TEXT_UNIT_TITLE_CIV3", "Neutral");
|
||||
public static readonly InfantryType C4 = new InfantryType(14, "c4", "TEXT_UNIT_TITLE_CIV4", "Neutral");
|
||||
public static readonly InfantryType C5 = new InfantryType(15, "c5", "TEXT_UNIT_TITLE_CIV11", "Neutral");
|
||||
public static readonly InfantryType C6 = new InfantryType(16, "c6", "TEXT_UNIT_TITLE_CIV12", "Neutral");
|
||||
public static readonly InfantryType C7 = new InfantryType(17, "c7", "TEXT_UNIT_TITLE_CIV7", "Neutral", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType C8 = new InfantryType(18, "c8", "TEXT_UNIT_TITLE_CIV8", "Neutral");
|
||||
public static readonly InfantryType C9 = new InfantryType(19, "c9", "TEXT_UNIT_TITLE_CIV9", "Neutral");
|
||||
public static readonly InfantryType C10 = new InfantryType(20, "c10", "TEXT_UNIT_RA_SCIENTIST", "Neutral");
|
||||
public static readonly InfantryType Einstein = new InfantryType(21, "einstein", "TEXT_UNIT_RA_EINSTEIN", "Neutral");
|
||||
public static readonly InfantryType Delphi = new InfantryType(22, "delphi", "TEXT_UNIT_RA_DELPHI", "Neutral", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType DrChan = new InfantryType(23, "chan", "TEXT_UNIT_TITLE_CHAN", "Neutral");
|
||||
public static readonly InfantryType C1 = new InfantryType(11, "c1", "TEXT_UNIT_TITLE_CIV1", "Neutral", UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C2 = new InfantryType(12, "c2", "TEXT_UNIT_TITLE_CIV10", "Neutral", "c1", InfantryClassicRemap.RemapCiv2, UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C3 = new InfantryType(13, "c3", "TEXT_UNIT_TITLE_CIV3", "Neutral", "c2", null, UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C4 = new InfantryType(14, "c4", "TEXT_UNIT_TITLE_CIV4", "Neutral", "c2", InfantryClassicRemap.RemapCiv4, UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C5 = new InfantryType(15, "c5", "TEXT_UNIT_TITLE_CIV11", "Neutral", "c2", InfantryClassicRemap.RemapCiv5, UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C6 = new InfantryType(16, "c6", "TEXT_UNIT_TITLE_CIV12", "Neutral", "c1", InfantryClassicRemap.RemapCiv6, UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C7 = new InfantryType(17, "c7", "TEXT_UNIT_TITLE_CIV7", "Neutral", "c1", InfantryClassicRemap.RemapCiv7, UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C8 = new InfantryType(18, "c8", "TEXT_UNIT_TITLE_CIV8", "Neutral", "c1", InfantryClassicRemap.RemapCiv8, UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C9 = new InfantryType(19, "c9", "TEXT_UNIT_TITLE_CIV9", "Neutral", "c1", InfantryClassicRemap.RemapCiv10, UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C10 = new InfantryType(20, "c10", "TEXT_UNIT_RA_SCIENTIST", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType Einstein = new InfantryType(21, "einstein", "TEXT_UNIT_RA_EINSTEIN", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType Delphi = new InfantryType(22, "delphi", "TEXT_UNIT_RA_DELPHI", "Neutral", UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType DrChan = new InfantryType(23, "chan", "TEXT_UNIT_TITLE_CHAN", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType ShockTrooper = new InfantryType(24, "shok", "TEXT_UNIT_RA_SHOK", "USSR", UnitTypeFlag.IsArmed | UnitTypeFlag.IsExpansionUnit);
|
||||
public static readonly InfantryType Mechanic = new InfantryType(25, "mech", "TEXT_UNIT_RA_MECH", "Greece", UnitTypeFlag.IsArmed | UnitTypeFlag.IsExpansionUnit);
|
||||
|
||||
|
@ -36,9 +36,9 @@ namespace MobiusEditor.RedAlert
|
||||
public static readonly UnitType MCV = new UnitType(11, "mcv", "TEXT_UNIT_RA_MCV", "Greece");
|
||||
public static readonly UnitType V2Launcher = new UnitType(12, "v2rl", "TEXT_UNIT_RA_V2RL", "USSR", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType ConvoyTruck = new UnitType(13, "truk", "TEXT_UNIT_RA_TRUK", "Greece");
|
||||
public static readonly UnitType Ant1 = new UnitType(14, "ant1", "TEXT_UNIT_RA_ANT1", "Special", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Ant2 = new UnitType(15, "ant2", "TEXT_UNIT_RA_ANT2", "Special", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Ant3 = new UnitType(16, "ant3", "TEXT_UNIT_RA_ANT3", "Special", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Ant1 = new UnitType(14, "ant1", "TEXT_UNIT_RA_ANT1", "BadGuy", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Ant2 = new UnitType(15, "ant2", "TEXT_UNIT_RA_ANT2", "Ukraine", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Ant3 = new UnitType(16, "ant3", "TEXT_UNIT_RA_ANT3", "Germany", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Chrono = new UnitType(17, "ctnk", "TEXT_UNIT_RA_CTNK", "Greece", UnitTypeFlag.IsArmed | UnitTypeFlag.IsExpansionUnit);
|
||||
public static readonly UnitType Tesla = new UnitType(18, "ttnk", "TEXT_UNIT_RA_TTNK", "USSR", UnitTypeFlag.IsArmed | UnitTypeFlag.HasTurret | UnitTypeFlag.IsExpansionUnit | UnitTypeFlag.IsJammer);
|
||||
public static readonly UnitType MAD = new UnitType(19, "qtnk", "TEXT_UNIT_RA_QTNK", "USSR", UnitTypeFlag.IsArmed | UnitTypeFlag.IsExpansionUnit);
|
||||
|
@ -200,7 +200,6 @@ namespace MobiusEditor.Render
|
||||
var renderBounds = new Rectangle(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height, tileSize.Width, tileSize.Height);
|
||||
if(tile.Image != null)
|
||||
{
|
||||
//graphics.DrawImage(tile.Image, renderBounds);
|
||||
using (Bitmap tileImg = tile.Image.RemoveAlpha())
|
||||
{
|
||||
graphics.DrawImage(tileImg, renderBounds);
|
||||
@ -458,8 +457,15 @@ namespace MobiusEditor.Render
|
||||
string tileName = terrain.Type.GraphicsSource;
|
||||
if (!Globals.TheTilesetManager.GetTileData(tileName, terrain.Type.DisplayIcon, out Tile tile))
|
||||
{
|
||||
Debug.Print(string.Format("Terrain {0} ({1}) not found", tileName, terrain.Type.DisplayIcon));
|
||||
return (Rectangle.Empty, (g) => { }, false);
|
||||
// Fox for classic ore mine not using GraphicsSource override.
|
||||
if (!String.Equals(terrain.Type.GraphicsSource, terrain.Type.Name, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
if (!Globals.TheTilesetManager.GetTileData(terrain.Type.Name, terrain.Type.DisplayIcon, out tile))
|
||||
{
|
||||
Debug.Print(string.Format("Terrain {0} ({1}) not found", tileName, terrain.Type.DisplayIcon));
|
||||
return (Rectangle.Empty, (g) => { }, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
var tint = terrain.Tint;
|
||||
var imageAttributes = new ImageAttributes();
|
||||
@ -504,7 +510,7 @@ namespace MobiusEditor.Render
|
||||
{
|
||||
maxIcon = Globals.TheTilesetManager.GetTileDataLength(building.Type.GraphicsSource);
|
||||
hasCollapseFrame = (gameType == GameType.TiberianDawn || gameType == GameType.SoleSurvivor) && maxIcon > 1 && maxIcon % 2 == 1;
|
||||
damageIconOffs = maxIcon / 2;
|
||||
damageIconOffs = (maxIcon + (hasCollapseFrame ? 0 : 1)) / 2;
|
||||
collapseIcon = maxIcon - 1;
|
||||
}
|
||||
if (building.Type.HasTurret)
|
||||
@ -526,8 +532,9 @@ namespace MobiusEditor.Render
|
||||
icon += damageIconOffs;
|
||||
}
|
||||
}
|
||||
ITeamColor tc = building.Type.CanRemap ? Globals.TheTeamColorManager[building.House.BuildingTeamColor] : null;
|
||||
if (Globals.TheTilesetManager.GetTeamColorTileData(building.Type.GraphicsSource, icon, tc, out Tile tile))
|
||||
ITeamColor teamColor = building.Type.CanRemap ? Globals.TheTeamColorManager[building.House.BuildingTeamColor] : null;
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(building.Type.GraphicsSource, icon, teamColor, out Tile tile, true, false);
|
||||
if (tile != null && tile.Image != null)
|
||||
{
|
||||
var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);
|
||||
var maxSize = new Size(building.Type.Size.Width * tileSize.Width, building.Type.Size.Height * tileSize.Height);
|
||||
@ -543,7 +550,7 @@ namespace MobiusEditor.Render
|
||||
int maxOverlayIcon = Globals.TheTilesetManager.GetTileDataLength(building.Type.FactoryOverlay);
|
||||
overlayIcon = maxOverlayIcon / 2;
|
||||
}
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(building.Type.FactoryOverlay, overlayIcon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out factoryOverlayTile);
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(building.Type.FactoryOverlay, overlayIcon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out factoryOverlayTile, true, false);
|
||||
}
|
||||
void render(Graphics g)
|
||||
{
|
||||
@ -569,6 +576,7 @@ namespace MobiusEditor.Render
|
||||
factory.SetResolution(96, 96);
|
||||
using (Graphics factoryG = Graphics.FromImage(factory))
|
||||
{
|
||||
factoryG.CopyRenderSettingsFrom(g);
|
||||
var factBounds = RenderBounds(tile.Image.Size, building.Type.Size, tileScale);
|
||||
var ovrlBounds = RenderBounds(factoryOverlayTile.Image.Size, building.Type.Size, tileScale);
|
||||
factoryG.DrawImage(tile.Image, factBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel);
|
||||
@ -597,8 +605,18 @@ namespace MobiusEditor.Render
|
||||
public static (Rectangle, Action<Graphics>, bool) RenderInfantry(Point topLeft, Size tileSize, Infantry infantry, InfantryStoppingType infantryStoppingType)
|
||||
{
|
||||
var icon = HumanShape[Facing32[infantry.Direction.ID]];
|
||||
string teamColor = infantry.House?.UnitTeamColor;
|
||||
if (Globals.TheTilesetManager.GetTeamColorTileData(infantry.Type.Name, icon, Globals.TheTeamColorManager[teamColor], out Tile tile))
|
||||
ITeamColor teamColor = infantry.Type.CanRemap ? Globals.TheTeamColorManager[infantry.House?.UnitTeamColor] : null;
|
||||
Tile tile = null;
|
||||
// RA classic infantry remap support.
|
||||
if (infantry.Type.ClassicGraphicsSource != null && Globals.TheTilesetManager is TilesetManagerClassic tsmc)
|
||||
{
|
||||
tsmc.GetTeamColorTileData(infantry.Type.Name, icon, teamColor, out tile, true, false, infantry.Type.ClassicGraphicsSource, infantry.Type.ClassicGraphicsRemap);
|
||||
}
|
||||
else
|
||||
{
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(infantry.Type.Name, icon, teamColor, out tile, true, false);
|
||||
}
|
||||
if (tile != null && tile.Image != null)
|
||||
{
|
||||
// These values are experimental, from comparing map editor screenshots to game screenshots. -Nyer
|
||||
int infantryCorrectX = tileSize.Width / -12;
|
||||
@ -724,15 +742,18 @@ namespace MobiusEditor.Render
|
||||
{
|
||||
icon = BodyShape[Facing32[unit.Direction.ID]];
|
||||
}
|
||||
string teamColor = null;
|
||||
if (unit.House != null)
|
||||
ITeamColor teamColor = null;
|
||||
if (unit.House != null && unit.Type.CanRemap)
|
||||
{
|
||||
if (!unit.House.OverrideTeamColors.TryGetValue(unit.Type.Name, out teamColor))
|
||||
String teamColorName;
|
||||
if (!unit.House.OverrideTeamColors.TryGetValue(unit.Type.Name, out teamColorName))
|
||||
{
|
||||
teamColor = unit.House.UnitTeamColor;
|
||||
teamColorName = unit.House.UnitTeamColor;
|
||||
}
|
||||
teamColor = Globals.TheTeamColorManager[teamColorName];
|
||||
}
|
||||
if (!Globals.TheTilesetManager.GetTeamColorTileData(unit.Type.Name, icon, Globals.TheTeamColorManager[teamColor], out Tile tile))
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(unit.Type.Name, icon, teamColor, out Tile tile, true, false);
|
||||
if (tile == null || tile.Image == null)
|
||||
{
|
||||
Debug.Print(string.Format("Unit {0} ({1}) not found", unit.Type.Name, icon));
|
||||
return (Rectangle.Empty, (g) => { }, false);
|
||||
@ -795,9 +816,9 @@ namespace MobiusEditor.Render
|
||||
turret2Icon = getRotorIcon(turret2Name, unit.Direction.ID, turret2Icon);
|
||||
}
|
||||
if (turretName != null)
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(turretName, turretIcon, Globals.TheTeamColorManager[teamColor], out turretTile);
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(turretName, turretIcon, teamColor, out turretTile, true, false);
|
||||
if (turret2Name != null)
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(turret2Name, turret2Icon, Globals.TheTeamColorManager[teamColor], out turret2Tile);
|
||||
Globals.TheTilesetManager.GetTeamColorTileData(turret2Name, turret2Icon, teamColor, out turret2Tile, true, false);
|
||||
}
|
||||
var tint = unit.Tint;
|
||||
void render(Graphics g)
|
||||
@ -822,6 +843,7 @@ namespace MobiusEditor.Render
|
||||
unitBm.SetResolution(96, 96);
|
||||
using (Graphics unitG = Graphics.FromImage(unitBm))
|
||||
{
|
||||
unitG.CopyRenderSettingsFrom(g);
|
||||
if (tile != null) {
|
||||
unitG.DrawImage(tile.Image, renderRect, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel);
|
||||
}
|
||||
@ -887,11 +909,11 @@ namespace MobiusEditor.Render
|
||||
ug.DrawImage(turrTile.Image, turrBounds, 0, 0, turrTile.Image.Width, turrTile.Image.Height, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
if (turretTile != null)
|
||||
if (turretTile != null && turretTile.Image != null)
|
||||
{
|
||||
RenderTurret(unitG, turretTile, turretAdjust, tileSize);
|
||||
}
|
||||
if (unit.Type.HasDoubleTurret && turret2Tile != null)
|
||||
if (unit.Type.HasDoubleTurret && turret2Tile != null && turret2Tile.Image != null)
|
||||
{
|
||||
RenderTurret(unitG, turret2Tile, turret2Adjust, tileSize);
|
||||
}
|
||||
@ -926,7 +948,7 @@ namespace MobiusEditor.Render
|
||||
int mpId = Waypoint.GetMpIdFromFlag(waypoint.Flag);
|
||||
int icon = 0;
|
||||
bool isDefaultIcon = true;
|
||||
bool gotIcon = false;
|
||||
bool gotTile = false;
|
||||
Tile tile;
|
||||
if (!soloMission && mpId >= 0 && mpId < flagColors.Length)
|
||||
{
|
||||
@ -935,7 +957,7 @@ namespace MobiusEditor.Render
|
||||
// Always paint flags as opaque.
|
||||
transparencyModifier = 1.0f;
|
||||
teamColor = flagColors[mpId];
|
||||
gotIcon = Globals.TheTilesetManager.GetTeamColorTileData(tileGraphics, icon, teamColor, out tile);
|
||||
gotTile = Globals.TheTilesetManager.GetTeamColorTileData(tileGraphics, icon, teamColor, out tile);
|
||||
}
|
||||
else if (gameType == GameType.SoleSurvivor && (waypoint.Flag & WaypointFlag.CrateSpawn) == WaypointFlag.CrateSpawn)
|
||||
{
|
||||
@ -943,20 +965,20 @@ namespace MobiusEditor.Render
|
||||
tileGraphics = "scrate";
|
||||
//tint = Color.FromArgb(waypoint.Tint.A, Color.Green);
|
||||
//brightness = 1.5f;
|
||||
gotIcon = Globals.TheTilesetManager.GetTileData(tileGraphics, icon, out tile);
|
||||
gotTile = Globals.TheTilesetManager.GetTileData(tileGraphics, icon, out tile);
|
||||
}
|
||||
else
|
||||
{
|
||||
gotIcon = Globals.TheTilesetManager.GetTileData(tileGraphics, icon, out tile);
|
||||
gotTile = Globals.TheTilesetManager.GetTileData(tileGraphics, icon, out tile);
|
||||
}
|
||||
if (!gotIcon && isDefaultIcon)
|
||||
if (!gotTile && isDefaultIcon)
|
||||
{
|
||||
// Beacon only exists in remastered graphics. Get fallback.
|
||||
tileGraphics = "armor";
|
||||
icon = 6;
|
||||
gotIcon = Globals.TheTilesetManager.GetTeamColorTileData(tileGraphics, icon, teamColor, out tile);
|
||||
tileGraphics = "trans.icn";
|
||||
icon = 3;
|
||||
gotTile = Globals.TheTilesetManager.GetTeamColorTileData(tileGraphics, icon, teamColor, out tile);
|
||||
}
|
||||
if (!gotIcon)
|
||||
if (!gotTile)
|
||||
{
|
||||
Debug.Print(string.Format("Waypoint graphics {0} ({1}) not found", tileGraphics, icon));
|
||||
return (Rectangle.Empty, (g) => { });
|
||||
@ -1113,7 +1135,7 @@ namespace MobiusEditor.Render
|
||||
RegionData paintAreaRel;
|
||||
if (!paintAreas.TryGetValue(ovlt.Name, out paintAreaRel))
|
||||
{
|
||||
paintAreaRel = GetOverlayOutline(map.Theater, location, tileSize, tileScale, overlay, outlineThickness, alphaThreshold, true);
|
||||
paintAreaRel = GetOverlayOutline(location, tileSize, tileScale, overlay, outlineThickness, alphaThreshold, true);
|
||||
paintAreas[ovlt.Name] = paintAreaRel;
|
||||
}
|
||||
int actualTopLeftX = location.X * tileSize.Width;
|
||||
@ -1183,7 +1205,7 @@ namespace MobiusEditor.Render
|
||||
return false;
|
||||
}
|
||||
|
||||
public static RegionData GetOverlayOutline(TheaterType theater, Point topLeft, Size tileSize, double tileScale, Overlay overlay, float outline, byte alphaThreshold, bool relative)
|
||||
public static RegionData GetOverlayOutline(Point topLeft, Size tileSize, double tileScale, Overlay overlay, float outline, byte alphaThreshold, bool relative)
|
||||
{
|
||||
OverlayType ovtype = overlay.Type;
|
||||
string name = ovtype.GraphicsSource;
|
||||
@ -1200,84 +1222,87 @@ namespace MobiusEditor.Render
|
||||
Size maxSize = new Size(Globals.OriginalTileWidth, Globals.OriginalTileHeight);
|
||||
int actualOutlineX = (int)Math.Max(1, outline * tileSize.Width);
|
||||
int actualOutlineY = (int)Math.Max(1, outline * tileSize.Height);
|
||||
Byte[] imgData;
|
||||
int stride;
|
||||
// Make full-tile image out of the graphics.
|
||||
using (Bitmap bm = new Bitmap(tileSize.Width, tileSize.Height, PixelFormat.Format32bppArgb))
|
||||
{
|
||||
bm.SetResolution(96, 96);
|
||||
using (Graphics g2 = Graphics.FromImage(bm))
|
||||
{
|
||||
SetRenderSettings(g2, false);
|
||||
g2.DrawImage(tile.Image, relOverlayBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel);
|
||||
}
|
||||
Byte[] imgData = ImageUtils.GetImageData(bm, out int stride, PixelFormat.Format32bppArgb, true);
|
||||
|
||||
bool isOpaqueAndNotBlack(byte[] mapdata, int yVal, int xVal)
|
||||
{
|
||||
int address = yVal * stride + xVal * 4;
|
||||
// Check alpha
|
||||
if (mapdata[address + 3] < alphaThreshold)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check brightness to exclude shadow
|
||||
byte red = mapdata[address + 2];
|
||||
byte grn = mapdata[address + 1];
|
||||
byte blu = mapdata[address + 0];
|
||||
// Integer method.
|
||||
int redBalanced = red * red * 2126;
|
||||
int grnBalanced = grn * grn * 7152;
|
||||
int bluBalanced = blu * blu * 0722;
|
||||
int lum = (redBalanced + grnBalanced + bluBalanced) / 255 / 255;
|
||||
// The integer division will automatically reduce anything near-black
|
||||
// to zero, so actually checking against a threshold is unnecessary.
|
||||
return lum > 0; // lum > lumThresholdSq * 1000
|
||||
|
||||
// Floating point method
|
||||
//double redF = red / 255.0;
|
||||
//double grnF = grn / 255.0;
|
||||
//double bluF = blu / 255.0;
|
||||
//double lum = 0.2126d * redF * redF + 0.7152d * grnF * grnF + 0.0722d * bluF * bluF;
|
||||
//return lum >= lumThresholdSq;
|
||||
};
|
||||
|
||||
//Func<byte[], int, int, bool> isOpaque_ = (mapdata, yVal, xVal) => mapdata[yVal * stride + xVal * 4 + 3] >= alphaThreshold;
|
||||
List<List<Point>> blobs = BlobDetection.FindBlobs(imgData, tileSize.Width, tileSize.Height, isOpaqueAndNotBlack, true, false);
|
||||
List<Point> allblobs = new List<Point>();
|
||||
foreach (List<Point> blob in blobs)
|
||||
{
|
||||
foreach (Point p in blob)
|
||||
{
|
||||
allblobs.Add(p);
|
||||
}
|
||||
}
|
||||
HashSet<Point> drawPoints = new HashSet<Point>();
|
||||
HashSet<Point> removePoints = new HashSet<Point>();
|
||||
foreach (Point p in allblobs)
|
||||
{
|
||||
Rectangle rect = new Rectangle(p.X + actualTopLeftX, p.Y + actualTopLeftY, 1, 1);
|
||||
removePoints.UnionWith(rect.Points());
|
||||
rect.Inflate(actualOutlineX, actualOutlineY);
|
||||
rect.Intersect(overlayBounds);
|
||||
if (!rect.IsEmpty)
|
||||
{
|
||||
drawPoints.UnionWith(rect.Points());
|
||||
}
|
||||
}
|
||||
foreach (Point p in removePoints)
|
||||
{
|
||||
drawPoints.Remove(p);
|
||||
}
|
||||
RegionData rData;
|
||||
using (Region r = new Region())
|
||||
{
|
||||
r.MakeEmpty();
|
||||
Size pixelSize = new Size(1, 1);
|
||||
foreach (Point p in drawPoints)
|
||||
{
|
||||
r.Union(new Rectangle(p, pixelSize));
|
||||
}
|
||||
rData = r.GetRegionData();
|
||||
}
|
||||
return rData;
|
||||
imgData = ImageUtils.GetImageData(bm, out stride, PixelFormat.Format32bppArgb, true);
|
||||
}
|
||||
bool isOpaqueAndNotBlack(byte[] mapdata, int yVal, int xVal)
|
||||
{
|
||||
int address = yVal * stride + xVal * 4;
|
||||
// Check alpha
|
||||
if (mapdata[address + 3] < alphaThreshold)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check brightness to exclude shadow
|
||||
byte red = mapdata[address + 2];
|
||||
byte grn = mapdata[address + 1];
|
||||
byte blu = mapdata[address + 0];
|
||||
// Integer method.
|
||||
int redBalanced = red * red * 2126;
|
||||
int grnBalanced = grn * grn * 7152;
|
||||
int bluBalanced = blu * blu * 0722;
|
||||
int lum = (redBalanced + grnBalanced + bluBalanced) / 255 / 255;
|
||||
// The integer division will automatically reduce anything near-black
|
||||
// to zero, so actually checking against a threshold is unnecessary.
|
||||
return lum > 0; // lum > lumThresholdSq * 1000
|
||||
|
||||
// Floating point method
|
||||
//double redF = red / 255.0;
|
||||
//double grnF = grn / 255.0;
|
||||
//double bluF = blu / 255.0;
|
||||
//double lum = 0.2126d * redF * redF + 0.7152d * grnF * grnF + 0.0722d * bluF * bluF;
|
||||
//return lum >= lumThresholdSq;
|
||||
};
|
||||
|
||||
//Func<byte[], int, int, bool> isOpaque_ = (mapdata, yVal, xVal) => mapdata[yVal * stride + xVal * 4 + 3] >= alphaThreshold;
|
||||
List<List<Point>> blobs = BlobDetection.FindBlobs(imgData, tileSize.Width, tileSize.Height, isOpaqueAndNotBlack, true, false);
|
||||
List<Point> allblobs = new List<Point>();
|
||||
foreach (List<Point> blob in blobs)
|
||||
{
|
||||
foreach (Point p in blob)
|
||||
{
|
||||
allblobs.Add(p);
|
||||
}
|
||||
}
|
||||
HashSet<Point> drawPoints = new HashSet<Point>();
|
||||
HashSet<Point> removePoints = new HashSet<Point>();
|
||||
foreach (Point p in allblobs)
|
||||
{
|
||||
Rectangle rect = new Rectangle(p.X + actualTopLeftX, p.Y + actualTopLeftY, 1, 1);
|
||||
removePoints.UnionWith(rect.Points());
|
||||
rect.Inflate(actualOutlineX, actualOutlineY);
|
||||
rect.Intersect(overlayBounds);
|
||||
if (!rect.IsEmpty)
|
||||
{
|
||||
drawPoints.UnionWith(rect.Points());
|
||||
}
|
||||
}
|
||||
foreach (Point p in removePoints)
|
||||
{
|
||||
drawPoints.Remove(p);
|
||||
}
|
||||
RegionData rData;
|
||||
using (Region r = new Region())
|
||||
{
|
||||
r.MakeEmpty();
|
||||
Size pixelSize = new Size(1, 1);
|
||||
foreach (Point p in drawPoints)
|
||||
{
|
||||
r.Union(new Rectangle(p, pixelSize));
|
||||
}
|
||||
rData = r.GetRegionData();
|
||||
}
|
||||
return rData;
|
||||
}
|
||||
|
||||
public static void RenderAllFootballAreas(Graphics graphics, Map map, Size tileSize, double tileScale, GameType gameType)
|
||||
@ -1337,15 +1362,15 @@ namespace MobiusEditor.Render
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderAllFakeBuildingLabels(Graphics graphics, Map map, Size tileSize, double tileScale)
|
||||
public static void RenderAllFakeBuildingLabels(Graphics graphics, Map map, Size tileSize)
|
||||
{
|
||||
foreach (var (topLeft, building) in map.Buildings.OfType<Building>())
|
||||
{
|
||||
RenderFakeBuildingLabel(graphics, building, topLeft, tileSize, tileScale, false);
|
||||
RenderFakeBuildingLabel(graphics, building, topLeft, tileSize, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderFakeBuildingLabel(Graphics graphics, Building building, Point topLeft, Size tileSize, double tileScale, Boolean forPreview)
|
||||
public static void RenderFakeBuildingLabel(Graphics graphics, Building building, Point topLeft, Size tileSize, Boolean forPreview)
|
||||
{
|
||||
if (!building.Type.IsFake)
|
||||
{
|
||||
@ -1362,11 +1387,12 @@ namespace MobiusEditor.Render
|
||||
new Size(maxSize.Width * tileSize.Width, maxSize.Height * tileSize.Height)
|
||||
);
|
||||
string fakeText = Globals.TheGameTextManager["TEXT_UI_FAKE"];
|
||||
double tileScaleHor = tileSize.Width / 128.0;
|
||||
using (var fakeBackgroundBrush = new SolidBrush(Color.FromArgb((forPreview ? 128 : 256) * 2 / 3, Color.Black)))
|
||||
using (var fakeTextBrush = new SolidBrush(Color.FromArgb(forPreview ? building.Tint.A : 255, Color.White)))
|
||||
{
|
||||
using (var font = graphics.GetAdjustedFont(fakeText, SystemFonts.DefaultFont, buildingBounds.Width, buildingBounds.Height,
|
||||
Math.Max(1, (int)(12 * tileScale)), Math.Max(1, (int)(24 * tileScale)), stringFormat, true))
|
||||
Math.Max(1, (int)(12 * tileScaleHor)), Math.Max(1, (int)(24 * tileScaleHor)), stringFormat, true))
|
||||
{
|
||||
var textBounds = graphics.MeasureString(fakeText, font, buildingBounds.Width, stringFormat);
|
||||
var backgroundBounds = new RectangleF(buildingBounds.Location, textBounds);
|
||||
@ -1376,15 +1402,15 @@ namespace MobiusEditor.Render
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderAllRebuildPriorityLabels(Graphics graphics, Map map, Size tileSize, double tileScale)
|
||||
public static void RenderAllRebuildPriorityLabels(Graphics graphics, Map map, Size tileSize)
|
||||
{
|
||||
foreach (var (topLeft, building) in map.Buildings.OfType<Building>())
|
||||
{
|
||||
RenderRebuildPriorityLabel(graphics, building, topLeft, tileSize, tileScale, false);
|
||||
RenderRebuildPriorityLabel(graphics, building, topLeft, tileSize, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderRebuildPriorityLabel(Graphics graphics, Building building, Point topLeft, Size tileSize, double tileScale, Boolean forPreview)
|
||||
public static void RenderRebuildPriorityLabel(Graphics graphics, Building building, Point topLeft, Size tileSize, Boolean forPreview)
|
||||
{
|
||||
var stringFormat = new StringFormat
|
||||
{
|
||||
@ -1398,12 +1424,13 @@ namespace MobiusEditor.Render
|
||||
);
|
||||
if (building.BasePriority >= 0)
|
||||
{
|
||||
double tileScaleHor = tileSize.Width / 128.0;
|
||||
string priText = building.BasePriority.ToString();
|
||||
using (var baseBackgroundBrush = new SolidBrush(Color.FromArgb((forPreview ? 128 : 256) * 2 / 3, Color.Black)))
|
||||
using (var baseTextBrush = new SolidBrush(Color.FromArgb(forPreview ? 128 : 255, Color.Red)))
|
||||
{
|
||||
using (var font = graphics.GetAdjustedFont(priText, SystemFonts.DefaultFont, buildingBounds.Width, buildingBounds.Height,
|
||||
Math.Max(1, (int)(12 * tileScale)), Math.Max(1, (int)(24 * tileScale)), stringFormat, true))
|
||||
Math.Max(1, (int)(12 * tileScaleHor)), Math.Max(1, (int)(24 * tileScaleHor)), stringFormat, true))
|
||||
{
|
||||
var textBounds = graphics.MeasureString(priText, font, buildingBounds.Width, stringFormat);
|
||||
var backgroundBounds = new RectangleF(buildingBounds.Location, textBounds);
|
||||
@ -1415,13 +1442,14 @@ namespace MobiusEditor.Render
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderAllTechnoTriggers(Graphics graphics, Map map, Size tileSize, double tileScale, MapLayerFlag layersToRender)
|
||||
public static void RenderAllTechnoTriggers(Graphics graphics, Map map, Size tileSize, MapLayerFlag layersToRender)
|
||||
{
|
||||
RenderAllTechnoTriggers(graphics, map, tileSize, tileScale, layersToRender, Color.LimeGreen, null, false);
|
||||
RenderAllTechnoTriggers(graphics, map, tileSize, layersToRender, Color.LimeGreen, null, false);
|
||||
}
|
||||
|
||||
public static void RenderAllTechnoTriggers(Graphics graphics, Map map, Size tileSize, double tileScale, MapLayerFlag layersToRender, Color color, string toPick, bool excludePick)
|
||||
public static void RenderAllTechnoTriggers(Graphics graphics, Map map, Size tileSize, MapLayerFlag layersToRender, Color color, string toPick, bool excludePick)
|
||||
{
|
||||
double tileScaleHor = tileSize.Width / 128.0;
|
||||
float borderSize = Math.Max(0.5f, tileSize.Width / 60.0f);
|
||||
foreach (var (cell, techno) in map.Technos)
|
||||
{
|
||||
@ -1504,7 +1532,7 @@ namespace MobiusEditor.Render
|
||||
using (var technoTriggerBrush = new SolidBrush(alphaColor))
|
||||
using (var technoTriggerPen = new Pen(alphaColor, borderSize))
|
||||
using (var font = graphics.GetAdjustedFont(trigger, SystemFonts.DefaultFont, bounds.Width, bounds.Height,
|
||||
Math.Max(1, (int)(12 * tileScale)), Math.Max(1, (int)(24 * tileScale)), stringFormat, true))
|
||||
Math.Max(1, (int)(12 * tileScaleHor)), Math.Max(1, (int)(24 * tileScaleHor)), stringFormat, true))
|
||||
{
|
||||
var textBounds = graphics.MeasureString(trigger, font, bounds.Width, stringFormat);
|
||||
var backgroundBounds = new RectangleF(bounds.Location, textBounds);
|
||||
@ -1518,7 +1546,7 @@ namespace MobiusEditor.Render
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderWayPointIndicators(Graphics graphics, Map map, Size tileSize, double tileScale, Color textColor, bool forPreview, bool excludeSpecified, params Waypoint[] specified)
|
||||
public static void RenderWayPointIndicators(Graphics graphics, Map map, Size tileSize, Color textColor, bool forPreview, bool excludeSpecified, params Waypoint[] specified)
|
||||
{
|
||||
HashSet<Waypoint> specifiedWaypoints = specified.ToHashSet();
|
||||
|
||||
@ -1531,12 +1559,12 @@ namespace MobiusEditor.Render
|
||||
{
|
||||
continue;
|
||||
}
|
||||
RenderWayPointIndicator(graphics, waypoint, point, tileSize, tileScale, textColor, forPreview);
|
||||
RenderWayPointIndicator(graphics, waypoint, point, tileSize, textColor, forPreview);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderWayPointIndicator(Graphics graphics, Waypoint waypoint, Point topLeft, Size tileSize, double tileScale, Color textColor, bool forPreview)
|
||||
public static void RenderWayPointIndicator(Graphics graphics, Waypoint waypoint, Point topLeft, Size tileSize, Color textColor, bool forPreview)
|
||||
{
|
||||
var stringFormat = new StringFormat
|
||||
{
|
||||
@ -1544,12 +1572,14 @@ namespace MobiusEditor.Render
|
||||
LineAlignment = StringAlignment.Center
|
||||
};
|
||||
var paintBounds = new Rectangle(new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height), tileSize);
|
||||
// Adjust calcuations to tile size. The below adjustments are done assuming the tile is 128 wide.
|
||||
double tileScaleHor = tileSize.Width / 128.0;
|
||||
string wpText = waypoint.Name;
|
||||
using (var baseBackgroundBrush = new SolidBrush(Color.FromArgb(forPreview ? 64 : 128, Color.Black)))
|
||||
using (var baseTextBrush = new SolidBrush(Color.FromArgb(forPreview ? 128 : 255, textColor)))
|
||||
{
|
||||
using (var font = graphics.GetAdjustedFont(wpText, SystemFonts.DefaultFont, paintBounds.Width, paintBounds.Height,
|
||||
Math.Max(1, (int)(12 * tileScale)), Math.Max(1, (int)(55 * tileScale)), stringFormat, true))
|
||||
Math.Max(1, (int)(12 * tileScaleHor)), Math.Max(1, (int)(55 * tileScaleHor)), stringFormat, true))
|
||||
{
|
||||
var textBounds = graphics.MeasureString(wpText, font, paintBounds.Width, stringFormat);
|
||||
var backgroundBounds = new RectangleF(paintBounds.Location, textBounds);
|
||||
@ -1721,23 +1751,24 @@ namespace MobiusEditor.Render
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderCellTriggersSoft(Graphics graphics, Map map, Size tileSize, double tileScale, params String[] specifiedToExclude)
|
||||
public static void RenderCellTriggersSoft(Graphics graphics, Map map, Size tileSize, params String[] specifiedToExclude)
|
||||
{
|
||||
RenderCellTriggers(graphics, map, tileSize, tileScale, Color.Black, Color.White, Color.White, 0.75f, false, true, specifiedToExclude);
|
||||
RenderCellTriggers(graphics, map, tileSize, Color.Black, Color.White, Color.White, 0.75f, false, true, specifiedToExclude);
|
||||
}
|
||||
|
||||
public static void RenderCellTriggersHard(Graphics graphics, Map map, Size tileSize, double tileScale, params String[] specifiedToExclude)
|
||||
public static void RenderCellTriggersHard(Graphics graphics, Map map, Size tileSize, params String[] specifiedToExclude)
|
||||
{
|
||||
RenderCellTriggers(graphics, map, tileSize, tileScale, Color.Black, Color.White, Color.White, 1, false, true, specifiedToExclude);
|
||||
RenderCellTriggers(graphics, map, tileSize, Color.Black, Color.White, Color.White, 1, false, true, specifiedToExclude);
|
||||
}
|
||||
|
||||
public static void RenderCellTriggersSelected(Graphics graphics, Map map, Size tileSize, double tileScale, params String[] specifiedToDraw)
|
||||
public static void RenderCellTriggersSelected(Graphics graphics, Map map, Size tileSize, params String[] specifiedToDraw)
|
||||
{
|
||||
RenderCellTriggers(graphics, map, tileSize, tileScale, Color.Black, Color.Yellow, Color.Yellow, 1, true, false, specifiedToDraw);
|
||||
RenderCellTriggers(graphics, map, tileSize, Color.Black, Color.Yellow, Color.Yellow, 1, true, false, specifiedToDraw);
|
||||
}
|
||||
|
||||
public static void RenderCellTriggers(Graphics graphics, Map map, Size tileSize, double tileScale, Color fillColor, Color borderColor, Color textColor, double alphaAdjust, bool thickborder, bool excludeSpecified, params String[] specified)
|
||||
public static void RenderCellTriggers(Graphics graphics, Map map, Size tileSize, Color fillColor, Color borderColor, Color textColor, double alphaAdjust, bool thickborder, bool excludeSpecified, params String[] specified)
|
||||
{
|
||||
double tileScaleHor = tileSize.Width / 128.0;
|
||||
Color ApplyAlpha(Color col, int baseAlpha, double alphaMul)
|
||||
{
|
||||
return Color.FromArgb(Math.Max(0, Math.Min(0xFF, (int)Math.Round(baseAlpha * alphaMul, MidpointRounding.AwayFromZero))), col);
|
||||
@ -1782,7 +1813,7 @@ namespace MobiusEditor.Render
|
||||
};
|
||||
var text = cellTrigger.Trigger;
|
||||
using (var font = graphics.GetAdjustedFont(text, SystemFonts.DefaultFont, textBounds.Width, textBounds.Height,
|
||||
Math.Max(1, (int)(24 * tileScale)), Math.Max(1, (int)(48 * tileScale)), stringFormat, true))
|
||||
Math.Max(1, (int)(24 * tileScaleHor)), Math.Max(1, (int)(48 * tileScaleHor)), stringFormat, true))
|
||||
{
|
||||
graphics.DrawString(text.ToString(), font, isPreview ? prevCellTriggersBrush : cellTriggersBrush, textBounds, stringFormat);
|
||||
}
|
||||
@ -1861,6 +1892,14 @@ namespace MobiusEditor.Render
|
||||
}
|
||||
}
|
||||
|
||||
public static void CopyRenderSettingsFrom(this Graphics target, Graphics source)
|
||||
{
|
||||
target.CompositingQuality = source.CompositingQuality;
|
||||
target.InterpolationMode = source.InterpolationMode;
|
||||
target.SmoothingMode = source.SmoothingMode;
|
||||
target.PixelOffsetMode = source.PixelOffsetMode;
|
||||
}
|
||||
|
||||
public static Rectangle RenderBounds(Size imageSize, Size cellDimensions, Size cellSize)
|
||||
{
|
||||
double scaleFactorX = cellSize.Width / (double)Globals.OriginalTileWidth;
|
||||
|
@ -413,6 +413,7 @@ namespace MobiusEditor.TiberianDawn
|
||||
{
|
||||
Bitmap mapImg = new Bitmap(Map.Metrics.Width * Globals.MapTileWidth, Map.Metrics.Height * Globals.MapTileHeight);
|
||||
mapImg.SetResolution(96, 96);
|
||||
mapImg.RemoveAlphaOnCurrent();
|
||||
MapImage = mapImg;
|
||||
}
|
||||
}
|
||||
|
@ -28,19 +28,19 @@ namespace MobiusEditor.TiberianDawn
|
||||
public static readonly InfantryType E5 = new InfantryType(4, "e5", "TEXT_UNIT_TITLE_NOD_CHEM_WARRIOR", "Badguy", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType E7 = new InfantryType(5, "e6", "TEXT_UNIT_TITLE_GDI_ENGINEER", "Goodguy");
|
||||
public static readonly InfantryType Commando = new InfantryType(6, "rmbo", "TEXT_UNIT_TITLE_GDI_COMMANDO", "Goodguy", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType C1 = new InfantryType(7, "c1", "TEXT_UNIT_TITLE_CIV1", "Neutral", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType C2 = new InfantryType(8, "c2", "TEXT_UNIT_TITLE_CIV2", "Neutral");
|
||||
public static readonly InfantryType C3 = new InfantryType(9, "c3", "TEXT_UNIT_TITLE_CIV3", "Neutral");
|
||||
public static readonly InfantryType C4 = new InfantryType(10, "c4", "TEXT_UNIT_TITLE_CIV4", "Neutral");
|
||||
public static readonly InfantryType C5 = new InfantryType(11, "c5", "TEXT_UNIT_TITLE_CIV5", "Neutral");
|
||||
public static readonly InfantryType C6 = new InfantryType(12, "c6", "TEXT_UNIT_TITLE_CIV6", "Neutral");
|
||||
public static readonly InfantryType C7 = new InfantryType(13, "c7", "TEXT_UNIT_TITLE_CIV7", "Neutral", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType C8 = new InfantryType(14, "c8", "TEXT_UNIT_TITLE_CIV8", "Neutral");
|
||||
public static readonly InfantryType C9 = new InfantryType(15, "c9", "TEXT_UNIT_TITLE_CIV9", "Neutral");
|
||||
public static readonly InfantryType C10 = new InfantryType(16, "c10", "TEXT_UNIT_TITLE_C10", "Neutral");
|
||||
public static readonly InfantryType Moebius = new InfantryType(17, "moebius", "TEXT_UNIT_TITLE_MOEBIUS", "Neutral");
|
||||
public static readonly InfantryType Delphi = new InfantryType(18, "delphi", "TEXT_UNIT_TITLE_DELPHI", "Neutral", UnitTypeFlag.IsArmed);
|
||||
public static readonly InfantryType DrChan = new InfantryType(19, "chan", "TEXT_UNIT_TITLE_CHAN", "Neutral");
|
||||
public static readonly InfantryType C1 = new InfantryType(7, "c1", "TEXT_UNIT_TITLE_CIV1", "Neutral", UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C2 = new InfantryType(8, "c2", "TEXT_UNIT_TITLE_CIV2", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C3 = new InfantryType(9, "c3", "TEXT_UNIT_TITLE_CIV3", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C4 = new InfantryType(10, "c4", "TEXT_UNIT_TITLE_CIV4", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C5 = new InfantryType(11, "c5", "TEXT_UNIT_TITLE_CIV5", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C6 = new InfantryType(12, "c6", "TEXT_UNIT_TITLE_CIV6", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C7 = new InfantryType(13, "c7", "TEXT_UNIT_TITLE_CIV7", "Neutral", UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C8 = new InfantryType(14, "c8", "TEXT_UNIT_TITLE_CIV8", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C9 = new InfantryType(15, "c9", "TEXT_UNIT_TITLE_CIV9", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType C10 = new InfantryType(16, "c10", "TEXT_UNIT_TITLE_C10", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType Moebius = new InfantryType(17, "moebius", "TEXT_UNIT_TITLE_MOEBIUS", "Neutral", UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType Delphi = new InfantryType(18, "delphi", "TEXT_UNIT_TITLE_DELPHI", "Neutral", UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
public static readonly InfantryType DrChan = new InfantryType(19, "chan", "TEXT_UNIT_TITLE_CHAN", "Neutral", UnitTypeFlag.NoRemap);
|
||||
|
||||
private static readonly InfantryType[] Types;
|
||||
|
||||
|
@ -40,10 +40,10 @@ namespace MobiusEditor.TiberianDawn
|
||||
public static readonly UnitType GunBoat = new UnitType(15, "boat", "TEXT_UNIT_TITLE_WAKE", "Goodguy", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType MCV = new UnitType(16, "mcv", "TEXT_UNIT_TITLE_GDI_MCV", "Goodguy");
|
||||
public static readonly UnitType Bike = new UnitType(17, "bike", "TEXT_UNIT_TITLE_NOD_RECON_BIKE", "Badguy", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Tric = new UnitType(18, "tric", "TEXT_UNIT_TITLE_TRIC", "Special", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Trex = new UnitType(19, "trex", "TEXT_UNIT_TITLE_TREX", "Special", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Rapt = new UnitType(20, "rapt", "TEXT_UNIT_TITLE_RAPT", "Special", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Steg = new UnitType(21, "steg", "TEXT_UNIT_TITLE_STEG", "Special", UnitTypeFlag.IsArmed);
|
||||
public static readonly UnitType Tric = new UnitType(18, "tric", "TEXT_UNIT_TITLE_TRIC", "Special", UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
public static readonly UnitType Trex = new UnitType(19, "trex", "TEXT_UNIT_TITLE_TREX", "Special", UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
public static readonly UnitType Rapt = new UnitType(20, "rapt", "TEXT_UNIT_TITLE_RAPT", "Special", UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
public static readonly UnitType Steg = new UnitType(21, "steg", "TEXT_UNIT_TITLE_STEG", "Special", UnitTypeFlag.IsArmed | UnitTypeFlag.NoRemap);
|
||||
|
||||
public static readonly UnitType Tran = new UnitType(0 | UnitTypeIDMask.Aircraft, "tran", "TEXT_UNIT_TITLE_GDI_TRANSPORT", "Goodguy", "LROTOR", "RROTOR", 1, -2, UnitTypeFlag.HasTurret | UnitTypeFlag.HasDoubleTurret);
|
||||
public static readonly UnitType A10 = new UnitType(1 | UnitTypeIDMask.Aircraft, "a10", "TEXT_UNIT_TITLE_A10", "Goodguy", UnitTypeFlag.IsArmed | UnitTypeFlag.IsFixedWing);
|
||||
|
@ -759,11 +759,11 @@ namespace MobiusEditor.Tools
|
||||
MapRenderer.RenderAllOccupierBounds(g, Globals.PreviewTileSize, buildingList);
|
||||
if ((Layers & MapLayerFlag.BuildingFakes) == MapLayerFlag.BuildingFakes)
|
||||
{
|
||||
MapRenderer.RenderFakeBuildingLabel(g, mockBuilding, new Point(0, 0), Globals.PreviewTileSize, Globals.PreviewTileScale, false);
|
||||
MapRenderer.RenderFakeBuildingLabel(g, mockBuilding, new Point(0, 0), Globals.PreviewTileSize, false);
|
||||
}
|
||||
if ((Layers & MapLayerFlag.BuildingRebuild) == MapLayerFlag.BuildingRebuild)
|
||||
{
|
||||
MapRenderer.RenderRebuildPriorityLabel(g, mockBuilding, new Point(0, 0), Globals.PreviewTileSize, Globals.PreviewTileScale, false);
|
||||
MapRenderer.RenderRebuildPriorityLabel(g, mockBuilding, new Point(0, 0), Globals.PreviewTileSize, false);
|
||||
}
|
||||
}
|
||||
buildingTypeMapPanel.MapImage = buildingPreview;
|
||||
@ -858,15 +858,15 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
if ((Layers & MapLayerFlag.BuildingFakes) == MapLayerFlag.BuildingFakes)
|
||||
{
|
||||
MapRenderer.RenderAllFakeBuildingLabels(graphics, previewMap, Globals.MapTileSize, Globals.MapTileScale);
|
||||
MapRenderer.RenderAllFakeBuildingLabels(graphics, previewMap, Globals.MapTileSize);
|
||||
}
|
||||
if ((Layers & MapLayerFlag.BuildingRebuild) == MapLayerFlag.BuildingRebuild)
|
||||
{
|
||||
MapRenderer.RenderAllRebuildPriorityLabels(graphics, previewMap, Globals.MapTileSize, Globals.MapTileScale);
|
||||
MapRenderer.RenderAllRebuildPriorityLabels(graphics, previewMap, Globals.MapTileSize);
|
||||
}
|
||||
if ((Layers & MapLayerFlag.TechnoTriggers) == MapLayerFlag.TechnoTriggers)
|
||||
{
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Layers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -486,14 +486,14 @@ namespace MobiusEditor.Tools
|
||||
selected = null;
|
||||
string[] selectedRange = selected != null ? new[] { selected } : new string[] { };
|
||||
// Normal techno triggers: under cell
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Layers, Color.LimeGreen, selected, true);
|
||||
MapRenderer.RenderCellTriggersHard(graphics, map, Globals.MapTileSize, Globals.MapTileScale, selectedRange);
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, map, Globals.MapTileSize, Layers, Color.LimeGreen, selected, true);
|
||||
MapRenderer.RenderCellTriggersHard(graphics, map, Globals.MapTileSize, selectedRange);
|
||||
if (selected != null)
|
||||
{
|
||||
// Only use preview map if in placement mode.
|
||||
MapRenderer.RenderCellTriggersSelected(graphics, placementMode ? previewMap : map, Globals.MapTileSize, Globals.MapTileScale, selectedRange);
|
||||
MapRenderer.RenderCellTriggersSelected(graphics, placementMode ? previewMap : map, Globals.MapTileSize, selectedRange);
|
||||
// Selected technos: on top of cell
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Layers, Color.Yellow, selected, false);
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, map, Globals.MapTileSize, Layers, Color.Yellow, selected, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -812,7 +812,7 @@ namespace MobiusEditor.Tools
|
||||
MapRenderer.RenderAllBoundsFromPoint(graphics, Globals.MapTileSize, previewMap.Technos.OfType<InfantryGroup>());
|
||||
if ((Layers & (MapLayerFlag.Infantry | MapLayerFlag.TechnoTriggers)) == (MapLayerFlag.Infantry | MapLayerFlag.TechnoTriggers))
|
||||
{
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Layers);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -957,7 +957,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
templateTypeMapPanel.MapImage = selected.Thumbnail;
|
||||
var templateTypeMetrics = new CellMetrics(selected.ThumbnailIconWidth, selected.ThumbnailIconHeight);
|
||||
templateTypeNavigationWidget = new NavigationWidget(templateTypeMapPanel, templateTypeMetrics, Globals.OriginalTileSize, false);
|
||||
templateTypeNavigationWidget = new NavigationWidget(templateTypeMapPanel, templateTypeMetrics, Globals.PreviewTileSize, false);
|
||||
templateTypeNavigationWidget.MouseoverSize = Size.Empty;
|
||||
templateTypeNavigationWidget.Activate();
|
||||
}
|
||||
|
@ -580,7 +580,7 @@ namespace MobiusEditor.Tools
|
||||
MapRenderer.RenderAllOccupierBounds(graphics, Globals.MapTileSize, previewMap.Technos.OfType<Terrain>());
|
||||
if ((Layers & MapLayerFlag.TechnoTriggers) == MapLayerFlag.TechnoTriggers)
|
||||
{
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Layers);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,7 +613,7 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
if ((Layers & MapLayerFlag.TechnoTriggers) == MapLayerFlag.TechnoTriggers)
|
||||
{
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Layers);
|
||||
}
|
||||
if ((Layers & MapLayerFlag.EffectRadius) == MapLayerFlag.EffectRadius)
|
||||
{
|
||||
|
@ -281,7 +281,7 @@ namespace MobiusEditor.Tools
|
||||
if ((layersToRender & MapLayerFlag.CellTriggers) == MapLayerFlag.CellTriggers
|
||||
&& (manuallyHandledLayers & MapLayerFlag.CellTriggers) == MapLayerFlag.None)
|
||||
{
|
||||
MapRenderer.RenderCellTriggersSoft(graphics, map, tileSize, tileScale);
|
||||
MapRenderer.RenderCellTriggersSoft(graphics, map, tileSize);
|
||||
}
|
||||
if ((layersToRender & (MapLayerFlag.Waypoints | MapLayerFlag.FootballArea)) == (MapLayerFlag.Waypoints | MapLayerFlag.FootballArea)
|
||||
&& (manuallyHandledLayers & MapLayerFlag.WaypointsIndic) == MapLayerFlag.None && plugin.GameType == GameType.SoleSurvivor)
|
||||
@ -307,22 +307,22 @@ namespace MobiusEditor.Tools
|
||||
if ((layersToRender & (MapLayerFlag.Waypoints | MapLayerFlag.WaypointsIndic)) == (MapLayerFlag.Waypoints | MapLayerFlag.WaypointsIndic)
|
||||
&& (manuallyHandledLayers & MapLayerFlag.WaypointsIndic) == MapLayerFlag.None)
|
||||
{
|
||||
MapRenderer.RenderWayPointIndicators(graphics, map, tileSize, tileScale, Color.LightGreen, false, true);
|
||||
MapRenderer.RenderWayPointIndicators(graphics, map, tileSize, Color.LightGreen, false, true);
|
||||
}
|
||||
if ((layersToRender & (MapLayerFlag.Buildings | MapLayerFlag.BuildingFakes)) == (MapLayerFlag.Buildings | MapLayerFlag.BuildingFakes)
|
||||
&& (manuallyHandledLayers & MapLayerFlag.BuildingFakes) == MapLayerFlag.None)
|
||||
{
|
||||
MapRenderer.RenderAllFakeBuildingLabels(graphics, map, tileSize, tileScale);
|
||||
MapRenderer.RenderAllFakeBuildingLabels(graphics, map, tileSize);
|
||||
}
|
||||
if ((layersToRender & (MapLayerFlag.Buildings | MapLayerFlag.BuildingRebuild)) == (MapLayerFlag.Buildings | MapLayerFlag.BuildingRebuild)
|
||||
&& (manuallyHandledLayers & MapLayerFlag.BuildingRebuild) == MapLayerFlag.None)
|
||||
{
|
||||
MapRenderer.RenderAllRebuildPriorityLabels(graphics, map, tileSize, tileScale);
|
||||
MapRenderer.RenderAllRebuildPriorityLabels(graphics, map, tileSize);
|
||||
}
|
||||
if ((layersToRender & MapLayerFlag.TechnoTriggers) == MapLayerFlag.TechnoTriggers
|
||||
&& (manuallyHandledLayers & MapLayerFlag.TechnoTriggers) == MapLayerFlag.None)
|
||||
{
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, map, tileSize, tileScale, layersToRender);
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, map, tileSize, layersToRender);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,13 +467,13 @@ namespace MobiusEditor.Tools
|
||||
MapRenderer.RenderWaypoint(plugin.GameType, true, Globals.MapTileSize, map.FlagColors.ToArray(), selected, 1.0f).Item2(graphics);
|
||||
}
|
||||
// Render those here to they are put over the opaque redraw of the current waypoint.
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, plugin.Map, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
MapRenderer.RenderAllTechnoTriggers(graphics, plugin.Map, Globals.MapTileSize, Layers);
|
||||
MapRenderer.RenderAllBoundsFromCell(graphics, Globals.MapTileSize,
|
||||
map.Waypoints.Where(wp => wp != selected && wp.Cell.HasValue).Select(wp => wp.Cell.Value), map.Metrics, Color.Orange);
|
||||
// For TD, always render reveal waypoint.
|
||||
bool renderAll = plugin.GameType != GameType.RedAlert || (Layers & MapLayerFlag.WaypointRadius) == MapLayerFlag.WaypointRadius;
|
||||
MapRenderer.RenderAllWayPointRevealRadiuses(graphics, plugin, map, Globals.MapTileSize, selected, !renderAll);
|
||||
MapRenderer.RenderWayPointIndicators(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Color.LightGreen, false, true, selectedRange);
|
||||
MapRenderer.RenderWayPointIndicators(graphics, map, Globals.MapTileSize, Color.LightGreen, false, true, selectedRange);
|
||||
if (selected != null)
|
||||
{
|
||||
if (placementMode && selectedIndex >= 0)
|
||||
@ -484,11 +484,11 @@ namespace MobiusEditor.Tools
|
||||
if (selected.Cell.HasValue)
|
||||
{
|
||||
MapRenderer.RenderAllBoundsFromCell(graphics, Globals.MapTileSize, new int[] { selected.Cell.Value }, map.Metrics, Color.Yellow);
|
||||
MapRenderer.RenderWayPointIndicators(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Color.Yellow, false, false, selectedRange);
|
||||
MapRenderer.RenderWayPointIndicators(graphics, map, Globals.MapTileSize, Color.Yellow, false, false, selectedRange);
|
||||
}
|
||||
if (dummySelected != null && (selected == null || selected.Cell != dummySelected.Cell))
|
||||
{
|
||||
MapRenderer.RenderWayPointIndicators(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Color.Yellow, true, false, new[] { dummySelected });
|
||||
MapRenderer.RenderWayPointIndicators(graphics, map, Globals.MapTileSize, Color.Yellow, true, false, new[] { dummySelected });
|
||||
// Need to do this manually since it's an extra waypoint not normally on the list, and it uses the radius data of the original waypoint to place.
|
||||
int[] wpReveal1 = plugin.GetRevealRadiusForWaypoints(map, false);
|
||||
int[] wpReveal2 = plugin.GetRevealRadiusForWaypoints(map, true);
|
||||
|
@ -500,7 +500,8 @@ namespace MobiusEditor.Utility
|
||||
Int32 hdrIconsPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x0C);
|
||||
// Offset of start of palette data. Probably always 0.
|
||||
Int32 hdrPalettesPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x10);
|
||||
// Offset of remaps data? Always fixed value "0x0D1AFFFF", which makes no sense as ptr.
|
||||
// Offset of remaps data. Dune II leftover of 4 bit to 8 bit translation tables.
|
||||
// Always fixed value 0x0D1AFFFF, which makes no sense as ptr.
|
||||
Int32 hdrRemapsPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x14);
|
||||
// Offset of 'transparency flags'? Generally points to an empty array at the end of the file.
|
||||
Int32 hdrTransFlagPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x18);
|
||||
@ -513,7 +514,85 @@ namespace MobiusEditor.Utility
|
||||
if (hdrHeight != 24 || hdrWidth != 24)
|
||||
throw new ArgumentException("Only 24×24 pixel tiles are supported.", "fileData");
|
||||
// Checking some normally hardcoded values
|
||||
if (hdrAllocated != 00 || hdrPalettesPtr != 0 || hdrRemapsPtr != 0x0D1AFFFF)
|
||||
if (hdrAllocated != 0 || hdrPalettesPtr != 0)// || hdrRemapsPtr != 0x0D1AFFFF)
|
||||
throw new ArgumentException("Invalid values encountered in header.");
|
||||
if (hdrCount == 0)
|
||||
throw new ArgumentException("Tileset files with 0 tiles are not supported!", "fileData");
|
||||
// Checking if data is all inside the file
|
||||
if (hdrIconsPtr >= fileLen || (hdrMapPtr + hdrCount) > fileLen)
|
||||
throw new ArgumentException("Invalid header values: indices outside file range.", "fileData");
|
||||
Int32 tileSize = hdrWidth * hdrHeight;
|
||||
// Maps the available images onto the full iconset definition
|
||||
Byte[] map = new Byte[hdrCount];
|
||||
Array.Copy(fileData, hdrMapPtr, map, 0, hdrCount);
|
||||
// Get max index plus one for real images count. Nothing in the file header actually specifies this directly.
|
||||
Int32 actualImages = map.Max(x => x == 0xFF ? -1 : x) + 1;
|
||||
if (hdrTransFlagPtr + actualImages > fileLen)
|
||||
throw new ArgumentException("Invalid header values: indices outside file range.", "fileData");
|
||||
if (hdrIconsPtr + actualImages * tileSize > fileLen)
|
||||
throw new ArgumentException("Tile image data outside file range.", "fileData");
|
||||
Byte[] imagesIndex = new Byte[actualImages];
|
||||
Array.Copy(fileData, hdrTransFlagPtr, imagesIndex, 0, actualImages);
|
||||
Byte[][] tiles = new Byte[hdrCount][];
|
||||
widths = new int[hdrCount];
|
||||
heights = new int[hdrCount];
|
||||
Boolean[] tileUseList = new Boolean[map.Length];
|
||||
for (Int32 i = 0; i < map.Length; ++i)
|
||||
{
|
||||
Byte dataIndex = map[i];
|
||||
Boolean used = dataIndex != 0xFF;
|
||||
tileUseList[i] = used;
|
||||
Byte[] tileData = new Byte[tileSize];
|
||||
if (used)
|
||||
{
|
||||
Int32 offset = hdrIconsPtr + dataIndex * tileSize;
|
||||
if ((offset + tileSize) > fileLen)
|
||||
throw new ArgumentException("Tile data outside file range.", "fileData");
|
||||
Array.Copy(fileData, offset, tileData, 0, tileSize);
|
||||
tiles[i] = tileData;
|
||||
widths[i] = hdrWidth;
|
||||
heights[i] = hdrHeight;
|
||||
}
|
||||
}
|
||||
return tiles;
|
||||
}
|
||||
|
||||
public static Byte[][] GetRaTmpData(Byte[] fileData, out int[] widths, out int[] heights)
|
||||
{
|
||||
Int32 fileLen = fileData.Length;
|
||||
if (fileLen < 0x28)
|
||||
throw new ArgumentException("File is not long enough to be a C&C Template file.", "fileData");
|
||||
Int16 hdrWidth = ArrayUtils.ReadInt16FromByteArrayLe(fileData, 0x00);
|
||||
Int16 hdrHeight = ArrayUtils.ReadInt16FromByteArrayLe(fileData, 0x02);
|
||||
// Amount of icons to form the full icon set. Not necessarily the same as the amount of actual icons.
|
||||
Int16 hdrCount = ArrayUtils.ReadInt16FromByteArrayLe(fileData, 0x04);
|
||||
// Always 0
|
||||
Int16 hdrAllocated = ArrayUtils.ReadInt16FromByteArrayLe(fileData, 0x06);
|
||||
// New in RA
|
||||
Int16 hdrMapWidth = ArrayUtils.ReadInt16FromByteArrayLe(fileData, 0x08);
|
||||
Int16 hdrMapHeight = ArrayUtils.ReadInt16FromByteArrayLe(fileData, 0x0A);
|
||||
Int32 hdrSize = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x0C);
|
||||
// Offset of start of actual icon data. Generally always 0x20
|
||||
Int32 hdrIconsPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x10);
|
||||
// Offset of start of palette data. Probably always 0.
|
||||
Int32 hdrPalettesPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x14);
|
||||
// Offset of remaps data. Dune II leftover of 4 bit to 8 bit translation tables.
|
||||
// Always seems to be 0x2C730FXX (with values differing for the lowest byte), which makes no sense as ptr.
|
||||
Int32 hdrRemapsPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x18);
|
||||
// Offset of 'transparency flags'? Generally points to an empty array at the end of the file.
|
||||
Int32 hdrTransFlagPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x1C);
|
||||
// Offset of 'color' map, indicating the terrain type for each type. This includes unused cells, which are usually indicated as 0.
|
||||
Int32 hdrColorMapPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x20);
|
||||
// Offset of actual icon set definition, defining for each index which icon data to use. FF for none.
|
||||
Int32 hdrMapPtr = ArrayUtils.ReadInt32FromByteArrayLe(fileData, 0x24);
|
||||
// File size check
|
||||
if (hdrSize != fileData.Length)
|
||||
throw new ArgumentException("File size in header does not match.", "fileData");
|
||||
// Only allowing standard 24x24 size
|
||||
if (hdrHeight != 24 || hdrWidth != 24)
|
||||
throw new ArgumentException("Only 24×24 pixel tiles are supported.", "fileData");
|
||||
// Checking some normally hardcoded values
|
||||
if (hdrAllocated != 00 || hdrPalettesPtr != 0)
|
||||
throw new ArgumentException("Invalid values encountered in header.");
|
||||
if (hdrCount == 0)
|
||||
throw new ArgumentException("Tileset files with 0 tiles are not supported!", "fileData");
|
||||
@ -556,14 +635,6 @@ namespace MobiusEditor.Utility
|
||||
return tiles;
|
||||
}
|
||||
|
||||
public static Byte[][] GetRaTmpData(Byte[] fileData, out int width, out int height)
|
||||
{
|
||||
width = 24;
|
||||
height = 24;
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Color[] LoadSixBitPalette(Byte[] fileData, int palStart, int colors)
|
||||
{
|
||||
Color[] palette = Enumerable.Repeat(Color.Black, colors).ToArray();
|
||||
|
@ -278,6 +278,45 @@ namespace MobiusEditor.Utility
|
||||
return GeneralUtils.GetBoundingBoxCenter(image.Width, image.Height, maxWidth, maxHeight);
|
||||
}
|
||||
|
||||
public static void RemoveAlphaOnCurrent(this Bitmap bitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
|
||||
if ((bitmap.PixelFormat & PixelFormat.Indexed) == PixelFormat.Indexed)
|
||||
{
|
||||
ColorPalette pal = bitmap.Palette;
|
||||
for (int i = 0; i < pal.Entries.Length; i++)
|
||||
{
|
||||
pal.Entries[i] = Color.FromArgb(255, pal.Entries[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
|
||||
{
|
||||
// can't handle.
|
||||
return;
|
||||
}
|
||||
BitmapData sourceData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
Int32 actualDataWidth = rect.Width * 4;
|
||||
Int32 h = bitmap.Height;
|
||||
Int32 origStride = sourceData.Stride;
|
||||
Byte[] imageData = new Byte[actualDataWidth];
|
||||
Int64 sourcePos = sourceData.Scan0.ToInt64();
|
||||
// Copy line by line, skipping by stride but copying actual data width
|
||||
for (Int32 y = 0; y < h; ++y)
|
||||
{
|
||||
Marshal.Copy(new IntPtr(sourcePos), imageData, 0, actualDataWidth);
|
||||
for (int i = 3; i < actualDataWidth; i += 4)
|
||||
{
|
||||
// Clear alpha
|
||||
imageData[i] = 255;
|
||||
}
|
||||
Marshal.Copy(imageData, 0, new IntPtr(sourcePos), actualDataWidth);
|
||||
sourcePos += origStride;
|
||||
}
|
||||
bitmap.UnlockBits(sourceData);
|
||||
return;
|
||||
}
|
||||
|
||||
public static Bitmap RemoveAlpha(this Bitmap bitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
|
||||
@ -285,7 +324,7 @@ namespace MobiusEditor.Utility
|
||||
targetImage.SetResolution(bitmap.HorizontalResolution, bitmap.VerticalResolution);
|
||||
BitmapData sourceData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
BitmapData targetData = targetImage.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
Int32 actualDataWidth = ((Image.GetPixelFormatSize(bitmap.PixelFormat) * rect.Width) + 7) / 8;
|
||||
Int32 actualDataWidth = ((Image.GetPixelFormatSize(PixelFormat.Format32bppArgb) * rect.Width) + 7) / 8;
|
||||
Int32 h = bitmap.Height;
|
||||
Int32 origStride = sourceData.Stride;
|
||||
Int32 targetStride = targetData.Stride;
|
||||
|
@ -16,7 +16,7 @@ namespace MobiusEditor.Utility
|
||||
private bool isEmbedded = false;
|
||||
private long fileStart;
|
||||
private long fileLength;
|
||||
private long dataStart;
|
||||
private uint dataStart;
|
||||
|
||||
public Mixfile(string mixPath)
|
||||
{
|
||||
@ -42,18 +42,18 @@ namespace MobiusEditor.Utility
|
||||
this.fileLength = length;
|
||||
// Copy reference to parent map. The "CreateViewStream" function takes care of reading the right parts from it.
|
||||
this.mixFileMap = container.mixFileMap;
|
||||
this.ReadMixHeader(mixFileMap, offset, fileLength);
|
||||
this.ReadMixHeader(this.mixFileMap, offset, this.fileLength);
|
||||
}
|
||||
|
||||
private void ReadMixHeader(MemoryMappedFile mixMap, long mixStart, long mixLength)
|
||||
{
|
||||
mixFileContents.Clear();
|
||||
this.mixFileContents.Clear();
|
||||
uint readOffset = 0;
|
||||
ushort nrOfFiles = 0;
|
||||
bool hasFlags = false;
|
||||
bool encrypted = false;
|
||||
bool checksum = false;
|
||||
using (BinaryReader headerReader = new BinaryReader(CreateViewStream(mixMap, mixStart, mixLength, readOffset, 2)))
|
||||
using (BinaryReader headerReader = new BinaryReader(this.CreateViewStream(mixMap, mixStart, mixLength, readOffset, 2)))
|
||||
{
|
||||
ushort start = headerReader.ReadUInt16();
|
||||
if (start == 0)
|
||||
@ -64,9 +64,9 @@ namespace MobiusEditor.Utility
|
||||
}
|
||||
if (hasFlags)
|
||||
{
|
||||
using (BinaryReader headerReader = new BinaryReader(CreateViewStream(mixMap, mixStart, mixLength, readOffset, 2)))
|
||||
using (BinaryReader headerReader = new BinaryReader(this.CreateViewStream(mixMap, mixStart, mixLength, readOffset, 2)))
|
||||
{
|
||||
var flags = headerReader.ReadUInt16();
|
||||
ushort flags = headerReader.ReadUInt16();
|
||||
checksum = (flags & 1) != 0;
|
||||
encrypted = (flags & 2) != 0;
|
||||
readOffset += 2;
|
||||
@ -74,7 +74,7 @@ namespace MobiusEditor.Utility
|
||||
// Not encrypted; read nr of files.
|
||||
if (!encrypted)
|
||||
{
|
||||
using (BinaryReader headerReader = new BinaryReader(CreateViewStream(mixMap, mixStart, mixLength, readOffset, 2)))
|
||||
using (BinaryReader headerReader = new BinaryReader(this.CreateViewStream(mixMap, mixStart, mixLength, readOffset, 2)))
|
||||
{
|
||||
nrOfFiles = headerReader.ReadUInt16();
|
||||
readOffset += 2;
|
||||
@ -85,7 +85,7 @@ namespace MobiusEditor.Utility
|
||||
Byte[] header = null;
|
||||
if (encrypted)
|
||||
{
|
||||
using (BinaryReader headerReader = new BinaryReader(CreateViewStream(mixMap, mixStart, mixLength, readOffset, 80)))
|
||||
using (BinaryReader headerReader = new BinaryReader(this.CreateViewStream(mixMap, mixStart, mixLength, readOffset, 80)))
|
||||
{
|
||||
byte[] blowfishKey = headerReader.ReadAllBytes();
|
||||
readOffset += 80;
|
||||
@ -102,7 +102,7 @@ namespace MobiusEditor.Utility
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Not a valid mix file: header length exceeds file length.");
|
||||
}
|
||||
using (BinaryReader headerReader = new BinaryReader(CreateViewStream(mixMap, mixStart, mixLength, readOffset, headerSize)))
|
||||
using (BinaryReader headerReader = new BinaryReader(this.CreateViewStream(mixMap, mixStart, mixLength, readOffset, headerSize)))
|
||||
{
|
||||
header = headerReader.ReadBytes((Int32)headerSize);
|
||||
// End of header reading; no longer needed.
|
||||
@ -123,7 +123,7 @@ namespace MobiusEditor.Utility
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(String.Format("Not a valid mix file: file #{0} with id {1:X08} exceeds archive length.", i, fileId));
|
||||
}
|
||||
mixFileContents.Add(fileId, (fileOffset, fileLength));
|
||||
this.mixFileContents.Add(fileId, (fileOffset, fileLength));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,26 +132,24 @@ namespace MobiusEditor.Utility
|
||||
{
|
||||
offset = 0;
|
||||
length = 0;
|
||||
uint fileId = hashRol.GetNameId(filename);
|
||||
uint fileId = this.hashRol.GetNameId(filename);
|
||||
(uint Offset, uint Length) fileLoc;
|
||||
if (!mixFileContents.TryGetValue(fileId, out fileLoc))
|
||||
if (!this.mixFileContents.TryGetValue(fileId, out fileLoc))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
offset = fileLoc.Offset;
|
||||
offset = fileLoc.Offset + this.dataStart;
|
||||
length = fileLoc.Length;
|
||||
return true;
|
||||
}
|
||||
|
||||
public Stream OpenFile(string path)
|
||||
{
|
||||
uint fileId = hashRol.GetNameId(path);
|
||||
(uint Offset, uint Length) fileLoc;
|
||||
if (!mixFileContents.TryGetValue(fileId, out fileLoc))
|
||||
if (!this.GetFileInfo(path, out uint offset, out uint length))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return CreateViewStream(mixFileMap, fileStart, fileLength, this.dataStart + fileLoc.Offset, fileLoc.Length);
|
||||
return this.CreateViewStream(this.mixFileMap, this.fileStart, this.fileLength, offset, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -166,7 +164,7 @@ namespace MobiusEditor.Utility
|
||||
/// <exception cref="IndexOutOfRangeException">The data is not in the bounds of this mix file.</exception>
|
||||
private Stream CreateViewStream(MemoryMappedFile mixMap, long mixFileStart, long mixFileLength, long dataReadOffset, uint dataReadLength)
|
||||
{
|
||||
if (disposedValue)
|
||||
if (this.disposedValue)
|
||||
{
|
||||
throw new ObjectDisposedException("Mixfile");
|
||||
}
|
||||
@ -182,22 +180,22 @@ namespace MobiusEditor.Utility
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
if (!this.disposedValue)
|
||||
{
|
||||
// Only dispose if not an embedded mix file.
|
||||
// If embedded, the mixFileMap is contained in the parent.
|
||||
if (disposing && !isEmbedded)
|
||||
if (disposing && !this.isEmbedded)
|
||||
{
|
||||
mixFileMap.Dispose();
|
||||
this.mixFileMap.Dispose();
|
||||
}
|
||||
mixFileMap = null;
|
||||
disposedValue = true;
|
||||
this.mixFileMap = null;
|
||||
this.disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
this.Dispose(true);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ namespace MobiusEditor.Utility
|
||||
this.Name = name;
|
||||
this.UnitRadarColor = unitRadarColor;
|
||||
this.BuildingRadarColor = buildingRadarColor;
|
||||
this.remapTable = Enumerable.Range(0, 0x100).Select(b => (Byte)b).ToArray();
|
||||
this.remapTable = Enumerable.Range(0, 0x100).Select(b => (byte)b).ToArray();
|
||||
int max = Math.Min(0x100, remapstart + remapValues.Length) - remapstart;
|
||||
for (int i = 0; i < max; ++i)
|
||||
{
|
||||
@ -53,7 +53,7 @@ namespace MobiusEditor.Utility
|
||||
this.Name = name;
|
||||
this.UnitRadarColor = unitRadarColor;
|
||||
this.BuildingRadarColor = buildingRadarColor;
|
||||
this.remapTable = Enumerable.Range(0, 0x100).Cast<byte>().ToArray();
|
||||
this.remapTable = Enumerable.Range(0, 0x100).Select(b => (byte)b).ToArray();
|
||||
int max = Math.Max(remapOrigins.Length, remapValues.Length);
|
||||
for (int i = 0; i < max; ++i)
|
||||
{
|
||||
@ -100,6 +100,7 @@ namespace MobiusEditor.Utility
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyToImage(byte[] bytes, int width, int height, int bytesPerPixel, int stride, Rectangle? opaqueBounds)
|
||||
{
|
||||
// Only handle 8bpp data.
|
||||
@ -110,7 +111,7 @@ namespace MobiusEditor.Utility
|
||||
Rectangle bounds = opaqueBounds ?? new Rectangle(0, 0, width, height);
|
||||
int boundsBottom = Math.Min(height, bounds.Bottom);
|
||||
int boundsWidth = Math.Min(Math.Max(0, width - bounds.Left), bounds.Width);
|
||||
int linePtr = 0;
|
||||
int linePtr = bounds.Top * stride;
|
||||
for (int y = bounds.Top; y < boundsBottom; y++)
|
||||
{
|
||||
int ptr = linePtr + bounds.Left;
|
||||
|
@ -32,7 +32,7 @@ namespace MobiusEditor.Utility
|
||||
|
||||
static TeamRemapManager()
|
||||
{
|
||||
RemapsTd = (from field in typeof(ITeamColorManager).GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||
RemapsTd = (from field in typeof(TeamRemapManager).GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||
where field.IsInitOnly && typeof(TeamRemap).IsAssignableFrom(field.FieldType) && field.Name.StartsWith("RemapTd")
|
||||
select field.GetValue(null) as TeamRemap).ToDictionary(trm => trm.Name);
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ namespace MobiusEditor.Utility
|
||||
{
|
||||
if (generateFallback && tiles.Any(t => t.Image == null))
|
||||
{
|
||||
// Tile found, but contains no data. Re-fetch with dummy generation.
|
||||
// Tile not found, or contains no data. Re-fetch with dummy generation.
|
||||
if (tileset.GetTileData(name, shape, teamColor, out fps, out tiles, true))
|
||||
{
|
||||
// Signal in return value that dummy was generated.
|
||||
@ -151,7 +151,7 @@ namespace MobiusEditor.Utility
|
||||
}
|
||||
}
|
||||
// If the tile is not defined at all, and onlyifdefined is not enabled, make a dummy entry anyway.
|
||||
if (!onlyIfDefined && generateFallback && first != null && first.GetTileData(name, shape, teamColor, out fps, out tiles, true))
|
||||
if (generateFallback && !onlyIfDefined && first != null && first.GetTileData(name, shape, teamColor, out fps, out tiles, true))
|
||||
{
|
||||
// Signal in return value that dummy was generated.
|
||||
return false;
|
||||
|
@ -60,7 +60,7 @@ namespace MobiusEditor.Utility
|
||||
this.currentlyLoadedPalette = TeamRemapManager.GetPaletteForTheater(this.archiveManager, theater);
|
||||
}
|
||||
|
||||
public Boolean GetTeamColorTileData(String name, Int32 shape, ITeamColor teamColor, out Tile tile, Boolean generateFallback, Boolean onlyIfDefined)
|
||||
public Boolean GetTeamColorTileData(String name, Int32 shape, ITeamColor teamColor, out Tile tile, Boolean generateFallback, Boolean onlyIfDefined, string remapGraphicsSource, byte[] remapTable)
|
||||
{
|
||||
tile = null;
|
||||
String teamColorName = teamColor == null ? String.Empty : (teamColor.Name ?? String.Empty);
|
||||
@ -78,7 +78,8 @@ namespace MobiusEditor.Utility
|
||||
}
|
||||
else
|
||||
{
|
||||
shapeFile = this.GetShapeFile(name);
|
||||
// If there's a remap graphics source, prefer that.
|
||||
shapeFile = this.GetShapeFile(remapGraphicsSource ?? name);
|
||||
if (shapeFile == null)
|
||||
{
|
||||
if (!generateFallback)
|
||||
@ -88,25 +89,44 @@ namespace MobiusEditor.Utility
|
||||
shapeFile = new Dictionary<int, ShapeFrameData>();
|
||||
}
|
||||
tileData[name] = shapeFile;
|
||||
// System to fix RA's remapped infantry. Since everything is cached, this only works if the very
|
||||
// first call to fetch these graphics is guaranteed to pass along the graphics source and remap info.
|
||||
if (remapTable != null && remapTable.Length >= 0x100)
|
||||
{
|
||||
foreach (int key in shapeFile.Keys)
|
||||
{
|
||||
ShapeFrameData sfd = shapeFile[key];
|
||||
Byte[] frameGfx = sfd.FrameData;
|
||||
for (int i = 0; i < frameGfx.Length; ++i)
|
||||
{
|
||||
frameGfx[i] = remapTable[frameGfx[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remaps the tile, and takes care of caching it and possibly generating dummies.
|
||||
tile = this.RemapShapeFile(shapeFile, shape, teamColor, generateFallback);
|
||||
}
|
||||
return tile != null;
|
||||
}
|
||||
|
||||
public Boolean GetTeamColorTileData(String name, Int32 shape, ITeamColor teamColor, out Tile tile)
|
||||
public Boolean GetTeamColorTileData(String name, Int32 shape, ITeamColor teamColor, out Tile tile, Boolean generateFallback, Boolean onlyIfDefined)
|
||||
{
|
||||
return GetTeamColorTileData(name, shape, teamColor, out tile, false, false);
|
||||
return GetTeamColorTileData(name, shape, teamColor, out tile, generateFallback, onlyIfDefined, null, null);
|
||||
}
|
||||
|
||||
public Boolean GetTileData(String name, Int32 shape, out Tile tile, Boolean generateFallback, Boolean onlyIfDefined)
|
||||
{
|
||||
return GetTeamColorTileData(name, shape, null, out tile, false, false);
|
||||
return GetTeamColorTileData(name, shape, null, out tile, generateFallback, onlyIfDefined, null, null);
|
||||
}
|
||||
|
||||
public Boolean GetTeamColorTileData(String name, Int32 shape, ITeamColor teamColor, out Tile tile)
|
||||
{
|
||||
return GetTeamColorTileData(name, shape, teamColor, out tile, false, false, null, null);
|
||||
}
|
||||
|
||||
public Boolean GetTileData(String name, Int32 shape, out Tile tile)
|
||||
{
|
||||
return GetTeamColorTileData(name, shape, null, out tile, false, false);
|
||||
return GetTeamColorTileData(name, shape, null, out tile, false, false, null, null);
|
||||
}
|
||||
|
||||
public int GetTileDataLength(string name)
|
||||
@ -117,7 +137,13 @@ namespace MobiusEditor.Utility
|
||||
}
|
||||
if (!this.tileData.TryGetValue(name, out Dictionary<int, ShapeFrameData> shapes))
|
||||
{
|
||||
return -1;
|
||||
// If it's not cached yet, fetch without caching. This avoids issues with the special remap system.
|
||||
// These ShapeFrameData objects don't need to be disposed since they can't contain Bitmap objects yet.
|
||||
shapes = GetShapeFile(name);
|
||||
if (shapes == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return shapes.Max(kv => kv.Key) + 1;
|
||||
}
|
||||
@ -125,8 +151,22 @@ namespace MobiusEditor.Utility
|
||||
private Dictionary<int, ShapeFrameData> GetShapeFile(String name)
|
||||
{
|
||||
bool isShpExt = false;
|
||||
Byte[] fileContents = null;
|
||||
// If it has an extension, force it.
|
||||
if (Path.HasExtension(name))
|
||||
{
|
||||
fileContents = GetFileContents(name);
|
||||
// Immediately abort; classic file system does not support double extensions.
|
||||
if (fileContents == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Try theater extension, then ".shp".
|
||||
Byte[] fileContents = GetFileContents(name + "." + theater.ClassicExtension);
|
||||
if (fileContents == null)
|
||||
{
|
||||
fileContents = GetFileContents(name + "." + theater.ClassicExtension);
|
||||
}
|
||||
if (fileContents == null)
|
||||
{
|
||||
isShpExt = true;
|
||||
@ -168,15 +208,7 @@ namespace MobiusEditor.Utility
|
||||
try
|
||||
{
|
||||
// RA map template tileset
|
||||
int width;
|
||||
int height;
|
||||
shpData = ClassicSpriteLoader.GetRaTmpData(fileContents, out width, out height);
|
||||
if (shpData != null)
|
||||
{
|
||||
int len = shpData.Length;
|
||||
widths = Enumerable.Repeat(width, len).ToArray();
|
||||
heights = Enumerable.Repeat(height, len).ToArray();
|
||||
}
|
||||
shpData = ClassicSpriteLoader.GetRaTmpData(fileContents, out widths, out heights);
|
||||
}
|
||||
catch (ArgumentException) { /* ignore */ }
|
||||
}
|
||||
@ -228,10 +260,11 @@ namespace MobiusEditor.Utility
|
||||
return null;
|
||||
}
|
||||
// Make average-sized dummy.
|
||||
int minWidth = shapeFile.Values.Where(v => v.Width != 0).Min(v => v.Width);
|
||||
int maxWidth = shapeFile.Values.Where(v => v.Width != 0).Max(v => v.Width);
|
||||
int minHeight = shapeFile.Values.Where(v => v.Height != 0).Min(v => v.Height);
|
||||
int maxHeight = shapeFile.Values.Where(v => v.Height != 0).Max(v => v.Height);
|
||||
bool noValues = shapeFile.Values.Count == 0;
|
||||
int minWidth = noValues? 24 : shapeFile.Values.Where(v => v.Width != 0).Min(v => v.Width);
|
||||
int maxWidth = noValues? 24 : shapeFile.Values.Where(v => v.Width != 0).Max(v => v.Width);
|
||||
int minHeight = noValues? 24 : shapeFile.Values.Where(v => v.Height != 0).Min(v => v.Height);
|
||||
int maxHeight = noValues? 24 : shapeFile.Values.Where(v => v.Height != 0).Max(v => v.Height);
|
||||
int dummyWidth = minWidth + (maxWidth - minWidth) / 2;
|
||||
int dummyHeight = minHeight + (maxHeight - minHeight) / 2;
|
||||
frameData = GenerateDummy(dummyWidth, dummyHeight);
|
||||
@ -249,9 +282,20 @@ namespace MobiusEditor.Utility
|
||||
if (teamColor != null && !String.IsNullOrEmpty(teamColorName) && !frameData.IsDummy)
|
||||
{
|
||||
// Finally, the actual remapping!
|
||||
teamColor.ApplyToImage(data, width, height, 1, width, opaqueBounds);
|
||||
byte[] dataRemap = new byte[data.Length];
|
||||
Array.Copy(data, 0, dataRemap, 0, data.Length);
|
||||
teamColor.ApplyToImage(dataRemap, width, height, 1, width, opaqueBounds);
|
||||
data = dataRemap;
|
||||
}
|
||||
Bitmap bm = ImageUtils.BuildImage(data, width, height, width, PixelFormat.Format8bppIndexed, currentlyLoadedPalette, null);
|
||||
Color[] pal = currentlyLoadedPalette;
|
||||
if (frameData.IsDummy)
|
||||
{
|
||||
// Make gray colour semitransparent on dummy graphics.
|
||||
pal = new Color[currentlyLoadedPalette.Length];
|
||||
Array.Copy(currentlyLoadedPalette, 0, pal, 0, pal.Length);
|
||||
pal[14] = Color.FromArgb(0x80, pal[14]);
|
||||
}
|
||||
Bitmap bm = ImageUtils.BuildImage(data, width, height, width, PixelFormat.Format8bppIndexed, pal, null);
|
||||
tile = new Tile(bm, opaqueBounds);
|
||||
frameData.TeamColorTiles.Add(teamColorName, tile);
|
||||
return tile;
|
||||
|
Loading…
x
Reference in New Issue
Block a user