Restricted fill to map bounds, and added a .exe.config option to control this behavior
Better indication of occupied cells on tool previews and on the map placement preview. Added bibs to building previews Added .exe.config option to allow theater-illegal objects Re-enabled aircraft, controlled by a .exe.config option Re-enabled craters CR2-CR6, controlled by a .exe.config option Added code to disable trigger select field for Aircraft Disabled remap on RA civilian buildings. Added the unused Desert civilian buildings to the RA buildings list. Added optimising to not repaint the entire map when changing indicators that are purely handled in post-render. Changed version to 1.4.3.0 Fixed resource issues in some forms. Haystacks/igloos in RA are now called "Haystack" rather than "Civilian Building" Smudge icon does not reset when selecting different smudge (only noticeable when other craters are enabled)
This commit is contained in:
parent
a9ba2bdcd3
commit
007d6f3c5a
@ -16,12 +16,6 @@
|
||||
<setting name="ModsToLoad" serializeAs="String">
|
||||
<value>2844969675;Tiberian_Dawn\ConcretePavementTD</value>
|
||||
</setting>
|
||||
<setting name="NoMetaFilesForSinglePlay" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="IgnoreBibs" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="MapScale" serializeAs="String">
|
||||
<value>0.5</value>
|
||||
</setting>
|
||||
@ -40,12 +34,30 @@
|
||||
<setting name="ObjectToolItemSizeMultiplier" serializeAs="String">
|
||||
<value>0.3</value>
|
||||
</setting>
|
||||
<setting name="IgnoreRaObsoleteClear" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="UndoRedoStackSize" serializeAs="String">
|
||||
<value>50</value>
|
||||
</setting>
|
||||
<setting name="NoMetaFilesForSinglePlay" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="ConvertRaObsoleteClear" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="BlockingBibs" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="DisableAirUnits" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="ConvertCraters" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="BoundsObstructFill" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="FilterTheaterObjects" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
</MobiusEditor.Properties.Settings>
|
||||
</applicationSettings>
|
||||
<userSettings>
|
||||
|
@ -119,13 +119,14 @@ namespace MobiusEditor.Controls
|
||||
string[] items;
|
||||
string[] filteredEvents;
|
||||
string[] filteredActions;
|
||||
Boolean isAircraft = obj is Unit un && un.Type.IsAircraft;
|
||||
switch (obj)
|
||||
{
|
||||
case Infantry infantry:
|
||||
case Unit unit:
|
||||
items = Plugin.Map.FilterUnitTriggers().Select(t => t.Name).Distinct().ToArray();
|
||||
filteredEvents = Plugin.Map.EventTypes.Where(ev => Plugin.Map.UnitEventTypes.Contains(ev)).Distinct().ToArray();
|
||||
filteredActions = Plugin.Map.ActionTypes.Where(ac => Plugin.Map.UnitActionTypes.Contains(ac)).Distinct().ToArray();
|
||||
filteredEvents = isAircraft ? new string[0] : Plugin.Map.EventTypes.Where(ev => Plugin.Map.UnitEventTypes.Contains(ev)).Distinct().ToArray();
|
||||
filteredActions = isAircraft ? new string[0] : Plugin.Map.ActionTypes.Where(ac => Plugin.Map.UnitActionTypes.Contains(ac)).Distinct().ToArray();
|
||||
break;
|
||||
case Building building:
|
||||
items = Plugin.Map.FilterStructureTriggers().Select(t => t.Name).Distinct().ToArray();
|
||||
@ -142,6 +143,7 @@ namespace MobiusEditor.Controls
|
||||
items = Trigger.None.Yield().Concat(Plugin.Map.Triggers.Select(t => t.Name).Where(t => allowedTriggers.Contains(t)).Distinct()).ToArray();
|
||||
int selectIndex = selected == null ? 0 : Enumerable.Range(0, items.Length).FirstOrDefault(x => String.Equals(items[x], selected, StringComparison.InvariantCultureIgnoreCase));
|
||||
triggerComboBox.DataSource = items;
|
||||
triggerComboBox.Enabled = !isAircraft;
|
||||
triggerToolTip = Map.MakeAllowedTriggersToolTip(filteredEvents, filteredActions);
|
||||
if (obj != null)
|
||||
{
|
||||
@ -355,6 +357,10 @@ namespace MobiusEditor.Controls
|
||||
{
|
||||
tooltip = "Triggers can only be linked to prebuilt structures.";
|
||||
}
|
||||
else if (Object is Unit un && un.Type.IsAircraft)
|
||||
{
|
||||
tooltip = "Triggers can not be linked to aircraft.";
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltip = triggerToolTip;
|
||||
|
@ -14,11 +14,8 @@
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
using MobiusEditor.Interface;
|
||||
using MobiusEditor.Model;
|
||||
using MobiusEditor.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
@ -85,7 +82,10 @@ namespace MobiusEditor.Controls
|
||||
return;
|
||||
}
|
||||
UpdateDataSource();
|
||||
stateComboBox.DataBindings.Add("SelectedItem", smudge, "Icon");
|
||||
if (stateComboBox.Items.Count > 1)
|
||||
{
|
||||
stateComboBox.DataBindings.Add("SelectedItem", smudge, "Icon");
|
||||
}
|
||||
stateComboBox.Enabled = stateComboBox.Items.Count > 1;
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,13 @@ namespace MobiusEditor
|
||||
PreviewSmoothScale = Properties.Settings.Default.PreviewScale < 0;
|
||||
ExportTileScale = Math.Min(1, Math.Max(0.05f, Math.Abs(Properties.Settings.Default.ExportScale)));
|
||||
ExportSmoothScale = Properties.Settings.Default.ExportScale < 0;
|
||||
IgnoreBibs = Properties.Settings.Default.IgnoreBibs;
|
||||
IgnoreRaObsoleteClear = Properties.Settings.Default.IgnoreRaObsoleteClear;
|
||||
UndoRedoStackSize = Properties.Settings.Default.UndoRedoStackSize;
|
||||
DisableAirUnits = Properties.Settings.Default.DisableAirUnits;
|
||||
ConvertCraters = Properties.Settings.Default.ConvertCraters;
|
||||
BlockingBibs = Properties.Settings.Default.BlockingBibs;
|
||||
ConvertRaObsoleteClear = Properties.Settings.Default.ConvertRaObsoleteClear;
|
||||
BoundsObstructFill = Properties.Settings.Default.BoundsObstructFill;
|
||||
FilterTheaterObjects = Properties.Settings.Default.FilterTheaterObjects;
|
||||
}
|
||||
|
||||
public const string TilesetsXMLPath = @"DATA\XML\TILESETS.XML";
|
||||
@ -61,8 +65,12 @@ namespace MobiusEditor
|
||||
public static int ExportTileHeight => Math.Max(1, (int)(OriginalTileHeight * ExportTileScale));
|
||||
public static Size ExportTileSize => new Size(ExportTileWidth, ExportTileHeight);
|
||||
|
||||
public static bool IgnoreBibs;
|
||||
public static bool IgnoreRaObsoleteClear;
|
||||
public static bool DisableAirUnits;
|
||||
public static bool ConvertCraters;
|
||||
public static bool BlockingBibs;
|
||||
public static bool ConvertRaObsoleteClear;
|
||||
public static bool BoundsObstructFill;
|
||||
public static bool FilterTheaterObjects;
|
||||
|
||||
public static int UndoRedoStackSize = 50;
|
||||
|
||||
|
@ -1086,13 +1086,14 @@ namespace MobiusEditor
|
||||
availableToolTypes |= ToolType.Waypoint;
|
||||
if (plugin.Map.TemplateTypes.Any(t => t.Theaters == null || t.Theaters.Contains(th))) availableToolTypes |= ToolType.Map;
|
||||
if (plugin.Map.SmudgeTypes.Any()) availableToolTypes |= ToolType.Smudge;
|
||||
if (plugin.Map.OverlayTypes.Any(t => t.IsPlaceable && ((t.Theaters == null) || t.Theaters.Contains(th)))) availableToolTypes |= ToolType.Overlay;
|
||||
if (plugin.Map.TerrainTypes.Any(t => t.Theaters == null || t.Theaters.Contains(th))) availableToolTypes |= ToolType.Terrain;
|
||||
if (plugin.Map.OverlayTypes.Any(t => t.IsPlaceable && (!Globals.FilterTheaterObjects || t.Theaters == null || t.Theaters.Contains(th)))) availableToolTypes |= ToolType.Overlay;
|
||||
if (plugin.Map.TerrainTypes.Any(t => !Globals.FilterTheaterObjects || t.Theaters == null || t.Theaters.Contains(th))) availableToolTypes |= ToolType.Terrain;
|
||||
if (plugin.Map.InfantryTypes.Any()) availableToolTypes |= ToolType.Infantry;
|
||||
if (plugin.Map.UnitTypes.Any()) availableToolTypes |= ToolType.Unit;
|
||||
if (plugin.Map.BuildingTypes.Any(t => t.Theaters == null || t.Theaters.Contains(th))) availableToolTypes |= ToolType.Building;
|
||||
if (plugin.Map.OverlayTypes.Any(t => t.IsResource && (t.Theaters == null || t.Theaters.Contains(th)))) availableToolTypes |= ToolType.Resources;
|
||||
if (plugin.Map.OverlayTypes.Any(t => t.IsWall && (t.Theaters == null || t.Theaters.Contains(th)))) availableToolTypes |= ToolType.Wall;
|
||||
if (plugin.Map.BuildingTypes.Any(t => !Globals.FilterTheaterObjects || t.Theaters == null || t.Theaters.Contains(th))) availableToolTypes |= ToolType.Building;
|
||||
if (plugin.Map.OverlayTypes.Any(t => t.IsResource && (!Globals.FilterTheaterObjects || t.Theaters == null || t.Theaters.Contains(th)))) availableToolTypes |= ToolType.Resources;
|
||||
if (plugin.Map.OverlayTypes.Any(t => t.IsWall && (!Globals.FilterTheaterObjects || t.Theaters == null || t.Theaters.Contains(th)))) availableToolTypes |= ToolType.Wall;
|
||||
// Always allow celltrigger tool, even if triggers list is empty; it contains a tooltip saying which triggers are eligible.
|
||||
availableToolTypes |= ToolType.CellTrigger;
|
||||
}
|
||||
foreach (var toolStripButton in viewToolStripButtons)
|
||||
|
@ -14,6 +14,7 @@
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
using MobiusEditor.Interface;
|
||||
using MobiusEditor.Render;
|
||||
using MobiusEditor.Tools;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
@ -29,6 +30,7 @@ namespace MobiusEditor.Model
|
||||
Fake = (1 << 2),
|
||||
Turret = (1 << 3),
|
||||
SingleFrame = (1 << 4),
|
||||
NoRemap = (1 << 5),
|
||||
}
|
||||
|
||||
public class BuildingType : ICellOverlapper, ICellOccupier, ITechnoType, IBrowsableType
|
||||
@ -76,22 +78,16 @@ namespace MobiusEditor.Model
|
||||
}
|
||||
|
||||
public string OwnerHouse { get; private set; }
|
||||
|
||||
public TheaterType[] Theaters { get; private set; }
|
||||
|
||||
public bool IsFake => (Flag & BuildingTypeFlag.Fake) == BuildingTypeFlag.Fake;
|
||||
|
||||
public bool HasTurret => (Flag & BuildingTypeFlag.Turret) == BuildingTypeFlag.Turret;
|
||||
|
||||
public string FactoryOverlay { get; private set; }
|
||||
|
||||
public Bitmap Thumbnail { get; set; }
|
||||
|
||||
public bool IsArmed => false; // Not actually true, but irrelevant for practical purposes; their Mission is not set in the ini file.
|
||||
|
||||
public bool IsHarvester => false;
|
||||
|
||||
public bool IsFake => (Flag & BuildingTypeFlag.Fake) == BuildingTypeFlag.Fake;
|
||||
public bool HasTurret => (Flag & BuildingTypeFlag.Turret) == BuildingTypeFlag.Turret;
|
||||
public bool IsSingleFrame => (Flag & BuildingTypeFlag.SingleFrame) == BuildingTypeFlag.SingleFrame;
|
||||
public bool CanRemap => (Flag & BuildingTypeFlag.NoRemap) != BuildingTypeFlag.NoRemap;
|
||||
|
||||
public BuildingType(sbyte id, string name, string textId, int powerProd, int powerUse, int storage, bool[,] occupyMask, string ownerHouse, TheaterType[] theaters, string factoryOverlay, BuildingTypeFlag flag)
|
||||
{
|
||||
@ -113,6 +109,11 @@ namespace MobiusEditor.Model
|
||||
RecalculateBibs();
|
||||
}
|
||||
|
||||
public BuildingType(sbyte id, string name, string textId, int powerProd, int powerUse, bool[,] occupyMask, string ownerHouse, TheaterType[] theaters, BuildingTypeFlag flag)
|
||||
: this(id, name, textId, powerProd, powerUse, 0, occupyMask, ownerHouse, theaters, null, flag)
|
||||
{
|
||||
}
|
||||
|
||||
public BuildingType(sbyte id, string name, string textId, int powerProd, int powerUse, int storage, bool[,] occupyMask, string ownerHouse)
|
||||
: this(id, name, textId, powerProd, powerUse, storage, occupyMask, ownerHouse, null, null, BuildingTypeFlag.None)
|
||||
{
|
||||
@ -157,7 +158,7 @@ namespace MobiusEditor.Model
|
||||
OccupyMask[y, x] = BaseOccupyMask[y, x];
|
||||
}
|
||||
}
|
||||
if (!Globals.IgnoreBibs)
|
||||
if (Globals.BlockingBibs)
|
||||
{
|
||||
for (var x = 0; x < maskX; ++x)
|
||||
{
|
||||
@ -244,6 +245,10 @@ namespace MobiusEditor.Model
|
||||
{
|
||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||
render.Item2(g);
|
||||
if (IsFake)
|
||||
{
|
||||
ViewTool.RenderBuildingLabels(g, mockBuilding, Point.Empty, Globals.PreviewTileSize, Globals.PreviewTileScale, MapLayerFlag.BuildingFakes, false);
|
||||
}
|
||||
}
|
||||
Thumbnail = buildingPreview;
|
||||
}
|
||||
|
@ -37,19 +37,20 @@ namespace MobiusEditor.Model
|
||||
Walls = 1 << 3,
|
||||
Overlay = 1 << 4,
|
||||
Smudge = 1 << 5,
|
||||
Waypoints = 1 << 6,
|
||||
CellTriggers = 1 << 7,
|
||||
Infantry = 1 << 8,
|
||||
Units = 1 << 9,
|
||||
Buildings = 1 << 10,
|
||||
Boundaries = 1 << 11,
|
||||
Infantry = 1 << 6,
|
||||
Units = 1 << 7,
|
||||
Buildings = 1 << 8,
|
||||
|
||||
Boundaries = 1 << 9,
|
||||
Waypoints = 1 << 10,
|
||||
CellTriggers = 1 << 11,
|
||||
TechnoTriggers = 1 << 12,
|
||||
BuildingRebuild = 1 << 13,
|
||||
BuildingFakes = 1 << 14,
|
||||
|
||||
OverlayAll = Resources | Walls | Overlay,
|
||||
Technos = Terrain | Walls | Infantry | Units | Buildings | BuildingFakes,
|
||||
|
||||
Indicators = Boundaries | Waypoints | CellTriggers | TechnoTriggers | BuildingRebuild | BuildingFakes,
|
||||
All = int.MaxValue
|
||||
}
|
||||
|
||||
|
@ -45,5 +45,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.4.2.1")]
|
||||
[assembly: AssemblyVersion("1.4.3.0")]
|
||||
// [assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
84
CnCTDRAMapEditor/Properties/Settings.Designer.cs
generated
84
CnCTDRAMapEditor/Properties/Settings.Designer.cs
generated
@ -32,24 +32,6 @@ namespace MobiusEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool NoMetaFilesForSinglePlay {
|
||||
get {
|
||||
return ((bool)(this["NoMetaFilesForSinglePlay"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool IgnoreBibs {
|
||||
get {
|
||||
return ((bool)(this["IgnoreBibs"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0.5")]
|
||||
@ -106,19 +88,73 @@ namespace MobiusEditor.Properties {
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool IgnoreRaObsoleteClear {
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("50")]
|
||||
public int UndoRedoStackSize {
|
||||
get {
|
||||
return ((bool)(this["IgnoreRaObsoleteClear"]));
|
||||
return ((int)(this["UndoRedoStackSize"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("50")]
|
||||
public int UndoRedoStackSize {
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool NoMetaFilesForSinglePlay {
|
||||
get {
|
||||
return ((int)(this["UndoRedoStackSize"]));
|
||||
return ((bool)(this["NoMetaFilesForSinglePlay"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool ConvertRaObsoleteClear {
|
||||
get {
|
||||
return ((bool)(this["ConvertRaObsoleteClear"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool BlockingBibs {
|
||||
get {
|
||||
return ((bool)(this["BlockingBibs"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool DisableAirUnits {
|
||||
get {
|
||||
return ((bool)(this["DisableAirUnits"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool ConvertCraters {
|
||||
get {
|
||||
return ((bool)(this["ConvertCraters"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool BoundsObstructFill {
|
||||
get {
|
||||
return ((bool)(this["BoundsObstructFill"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool FilterTheaterObjects {
|
||||
get {
|
||||
return ((bool)(this["FilterTheaterObjects"]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,6 @@
|
||||
<Setting Name="ModsToLoad" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">2844969675;Tiberian_Dawn\ConcretePavementTD</Value>
|
||||
</Setting>
|
||||
<Setting Name="NoMetaFilesForSinglePlay" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="IgnoreBibs" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="MapScale" Type="System.Double" Scope="Application">
|
||||
<Value Profile="(Default)">0.5</Value>
|
||||
</Setting>
|
||||
@ -29,12 +23,30 @@
|
||||
<Setting Name="ObjectToolItemSizeMultiplier" Type="System.Double" Scope="Application">
|
||||
<Value Profile="(Default)">0.3</Value>
|
||||
</Setting>
|
||||
<Setting Name="IgnoreRaObsoleteClear" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="UndoRedoStackSize" Type="System.Int32" Scope="Application">
|
||||
<Value Profile="(Default)">50</Value>
|
||||
</Setting>
|
||||
<Setting Name="NoMetaFilesForSinglePlay" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="ConvertRaObsoleteClear" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="BlockingBibs" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="DisableAirUnits" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="ConvertCraters" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="BoundsObstructFill" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="FilterTheaterObjects" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="ShowInviteWarning" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
|
@ -62,30 +62,50 @@ namespace MobiusEditor.RedAlert
|
||||
public static readonly BuildingType FakeCommand = new BuildingType(36, "dome", "TEXT_STRUCTURE_RA_DOMF", 0, 2, new bool[2, 2] { { true, true }, { true, true } }, "Greece", BuildingTypeFlag.Bib | BuildingTypeFlag.Fake);
|
||||
public static readonly BuildingType AVMine = new BuildingType(43, "minv", "TEXT_STRUCTURE_RA_MINV", 0, 0, new bool[1, 1] { { true } }, "Greece", BuildingTypeFlag.SingleFrame);
|
||||
public static readonly BuildingType APMine = new BuildingType(44, "minp", "TEXT_STRUCTURE_RA_MINP", 0, 0, new bool[1, 1] { { true } }, "Greece", BuildingTypeFlag.SingleFrame);
|
||||
public static readonly BuildingType V01 = new BuildingType(45, "v01", "TEXT_STRUCTURE_TITLE_CIV1", 0, 0, new bool[2, 2] { { false, false }, { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V02 = new BuildingType(46, "v02", "TEXT_STRUCTURE_TITLE_CIV2", 0, 0, new bool[2, 2] { { false, false }, { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V03 = new BuildingType(47, "v03", "TEXT_STRUCTURE_TITLE_CIV3", 0, 0, new bool[2, 2] { { false, true }, { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V04 = new BuildingType(48, "v04", "TEXT_STRUCTURE_TITLE_CIV4", 0, 0, new bool[2, 2] { { false, false }, { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V05 = new BuildingType(49, "v05", "TEXT_STRUCTURE_TITLE_CIV5", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V06 = new BuildingType(50, "v06", "TEXT_STRUCTURE_TITLE_CIV6", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V07 = new BuildingType(51, "v07", "TEXT_STRUCTURE_TITLE_CIV7", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V08 = new BuildingType(52, "v08", "TEXT_STRUCTURE_TITLE_CIV8", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V09 = new BuildingType(53, "v09", "TEXT_STRUCTURE_TITLE_CIV9", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V10 = new BuildingType(54, "v10", "TEXT_STRUCTURE_TITLE_CIV10", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V11 = new BuildingType(55, "v11", "TEXT_STRUCTURE_TITLE_CIV11", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V12 = new BuildingType(56, "v12", "TEXT_STRUCTURE_TITLE_CIV12", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V13 = new BuildingType(57, "v13", "TEXT_STRUCTURE_TITLE_CIV12", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V14 = new BuildingType(58, "v14", "TEXT_STRUCTURE_TITLE_CIV13", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V15 = new BuildingType(59, "v15", "TEXT_STRUCTURE_TITLE_CIV14", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V16 = new BuildingType(60, "v16", "TEXT_STRUCTURE_TITLE_CIV15", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V17 = new BuildingType(61, "v17", "TEXT_STRUCTURE_TITLE_CIV16", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V18 = new BuildingType(62, "v18", "TEXT_STRUCTURE_TITLE_CIV17", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType V19 = new BuildingType(63, "v19", "Oil Pump", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly BuildingType Barrel = new BuildingType(82, "barl", "TEXT_STRUCTURE_RA_BARL", 0, 0, new bool[1, 1] { { true } }, "Neutral");
|
||||
public static readonly BuildingType Barrel3 = new BuildingType(83, "brl3", "TEXT_STRUCTURE_RA_BRL3", 0, 0, new bool[1, 1] { { true } }, "Neutral");
|
||||
public static readonly BuildingType V01 = new BuildingType(45, "v01", "TEXT_STRUCTURE_TITLE_CIV1", 0, 0, new bool[2, 2] { { false, false }, { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V02 = new BuildingType(46, "v02", "TEXT_STRUCTURE_TITLE_CIV2", 0, 0, new bool[2, 2] { { false, false }, { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V03 = new BuildingType(47, "v03", "TEXT_STRUCTURE_TITLE_CIV3", 0, 0, new bool[2, 2] { { false, true }, { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V04 = new BuildingType(48, "v04", "TEXT_STRUCTURE_TITLE_CIV4", 0, 0, new bool[2, 2] { { false, false }, { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V05 = new BuildingType(49, "v05", "TEXT_STRUCTURE_TITLE_CIV5", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V06 = new BuildingType(50, "v06", "TEXT_STRUCTURE_TITLE_CIV6", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V07 = new BuildingType(51, "v07", "TEXT_STRUCTURE_TITLE_CIV7", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V08 = new BuildingType(52, "v08", "TEXT_STRUCTURE_TITLE_CIV8", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V09 = new BuildingType(53, "v09", "TEXT_STRUCTURE_TITLE_CIV9", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V10 = new BuildingType(54, "v10", "TEXT_STRUCTURE_TITLE_CIV10", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V11 = new BuildingType(55, "v11", "TEXT_STRUCTURE_TITLE_CIV11", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V12 = new BuildingType(56, "v12", "TEXT_STRUCTURE_TITLE_CIV12", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V13 = new BuildingType(57, "v13", "TEXT_STRUCTURE_TITLE_CIV12", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V14 = new BuildingType(58, "v14", "TEXT_STRUCTURE_TITLE_CIV13", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V15 = new BuildingType(59, "v15", "TEXT_STRUCTURE_TITLE_CIV14", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V16 = new BuildingType(60, "v16", "TEXT_STRUCTURE_TITLE_CIV15", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V17 = new BuildingType(61, "v17", "TEXT_STRUCTURE_TITLE_CIV16", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V18 = new BuildingType(62, "v18", "TEXT_STRUCTURE_TITLE_CIV17", 0, 0, new bool[1, 1] { { true } }, "Neutral", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V19 = new BuildingType(63, "v19", "Oil Pump", 0, 0, new bool[1, 1] { { true } }, "Neutral", BuildingTypeFlag.NoRemap);
|
||||
// Desert civilian buildings. Will never show up unless the option to filter theater-illegals is disabled.
|
||||
public static readonly BuildingType V20 = new BuildingType(64, "v20", "TEXT_STRUCTURE_TITLE_CIV18", 0, 0, new bool[2, 2] { { false, false }, { true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V21 = new BuildingType(65, "v21", "TEXT_STRUCTURE_TITLE_CIV19", 0, 0, new bool[2, 2] { { true, true }, { false, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V22 = new BuildingType(66, "v22", "TEXT_STRUCTURE_TITLE_CIV20", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V23 = new BuildingType(67, "v23", "TEXT_STRUCTURE_TITLE_CIV21", 0, 0, new bool[1, 1] { { true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V24 = new BuildingType(68, "v24", "TEXT_STRUCTURE_TITLE_CIV22", 0, 0, new bool[2, 2] { { false, false }, { true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V25 = new BuildingType(69, "v25", "TEXT_STRUCTURE_TITLE_CIV1", 0, 0, new bool[2, 2] { { false, true }, { true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V26 = new BuildingType(70, "v26", "TEXT_STRUCTURE_TITLE_CIV23", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V27 = new BuildingType(71, "v27", "TEXT_STRUCTURE_TITLE_CIV24", 0, 0, new bool[1, 1] { { true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V28 = new BuildingType(72, "v28", "TEXT_STRUCTURE_TITLE_CIV25", 0, 0, new bool[1, 1] { { true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V29 = new BuildingType(73, "v29", "TEXT_STRUCTURE_TITLE_CIV26", 0, 0, new bool[1, 1] { { true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V30 = new BuildingType(74, "v30", "TEXT_STRUCTURE_TITLE_CIV27", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V31 = new BuildingType(75, "v31", "TEXT_STRUCTURE_TITLE_CIV28", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V32 = new BuildingType(76, "v32", "TEXT_STRUCTURE_TITLE_CIV29", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V33 = new BuildingType(77, "v33", "TEXT_STRUCTURE_TITLE_CIV30", 0, 0, new bool[1, 2] { { true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V34 = new BuildingType(78, "v34", "TEXT_STRUCTURE_TITLE_CIV31", 0, 0, new bool[1, 1] { { true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V35 = new BuildingType(79, "v35", "TEXT_STRUCTURE_TITLE_CIV32", 0, 0, new bool[1, 1] { { true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V36 = new BuildingType(80, "v36", "TEXT_STRUCTURE_TITLE_CIV33", 0, 0, new bool[1, 1] { { true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType V37 = new BuildingType(81, "v37", "TEXT_STRUCTURE_TITLE_CIV34", 0, 0, new bool[2, 4] { { false, true, true, true }, { false, true, true, true } }, "Neutral", new TheaterType[0], BuildingTypeFlag.NoRemap);
|
||||
|
||||
public static readonly BuildingType Barrel = new BuildingType(82, "barl", "TEXT_STRUCTURE_RA_BARL", 0, 0, new bool[1, 1] { { true } }, "Neutral", BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType Barrel3 = new BuildingType(83, "brl3", "TEXT_STRUCTURE_RA_BRL3", 0, 0, new bool[1, 1] { { true } }, "Neutral", BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType Queen = new BuildingType(84, "quee", "TEXT_STRUCTURE_RA_QUEE", 0, 0, new bool[1, 2] { { true, true } }, "Special");
|
||||
public static readonly BuildingType Larva1 = new BuildingType(85, "lar1", "TEXT_STRUCTURE_RA_LAR1", 0, 0, new bool[1, 1] { { true } }, "Special");
|
||||
public static readonly BuildingType Larva2 = new BuildingType(86, "lar2", "TEXT_STRUCTURE_RA_LAR2", 0, 0, new bool[1, 1] { { true } }, "Special");
|
||||
public static readonly BuildingType Larva1 = new BuildingType(85, "lar1", "TEXT_STRUCTURE_RA_LAR1", 0, 0, new bool[1, 1] { { true } }, "Special", BuildingTypeFlag.NoRemap);
|
||||
public static readonly BuildingType Larva2 = new BuildingType(86, "lar2", "TEXT_STRUCTURE_RA_LAR2", 0, 0, new bool[1, 1] { { true } }, "Special", BuildingTypeFlag.NoRemap);
|
||||
|
||||
private static readonly BuildingType[] Types;
|
||||
|
||||
|
@ -293,29 +293,30 @@ namespace MobiusEditor.RedAlert
|
||||
{
|
||||
return;
|
||||
}
|
||||
ini.Sections.Extract("Digest");
|
||||
ini.Sections.Extract("Basic");
|
||||
ini.Sections.Extract("Aftermath");
|
||||
ini.Sections.Extract("Map");
|
||||
ini.Sections.Extract("Steam");
|
||||
ini.Sections.Extract("TeamTypes");
|
||||
ini.Sections.Extract("Trigs");
|
||||
ini.Sections.Extract("MapPack");
|
||||
ini.Sections.Extract("Terrain");
|
||||
ini.Sections.Extract("OverlayPack");
|
||||
ini.Sections.Extract("Smudge");
|
||||
ini.Sections.Extract("Units");
|
||||
ini.Sections.Extract("Aircraft");
|
||||
ini.Sections.Extract("Ships");
|
||||
ini.Sections.Extract("Infantry");
|
||||
ini.Sections.Extract("Structures");
|
||||
ini.Sections.Extract("Base");
|
||||
ini.Sections.Extract("Waypoints");
|
||||
ini.Sections.Extract("CellTriggers");
|
||||
ini.Sections.Extract("Briefing");
|
||||
// Remove any sections known and handled / disallowed by the editor.
|
||||
ini.Sections.Remove("Digest");
|
||||
ini.Sections.Remove("Basic");
|
||||
ini.Sections.Remove("Aftermath");
|
||||
ini.Sections.Remove("Map");
|
||||
ini.Sections.Remove("Steam");
|
||||
ini.Sections.Remove("TeamTypes");
|
||||
ini.Sections.Remove("Trigs");
|
||||
ini.Sections.Remove("MapPack");
|
||||
ini.Sections.Remove("Terrain");
|
||||
ini.Sections.Remove("OverlayPack");
|
||||
ini.Sections.Remove("Smudge");
|
||||
ini.Sections.Remove("Units");
|
||||
ini.Sections.Remove("Aircraft");
|
||||
ini.Sections.Remove("Ships");
|
||||
ini.Sections.Remove("Infantry");
|
||||
ini.Sections.Remove("Structures");
|
||||
ini.Sections.Remove("Base");
|
||||
ini.Sections.Remove("Waypoints");
|
||||
ini.Sections.Remove("CellTriggers");
|
||||
ini.Sections.Remove("Briefing");
|
||||
foreach (var house in Map.Houses)
|
||||
{
|
||||
ini.Sections.Extract(house.Type.Name);
|
||||
ini.Sections.Remove(house.Type.Name);
|
||||
}
|
||||
extraSections = ini.Sections.Count == 0 ? null : ini.Sections;
|
||||
UpdateBuildingRules(ini, this.Map);
|
||||
@ -337,8 +338,6 @@ namespace MobiusEditor.RedAlert
|
||||
this.feedBackHandler = feedBackHandler;
|
||||
var playerWaypoints = Enumerable.Range(0, multiStartPoints).Select(i => new Waypoint(string.Format("P{0}", i), WaypointFlag.PlayerStart));
|
||||
var generalWaypoints = Enumerable.Range(multiStartPoints, 98 - multiStartPoints).Select(i => new Waypoint(i.ToString()));
|
||||
//var playerWaypoints = Enumerable.Range(0, 8).Select(i => new Waypoint(string.Format("P{0}", i), WaypointFlag.PlayerStart));
|
||||
//var generalWaypoints = Enumerable.Range(8, 90).Select(i => new Waypoint(i.ToString()));
|
||||
var specialWaypoints = new Waypoint[] { new Waypoint("Home", WaypointFlag.Home), new Waypoint("Reinf.", WaypointFlag.Reinforce), new Waypoint("Special", WaypointFlag.Special) };
|
||||
var waypoints = playerWaypoints.Concat(generalWaypoints).Concat(specialWaypoints);
|
||||
var movies = new List<string>(movieTypesRa);
|
||||
@ -384,10 +383,10 @@ namespace MobiusEditor.RedAlert
|
||||
|
||||
Map = new Map(basicSection, null, Constants.MaxSize, typeof(House),
|
||||
houseTypes, TheaterTypes.GetTypes(), TemplateTypes.GetTypes(),
|
||||
TerrainTypes.GetTypes(), OverlayTypes.GetTypes(), SmudgeTypes.GetTypes(),
|
||||
TerrainTypes.GetTypes(), OverlayTypes.GetTypes(), SmudgeTypes.GetTypes(Globals.ConvertCraters),
|
||||
EventTypes.GetTypes(), cellEventTypes, unitEventTypes, structureEventTypes, terrainEventTypes,
|
||||
ActionTypes.GetTypes(), cellActionTypes, unitActionTypes, structureActionTypes, terrainActionTypes,
|
||||
MissionTypes.GetTypes(), DirectionTypes.GetTypes(), InfantryTypes.GetTypes(), UnitTypes.GetTypes(true),
|
||||
MissionTypes.GetTypes(), DirectionTypes.GetTypes(), InfantryTypes.GetTypes(), UnitTypes.GetTypes(Globals.DisableAirUnits),
|
||||
BuildingTypes.GetTypes(), TeamMissionTypes.GetTypes(), fullTechnoTypes, waypoints, movieTypes, themeTypes)
|
||||
{
|
||||
TiberiumOrGoldValue = 35,
|
||||
@ -750,7 +749,7 @@ namespace MobiusEditor.RedAlert
|
||||
{
|
||||
if (typeValue == 255)
|
||||
{
|
||||
if (!Globals.IgnoreRaObsoleteClear)
|
||||
if (Globals.ConvertRaObsoleteClear)
|
||||
{
|
||||
if (!clearedOldClear)
|
||||
{
|
||||
@ -766,7 +765,7 @@ namespace MobiusEditor.RedAlert
|
||||
templateType = null;
|
||||
}
|
||||
}
|
||||
if (!Globals.IgnoreRaObsoleteClear)
|
||||
if (Globals.ConvertRaObsoleteClear)
|
||||
{
|
||||
if (typeValue == 255 && !clearedOldClear)
|
||||
{
|
||||
@ -856,7 +855,7 @@ namespace MobiusEditor.RedAlert
|
||||
var terrainType = Map.TerrainTypes.Where(t => t.Equals(name)).FirstOrDefault();
|
||||
if (terrainType != null)
|
||||
{
|
||||
if (terrainType.Theaters != null && !terrainType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && terrainType.Theaters != null && !terrainType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Terrain '{0}' is not available in the set theater; skipping.", terrainType.Name));
|
||||
continue;
|
||||
@ -932,7 +931,7 @@ namespace MobiusEditor.RedAlert
|
||||
var overlayType = Map.OverlayTypes.Where(t => t.Equals(overlayId)).FirstOrDefault();
|
||||
if (overlayType != null)
|
||||
{
|
||||
if (overlayType.Theaters != null && !overlayType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && overlayType.Theaters != null && !overlayType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Overlay '{0}' is not available in the set theater; skipping.", overlayType.Name));
|
||||
continue;
|
||||
@ -948,8 +947,6 @@ namespace MobiusEditor.RedAlert
|
||||
}
|
||||
}
|
||||
var smudgeSection = ini.Sections.Extract("Smudge");
|
||||
// Craters other than cr1 don't work right in the game. Replace them by stage-0 cr1.
|
||||
Regex craterRegex = new Regex("^CR[2-6]$", RegexOptions.IgnoreCase);
|
||||
if (smudgeSection != null)
|
||||
{
|
||||
foreach (var (Key, Value) in smudgeSection)
|
||||
@ -963,11 +960,12 @@ namespace MobiusEditor.RedAlert
|
||||
var tokens = Value.Split(',');
|
||||
if (tokens.Length == 3)
|
||||
{
|
||||
bool badCrater = craterRegex.IsMatch(tokens[0]);
|
||||
// Craters other than cr1 don't work right in the game. Replace them by stage-0 cr1.
|
||||
bool badCrater = Globals.ConvertCraters && SmudgeTypes.GetBadCraterRegex().IsMatch(tokens[0]);
|
||||
var smudgeType = badCrater ? SmudgeTypes.Crater1 : Map.SmudgeTypes.Where(t => t.Equals(tokens[0]) && !t.IsAutoBib).FirstOrDefault();
|
||||
if (smudgeType != null)
|
||||
{
|
||||
if (smudgeType.Theaters != null && !smudgeType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && smudgeType.Theaters != null && !smudgeType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Smudge '{0}' is not available in the set theater; skipping.", smudgeType.Name));
|
||||
continue;
|
||||
@ -1113,11 +1111,10 @@ namespace MobiusEditor.RedAlert
|
||||
}
|
||||
}
|
||||
}
|
||||
// Classic game does not support this, so I'm leaving this out. It's buggy anyway.
|
||||
// Extracting it so it doesn't end up with the "extra sections"
|
||||
// Classic game does not support this, so I'm leaving this out by default.
|
||||
// It is always extracted, so it doesn't end up with the "extra sections"
|
||||
var aircraftSection = ini.Sections.Extract("Aircraft");
|
||||
/*/
|
||||
if (aircraftSection != null)
|
||||
if (!Globals.DisableAirUnits && aircraftSection != null)
|
||||
{
|
||||
foreach (var (Key, Value) in aircraftSection)
|
||||
{
|
||||
@ -1199,7 +1196,6 @@ namespace MobiusEditor.RedAlert
|
||||
}
|
||||
}
|
||||
}
|
||||
//*/
|
||||
var shipsSection = ini.Sections.Extract("Ships");
|
||||
if (shipsSection != null)
|
||||
{
|
||||
@ -1435,7 +1431,7 @@ namespace MobiusEditor.RedAlert
|
||||
errors.Add(string.Format("Structure '{0}' references unknown structure.", tokens[1]));
|
||||
continue;
|
||||
}
|
||||
if (buildingType.Theaters != null && !buildingType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && buildingType.Theaters != null && !buildingType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Structure '{0}' is not available in the set theater; skipping.", buildingType.Name));
|
||||
continue;
|
||||
@ -1547,7 +1543,7 @@ namespace MobiusEditor.RedAlert
|
||||
errors.Add(string.Format("Base rebuild entry {0} references unknown structure '{1}'.", priority, tokens[0]));
|
||||
continue;
|
||||
}
|
||||
if (buildingType.Theaters != null && !buildingType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && buildingType.Theaters != null && !buildingType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Base rebuild entry {0} references structure '{1}' which is not available in the set theater; skipping.", priority, buildingType.Name));
|
||||
continue;
|
||||
@ -2030,7 +2026,7 @@ namespace MobiusEditor.RedAlert
|
||||
infantry.Strength,
|
||||
cell,
|
||||
i,
|
||||
infantry.Mission,
|
||||
String.IsNullOrEmpty(infantry.Mission) ? "Guard" : infantry.Mission,
|
||||
infantry.Direction.ID,
|
||||
infantry.Trigger
|
||||
);
|
||||
@ -2085,30 +2081,31 @@ namespace MobiusEditor.RedAlert
|
||||
unit.Strength,
|
||||
cell,
|
||||
unit.Direction.ID,
|
||||
unit.Mission,
|
||||
String.IsNullOrEmpty(unit.Mission) ? "Guard" : unit.Mission,
|
||||
unit.Trigger
|
||||
);
|
||||
}
|
||||
// Classic game does not support this, so I'm leaving this out.
|
||||
/*/
|
||||
var aircraftSection = ini.Sections.Add("AIRCRAFT");
|
||||
var aircraftIndex = 0;
|
||||
foreach (var (location, aircraft) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsAircraft))
|
||||
// Classic game does not support this, so it's disabled by default.
|
||||
if (!Globals.DisableAirUnits)
|
||||
{
|
||||
var key = aircraftIndex.ToString("D3");
|
||||
aircraftIndex++;
|
||||
var aircraftSection = ini.Sections.Add("AIRCRAFT");
|
||||
var aircraftIndex = 0;
|
||||
foreach (var (location, aircraft) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsAircraft))
|
||||
{
|
||||
var key = aircraftIndex.ToString("D3");
|
||||
aircraftIndex++;
|
||||
|
||||
Map.Metrics.GetCell(location, out int cell);
|
||||
aircraftSection[key] = string.Format("{0},{1},{2},{3},{4},{5}",
|
||||
aircraft.House.Name,
|
||||
aircraft.Type.Name,
|
||||
aircraft.Strength,
|
||||
cell,
|
||||
aircraft.Direction.ID,
|
||||
aircraft.Mission
|
||||
);
|
||||
Map.Metrics.GetCell(location, out int cell);
|
||||
aircraftSection[key] = string.Format("{0},{1},{2},{3},{4},{5}",
|
||||
aircraft.House.Name,
|
||||
aircraft.Type.Name,
|
||||
aircraft.Strength,
|
||||
cell,
|
||||
aircraft.Direction.ID,
|
||||
String.IsNullOrEmpty(aircraft.Mission) ? "Guard" : aircraft.Mission
|
||||
);
|
||||
}
|
||||
}
|
||||
//*/
|
||||
var shipsSection = ini.Sections.Add("SHIPS");
|
||||
var shipsIndex = 0;
|
||||
foreach (var (location, ship) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsVessel))
|
||||
@ -2123,7 +2120,7 @@ namespace MobiusEditor.RedAlert
|
||||
ship.Strength,
|
||||
cell,
|
||||
ship.Direction.ID,
|
||||
ship.Mission,
|
||||
String.IsNullOrEmpty(ship.Mission) ? "Guard" : ship.Mission,
|
||||
ship.Trigger
|
||||
);
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ namespace MobiusEditor.RedAlert
|
||||
public static readonly OverlayType Gems2 = new OverlayType(10, "gem02", "Gems", new [] { TheaterTypes.Temperate, TheaterTypes.Snow }, OverlayTypeFlag.Gems, 2);
|
||||
public static readonly OverlayType Gems3 = new OverlayType(11, "gem03", "Gems", new [] { TheaterTypes.Temperate, TheaterTypes.Snow }, OverlayTypeFlag.Gems, 2);
|
||||
public static readonly OverlayType Gems4 = new OverlayType(12, "gem04", "Gems", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, OverlayTypeFlag.Gems, 2);
|
||||
public static readonly OverlayType V12 = new OverlayType(13, "v12", "TEXT_STRUCTURE_RA_CIVILIAN", new [] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly OverlayType V13 = new OverlayType(14, "v13", "TEXT_STRUCTURE_RA_CIVILIAN", new [] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly OverlayType V12 = new OverlayType(13, "v12", "TEXT_STRUCTURE_TITLE_CIV12", new [] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly OverlayType V13 = new OverlayType(14, "v13", "TEXT_STRUCTURE_TITLE_CIV12", new [] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly OverlayType V14 = new OverlayType(15, "v14", "TEXT_STRUCTURE_TITLE_CIV13", new [] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly OverlayType V15 = new OverlayType(16, "v15", "TEXT_STRUCTURE_TITLE_CIV14", new [] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
public static readonly OverlayType V16 = new OverlayType(17, "v16", "TEXT_STRUCTURE_TITLE_CIV15", new [] { TheaterTypes.Temperate, TheaterTypes.Snow });
|
||||
|
@ -17,25 +17,26 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MobiusEditor.RedAlert
|
||||
{
|
||||
public static class SmudgeTypes
|
||||
{
|
||||
public static readonly SmudgeType Crater1 = new SmudgeType(0, "cr1", 5);
|
||||
// Seems RA has issues reading these from missions.
|
||||
//public static readonly SmudgeType Crater2 = new SmudgeType(1, "cr2", 5);
|
||||
//public static readonly SmudgeType Crater3 = new SmudgeType(2, "cr3", 5);
|
||||
//public static readonly SmudgeType Crater4 = new SmudgeType(3, "cr4", 5);
|
||||
//public static readonly SmudgeType Crater5 = new SmudgeType(4, "cr5", 5);
|
||||
//public static readonly SmudgeType Crater6 = new SmudgeType(5, "cr6", 5);
|
||||
// Seems the game has issues reading these from missions.
|
||||
public static readonly SmudgeType Crater2 = new SmudgeType(1, "cr2", 5);
|
||||
public static readonly SmudgeType Crater3 = new SmudgeType(2, "cr3", 5);
|
||||
public static readonly SmudgeType Crater4 = new SmudgeType(3, "cr4", 5);
|
||||
public static readonly SmudgeType Crater5 = new SmudgeType(4, "cr5", 5);
|
||||
public static readonly SmudgeType Crater6 = new SmudgeType(5, "cr6", 5);
|
||||
public static readonly SmudgeType Scorch1 = new SmudgeType(6, "sc1");
|
||||
public static readonly SmudgeType Scorch2 = new SmudgeType(7, "sc2");
|
||||
public static readonly SmudgeType Scorch3 = new SmudgeType(8, "sc3");
|
||||
public static readonly SmudgeType Scorch4 = new SmudgeType(9, "sc4");
|
||||
public static readonly SmudgeType Scorch5 = new SmudgeType(10, "sc5");
|
||||
public static readonly SmudgeType Scorch6 = new SmudgeType(11, "sc6");
|
||||
// placeable versions of the bibs. Experimental for now - UI doesn't seem able to handle their full size like the game does.
|
||||
// placeable versions of the bibs.
|
||||
public static readonly SmudgeType Bib1Pl = new SmudgeType(12, "bib1", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new Size(4, 2));
|
||||
public static readonly SmudgeType Bib2Pl = new SmudgeType(13, "bib2", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new Size(3, 2));
|
||||
public static readonly SmudgeType Bib3Pl = new SmudgeType(14, "bib3", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new Size(2, 2));
|
||||
@ -45,18 +46,29 @@ namespace MobiusEditor.RedAlert
|
||||
public static readonly SmudgeType Bib3 = new SmudgeType(17, "bib3", new[] { TheaterTypes.Temperate, TheaterTypes.Snow }, new Size(2, 2), SmudgeTypeFlag.Bib3);
|
||||
|
||||
private static SmudgeType[] Types;
|
||||
private static Regex BadCraters;
|
||||
|
||||
static SmudgeTypes()
|
||||
{
|
||||
BadCraters = new Regex("^CR[2-6]$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
Types =
|
||||
(from field in typeof(SmudgeTypes).GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||
where field.IsInitOnly && typeof(SmudgeType).IsAssignableFrom(field.FieldType)
|
||||
select field.GetValue(null) as SmudgeType).ToArray();
|
||||
}
|
||||
|
||||
public static IEnumerable<SmudgeType> GetTypes()
|
||||
public static Regex GetBadCraterRegex()
|
||||
{
|
||||
return Types;
|
||||
return BadCraters;
|
||||
}
|
||||
|
||||
public static IEnumerable<SmudgeType> GetTypes(bool singleCrater)
|
||||
{
|
||||
if (!singleCrater)
|
||||
{
|
||||
return Types;
|
||||
}
|
||||
return Types.Where(sm => !BadCraters.IsMatch(sm.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,10 +70,10 @@ namespace MobiusEditor.RedAlert
|
||||
select field.GetValue(null) as UnitType).ToArray();
|
||||
}
|
||||
|
||||
public static IEnumerable<UnitType> GetTypes(bool placeableOnly)
|
||||
public static IEnumerable<UnitType> GetTypes(bool withoutAircraft)
|
||||
{
|
||||
// only return placeable units, not aircraft.
|
||||
if (placeableOnly)
|
||||
if (withoutAircraft)
|
||||
return Types.Where(t => !t.IsAircraft);
|
||||
return Types;
|
||||
}
|
||||
|
@ -214,36 +214,7 @@ namespace MobiusEditor.Render
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string tileName = terrain.Type.GraphicsSource;
|
||||
if (Globals.TheTilesetManager.GetTileData(map.Theater.Tilesets, tileName, terrain.Icon, out Tile tile))
|
||||
{
|
||||
var tint = terrain.Tint;
|
||||
var imageAttributes = new ImageAttributes();
|
||||
if (tint != Color.White)
|
||||
{
|
||||
var colorMatrix = new ColorMatrix(new float[][]
|
||||
{
|
||||
new float[] {tint.R / 255.0f, 0, 0, 0, 0},
|
||||
new float[] {0, tint.G / 255.0f, 0, 0, 0},
|
||||
new float[] {0, 0, tint.B / 255.0f, 0, 0},
|
||||
new float[] {0, 0, 0, tint.A / 255.0f, 0},
|
||||
new float[] {0, 0, 0, 0, 1},
|
||||
}
|
||||
);
|
||||
imageAttributes.SetColorMatrix(colorMatrix);
|
||||
}
|
||||
var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);
|
||||
var maxSize = new Size(terrain.Type.Size.Width * tileSize.Width, terrain.Type.Size.Height * tileSize.Height);
|
||||
Rectangle paintBounds = RenderBounds(tile.Image.Size, terrain.Type.Size, tileScale);
|
||||
paintBounds.X += location.X;
|
||||
paintBounds.Y += location.Y;
|
||||
var terrainBounds = new Rectangle(location, maxSize);
|
||||
overlappingRenderList.Add((terrainBounds, g => g.DrawImage(tile.Image, paintBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Print(string.Format("Terrain {0} ({1}) not found", tileName, terrain.Icon));
|
||||
}
|
||||
overlappingRenderList.Add(Render(gameType, map.Theater, topLeft, tileSize, tileScale, terrain));
|
||||
}
|
||||
}
|
||||
if ((layers & MapLayerFlag.Buildings) != MapLayerFlag.None)
|
||||
@ -391,6 +362,42 @@ namespace MobiusEditor.Render
|
||||
}
|
||||
}
|
||||
|
||||
public static (Rectangle, Action<Graphics>) Render(GameType gameType, TheaterType theater, Point topLeft, Size tileSize, double tileScale, Terrain terrain)
|
||||
{
|
||||
string tileName = terrain.Type.GraphicsSource;
|
||||
if (!Globals.TheTilesetManager.GetTileData(theater.Tilesets, tileName, terrain.Icon, out Tile tile))
|
||||
{
|
||||
Debug.Print(string.Format("Terrain {0} ({1}) not found", tileName, terrain.Icon));
|
||||
return (Rectangle.Empty, (g) => { });
|
||||
}
|
||||
var tint = terrain.Tint;
|
||||
var imageAttributes = new ImageAttributes();
|
||||
if (tint != Color.White)
|
||||
{
|
||||
var colorMatrix = new ColorMatrix(new float[][]
|
||||
{
|
||||
new float[] {tint.R / 255.0f, 0, 0, 0, 0},
|
||||
new float[] {0, tint.G / 255.0f, 0, 0, 0},
|
||||
new float[] {0, 0, tint.B / 255.0f, 0, 0},
|
||||
new float[] {0, 0, 0, tint.A / 255.0f, 0},
|
||||
new float[] {0, 0, 0, 0, 1},
|
||||
}
|
||||
);
|
||||
imageAttributes.SetColorMatrix(colorMatrix);
|
||||
}
|
||||
var location = new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height);
|
||||
var maxSize = new Size(terrain.Type.Size.Width * tileSize.Width, terrain.Type.Size.Height * tileSize.Height);
|
||||
Rectangle paintBounds = RenderBounds(tile.Image.Size, terrain.Type.Size, tileScale);
|
||||
paintBounds.X += location.X;
|
||||
paintBounds.Y += location.Y;
|
||||
var terrainBounds = new Rectangle(location, maxSize);
|
||||
void render(Graphics g)
|
||||
{
|
||||
g.DrawImage(tile.Image, paintBounds, 0, 0, tile.Image.Width, tile.Image.Height, GraphicsUnit.Pixel, imageAttributes);
|
||||
}
|
||||
return (terrainBounds, render);
|
||||
}
|
||||
|
||||
public static (Rectangle, Action<Graphics>) Render(GameType gameType, TheaterType theater, Point topLeft, Size tileSize, double tileScale, Building building)
|
||||
{
|
||||
var tint = building.Tint;
|
||||
@ -426,7 +433,8 @@ namespace MobiusEditor.Render
|
||||
icon = damageIcon;
|
||||
}
|
||||
}
|
||||
if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, building.Type.Tilename, icon, Globals.TheTeamColorManager[building.House.BuildingTeamColor], out Tile tile))
|
||||
TeamColor tc = building.Type.CanRemap ? Globals.TheTeamColorManager[building.House.BuildingTeamColor] : null;
|
||||
if (Globals.TheTilesetManager.GetTeamColorTileData(theater.Tilesets, building.Type.Tilename, icon, tc, out Tile tile))
|
||||
{
|
||||
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);
|
||||
|
@ -133,25 +133,26 @@ namespace MobiusEditor.TiberianDawn
|
||||
{
|
||||
return;
|
||||
}
|
||||
ini.Sections.Extract("Basic");
|
||||
ini.Sections.Extract("Map");
|
||||
ini.Sections.Extract("Briefing");
|
||||
ini.Sections.Extract("Steam");
|
||||
ini.Sections.Extract("TeamTypes");
|
||||
ini.Sections.Extract("Triggers");
|
||||
ini.Sections.Extract("Terrain");
|
||||
ini.Sections.Extract("Overlay");
|
||||
ini.Sections.Extract("Smudge");
|
||||
ini.Sections.Extract("Infantry");
|
||||
ini.Sections.Extract("Units");
|
||||
ini.Sections.Extract("Aircraft");
|
||||
ini.Sections.Extract("Structures");
|
||||
ini.Sections.Extract("Base");
|
||||
ini.Sections.Extract("Waypoints");
|
||||
ini.Sections.Extract("CellTriggers");
|
||||
// Remove any sections known and handled / disallowed by the editor.
|
||||
ini.Sections.Remove("Basic");
|
||||
ini.Sections.Remove("Map");
|
||||
ini.Sections.Remove("Briefing");
|
||||
ini.Sections.Remove("Steam");
|
||||
ini.Sections.Remove("TeamTypes");
|
||||
ini.Sections.Remove("Triggers");
|
||||
ini.Sections.Remove("Terrain");
|
||||
ini.Sections.Remove("Overlay");
|
||||
ini.Sections.Remove("Smudge");
|
||||
ini.Sections.Remove("Infantry");
|
||||
ini.Sections.Remove("Units");
|
||||
ini.Sections.Remove("Aircraft");
|
||||
ini.Sections.Remove("Structures");
|
||||
ini.Sections.Remove("Base");
|
||||
ini.Sections.Remove("Waypoints");
|
||||
ini.Sections.Remove("CellTriggers");
|
||||
foreach (var house in Map.Houses)
|
||||
{
|
||||
ini.Sections.Extract(house.Type.Name);
|
||||
ini.Sections.Remove(house.Type.Name);
|
||||
}
|
||||
extraSections = ini.Sections.Count == 0 ? null : ini.Sections;
|
||||
}
|
||||
@ -224,10 +225,10 @@ namespace MobiusEditor.TiberianDawn
|
||||
|
||||
Map = new Map(basicSection, null, Constants.MaxSize, typeof(House),
|
||||
houseTypes, TheaterTypes.GetTypes(), TemplateTypes.GetTypes(),
|
||||
TerrainTypes.GetTypes(), OverlayTypes.GetTypes(), SmudgeTypes.GetTypes(),
|
||||
TerrainTypes.GetTypes(), OverlayTypes.GetTypes(), SmudgeTypes.GetTypes(Globals.ConvertCraters),
|
||||
EventTypes.GetTypes(), cellEventTypes, unitEventTypes, structureEventTypes, terrainEventTypes,
|
||||
ActionTypes.GetTypes(), cellActionTypes, unitActionTypes, structureActionTypes, terrainActionTypes,
|
||||
MissionTypes.GetTypes(), DirectionTypes.GetTypes(), InfantryTypes.GetTypes(), UnitTypes.GetTypes(true),
|
||||
MissionTypes.GetTypes(), DirectionTypes.GetTypes(), InfantryTypes.GetTypes(), UnitTypes.GetTypes(Globals.DisableAirUnits),
|
||||
BuildingTypes.GetTypes(), TeamMissionTypes.GetTypes(), fullTechnoTypes, waypoints, movieTypes, themeTypes)
|
||||
{
|
||||
TiberiumOrGoldValue = 25
|
||||
@ -616,7 +617,7 @@ namespace MobiusEditor.TiberianDawn
|
||||
var terrainType = Map.TerrainTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault();
|
||||
if (terrainType != null)
|
||||
{
|
||||
if (terrainType.Theaters != null && !terrainType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && terrainType.Theaters != null && !terrainType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Terrain '{0}' is not available in the set theater; skipping.", terrainType.Name));
|
||||
continue;
|
||||
@ -695,7 +696,7 @@ namespace MobiusEditor.TiberianDawn
|
||||
var overlayType = Map.OverlayTypes.Where(t => t.Equals(Value)).FirstOrDefault();
|
||||
if (overlayType != null)
|
||||
{
|
||||
if (overlayType.Theaters != null && !overlayType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && overlayType.Theaters != null && !overlayType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Overlay '{0}' is not available in the set theater; skipping.", overlayType.Name));
|
||||
continue;
|
||||
@ -709,8 +710,6 @@ namespace MobiusEditor.TiberianDawn
|
||||
}
|
||||
}
|
||||
var smudgeSection = ini.Sections.Extract("Smudge");
|
||||
// Craters other than cr1 don't work right in the game. Replace them by stage-0 cr1.
|
||||
Regex craterRegex = new Regex("^CR[2-6]$", RegexOptions.IgnoreCase);
|
||||
if (smudgeSection != null)
|
||||
{
|
||||
foreach (var (Key, Value) in smudgeSection)
|
||||
@ -724,11 +723,12 @@ namespace MobiusEditor.TiberianDawn
|
||||
var tokens = Value.Split(',');
|
||||
if (tokens.Length == 3)
|
||||
{
|
||||
bool badCrater = craterRegex.IsMatch(tokens[0]);
|
||||
// Craters other than cr1 don't work right in the game. Replace them by stage-0 cr1.
|
||||
bool badCrater = Globals.ConvertCraters && SmudgeTypes.GetBadCraterRegex().IsMatch(tokens[0]);
|
||||
var smudgeType = badCrater ? SmudgeTypes.Crater1 : Map.SmudgeTypes.Where(t => t.Equals(tokens[0]) && !t.IsAutoBib).FirstOrDefault();
|
||||
if (smudgeType != null)
|
||||
{
|
||||
if (smudgeType.Theaters != null && !smudgeType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && smudgeType.Theaters != null && !smudgeType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Smudge '{0}' is not available in the set theater; skipping.", smudgeType.Name));
|
||||
continue;
|
||||
@ -993,11 +993,10 @@ namespace MobiusEditor.TiberianDawn
|
||||
}
|
||||
}
|
||||
}
|
||||
// Classic game does not support this, so I'm leaving this out. It's buggy anyway.
|
||||
// Extracting it so it doesn't end up with the "extra sections"
|
||||
// Classic game does not support this, so I'm leaving this out by default.
|
||||
// It is always extracted, so it doesn't end up with the "extra sections"
|
||||
var aircraftSection = ini.Sections.Extract("Aircraft");
|
||||
/*/
|
||||
if (aircraftSection != null)
|
||||
if (!Globals.DisableAirUnits && aircraftSection != null)
|
||||
{
|
||||
foreach (var (Key, Value) in aircraftSection)
|
||||
{
|
||||
@ -1079,7 +1078,6 @@ namespace MobiusEditor.TiberianDawn
|
||||
}
|
||||
}
|
||||
}
|
||||
//*/
|
||||
var structuresSection = ini.Sections.Extract("Structures");
|
||||
if (structuresSection != null)
|
||||
{
|
||||
@ -1094,7 +1092,7 @@ namespace MobiusEditor.TiberianDawn
|
||||
errors.Add(string.Format("Structure '{0}' references unknown structure.", tokens[1]));
|
||||
continue;
|
||||
}
|
||||
if (buildingType.Theaters != null && !buildingType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && buildingType.Theaters != null && !buildingType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Structure '{0}' is not available in the set theater; skipping.", buildingType.Name));
|
||||
continue;
|
||||
@ -1195,7 +1193,7 @@ namespace MobiusEditor.TiberianDawn
|
||||
var buildingType = Map.BuildingTypes.Where(t => t.Equals(tokens[0])).FirstOrDefault();
|
||||
if (buildingType != null)
|
||||
{
|
||||
if (buildingType.Theaters != null && !buildingType.Theaters.Contains(Map.Theater))
|
||||
if (Globals.FilterTheaterObjects && buildingType.Theaters != null && !buildingType.Theaters.Contains(Map.Theater))
|
||||
{
|
||||
errors.Add(string.Format("Base rebuild entry {0} references structure '{1}' which is not available in the set theater; skipping.", priority, buildingType.Name));
|
||||
continue;
|
||||
@ -1738,26 +1736,27 @@ namespace MobiusEditor.TiberianDawn
|
||||
unit.Trigger
|
||||
);
|
||||
}
|
||||
// Classic game does not support this, so I'm leaving this out. It's buggy anyway.
|
||||
/*/
|
||||
var aircraftSection = ini.Sections.Add("Aircraft");
|
||||
var aircraftIndex = 0;
|
||||
foreach (var (location, aircraft) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsAircraft))
|
||||
// Classic game does not support this, so it's disabled by default.
|
||||
if (!Globals.DisableAirUnits)
|
||||
{
|
||||
var key = aircraftIndex.ToString("D3");
|
||||
aircraftIndex++;
|
||||
var aircraftSection = ini.Sections.Add("Aircraft");
|
||||
var aircraftIndex = 0;
|
||||
foreach (var (location, aircraft) in Map.Technos.OfType<Unit>().Where(u => u.Occupier.Type.IsAircraft))
|
||||
{
|
||||
var key = aircraftIndex.ToString("D3");
|
||||
aircraftIndex++;
|
||||
|
||||
Map.Metrics.GetCell(location, out int cell);
|
||||
aircraftSection[key] = string.Format("{0},{1},{2},{3},{4},{5}",
|
||||
aircraft.House.Name,
|
||||
aircraft.Type.Name,
|
||||
aircraft.Strength,
|
||||
cell,
|
||||
aircraft.Direction.ID,
|
||||
String.IsNullOrEmpty(aircraft.Mission) ? "Guard" : aircraft.Mission
|
||||
);
|
||||
Map.Metrics.GetCell(location, out int cell);
|
||||
aircraftSection[key] = string.Format("{0},{1},{2},{3},{4},{5}",
|
||||
aircraft.House.Name,
|
||||
aircraft.Type.Name,
|
||||
aircraft.Strength,
|
||||
cell,
|
||||
aircraft.Direction.ID,
|
||||
String.IsNullOrEmpty(aircraft.Mission) ? "Guard" : aircraft.Mission
|
||||
);
|
||||
}
|
||||
}
|
||||
//*/
|
||||
foreach (var house in Map.Houses)
|
||||
{
|
||||
if ((house.Type.ID < 0) || !house.Enabled)
|
||||
|
@ -17,25 +17,26 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MobiusEditor.TiberianDawn
|
||||
{
|
||||
public static class SmudgeTypes
|
||||
{
|
||||
public static readonly SmudgeType Crater1 = new SmudgeType(0, "cr1", 5);
|
||||
// Seems RA has issues reading these from missions.
|
||||
//public static readonly SmudgeType Crater2 = new SmudgeType(1, "cr2", 5);
|
||||
//public static readonly SmudgeType Crater3 = new SmudgeType(2, "cr3", 5);
|
||||
//public static readonly SmudgeType Crater4 = new SmudgeType(3, "cr4", 5);
|
||||
//public static readonly SmudgeType Crater5 = new SmudgeType(4, "cr5", 5);
|
||||
//public static readonly SmudgeType Crater6 = new SmudgeType(5, "cr6", 5);
|
||||
// Seems the game has issues reading these from missions.
|
||||
public static readonly SmudgeType Crater2 = new SmudgeType(1, "cr2", 5);
|
||||
public static readonly SmudgeType Crater3 = new SmudgeType(2, "cr3", 5);
|
||||
public static readonly SmudgeType Crater4 = new SmudgeType(3, "cr4", 5);
|
||||
public static readonly SmudgeType Crater5 = new SmudgeType(4, "cr5", 5);
|
||||
public static readonly SmudgeType Crater6 = new SmudgeType(5, "cr6", 5);
|
||||
public static readonly SmudgeType Scorch1 = new SmudgeType(6, "sc1");
|
||||
public static readonly SmudgeType Scorch2 = new SmudgeType(7, "sc2");
|
||||
public static readonly SmudgeType Scorch3 = new SmudgeType(8, "sc3");
|
||||
public static readonly SmudgeType Scorch4 = new SmudgeType(9, "sc4");
|
||||
public static readonly SmudgeType Scorch5 = new SmudgeType(10, "sc5");
|
||||
public static readonly SmudgeType Scorch6 = new SmudgeType(11, "sc6");
|
||||
// placeable versions of the bibs. Experimental for now - UI doesn't seem able to handle their full size like the game does.
|
||||
// placeable versions of the bibs.
|
||||
public static readonly SmudgeType Bib1Pl = new SmudgeType(12, "bib1", new Size(4, 2));
|
||||
public static readonly SmudgeType Bib2Pl = new SmudgeType(13, "bib2", new Size(3, 2));
|
||||
public static readonly SmudgeType Bib3Pl = new SmudgeType(14, "bib3", new Size(2, 2));
|
||||
@ -45,18 +46,29 @@ namespace MobiusEditor.TiberianDawn
|
||||
public static readonly SmudgeType Bib3 = new SmudgeType(17, "bib3", new Size(2, 2), SmudgeTypeFlag.Bib3);
|
||||
|
||||
private static SmudgeType[] Types;
|
||||
private static Regex BadCraters;
|
||||
|
||||
static SmudgeTypes()
|
||||
{
|
||||
BadCraters = new Regex("^CR[2-6]$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
Types =
|
||||
(from field in typeof(SmudgeTypes).GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||
where field.IsInitOnly && typeof(SmudgeType).IsAssignableFrom(field.FieldType)
|
||||
select field.GetValue(null) as SmudgeType).ToArray();
|
||||
}
|
||||
|
||||
public static IEnumerable<SmudgeType> GetTypes()
|
||||
public static Regex GetBadCraterRegex()
|
||||
{
|
||||
return Types;
|
||||
return BadCraters;
|
||||
}
|
||||
|
||||
public static IEnumerable<SmudgeType> GetTypes(bool singleCrater)
|
||||
{
|
||||
if (!singleCrater)
|
||||
{
|
||||
return Types;
|
||||
}
|
||||
return Types.Where(sm => !BadCraters.IsMatch(sm.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,10 +61,10 @@ namespace MobiusEditor.TiberianDawn
|
||||
select field.GetValue(null) as UnitType).ToArray();
|
||||
}
|
||||
|
||||
public static IEnumerable<UnitType> GetTypes(Boolean placeableOnly)
|
||||
public static IEnumerable<UnitType> GetTypes(Boolean withoutAircraft)
|
||||
{
|
||||
// only return placeable units; you can't place down aircraft in C&C
|
||||
if (placeableOnly)
|
||||
if (withoutAircraft)
|
||||
return Types.Where(t => !t.IsAircraft);
|
||||
return Types;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ namespace MobiusEditor.Tools
|
||||
mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, selectedBuildingType.OverlapBounds.Size));
|
||||
}
|
||||
mockBuilding.Type = selectedBuildingType;
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -163,7 +163,7 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
mockBuilding.Direction = map.DirectionTypes.Where(d => d.Equals(FacingType.North)).First();
|
||||
}
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
|
||||
private void SelectedBuilding_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
@ -605,27 +605,44 @@ namespace MobiusEditor.Tools
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
private void RefreshMapPanel()
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
var oldImage = buildingTypeMapPanel.MapImage;
|
||||
if (mockBuilding.Type != null)
|
||||
{
|
||||
var render = MapRenderer.Render(plugin.GameType, map.Theater, new Point(0, 0), Globals.PreviewTileSize, Globals.PreviewTileScale, mockBuilding);
|
||||
if (!render.Item1.IsEmpty)
|
||||
Dictionary <Point, Smudge> bibCells = mockBuilding.GetBib(new Point(0, 0), map.SmudgeTypes);
|
||||
List<(Rectangle, Action<Graphics>)> bibRender = new List<(Rectangle, Action<Graphics>)>();
|
||||
if (bibCells != null)
|
||||
{
|
||||
var buildingPreview = new Bitmap(render.Item1.Width, render.Item1.Height);
|
||||
using (var g = Graphics.FromImage(buildingPreview))
|
||||
foreach (var point in bibCells.Keys)
|
||||
{
|
||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||
render.Item2(g);
|
||||
RenderBuildingLabels(g, mockBuilding, new Point(0, 0), Globals.PreviewTileSize, Globals.PreviewTileScale, Layers, false);
|
||||
var bibCellRender = MapRenderer.Render(map.Theater, point, Globals.PreviewTileSize, Globals.PreviewTileScale, bibCells[point]);
|
||||
bibRender.Add(bibCellRender);
|
||||
}
|
||||
buildingTypeMapPanel.MapImage = buildingPreview;
|
||||
}
|
||||
else
|
||||
var renderBuilding = MapRenderer.Render(plugin.GameType, map.Theater, new Point(0, 0), Globals.PreviewTileSize, Globals.PreviewTileScale, mockBuilding);
|
||||
Size previewSize = mockBuilding.OverlapBounds.Size;
|
||||
var buildingPreview = new Bitmap(previewSize.Width * Globals.PreviewTileWidth, previewSize.Height * Globals.PreviewTileHeight);
|
||||
using (var g = Graphics.FromImage(buildingPreview))
|
||||
{
|
||||
buildingTypeMapPanel.MapImage = null;
|
||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||
foreach (var bib in bibRender)
|
||||
{
|
||||
if (!bib.Item1.IsEmpty)
|
||||
{
|
||||
bib.Item2(g);
|
||||
}
|
||||
}
|
||||
if (!renderBuilding.Item1.IsEmpty)
|
||||
{
|
||||
renderBuilding.Item2(g);
|
||||
}
|
||||
List<(Point p, Building ter)> buildingList = new List<(Point p, Building ter)>();
|
||||
buildingList.Add((new Point(0, 0), mockBuilding));
|
||||
RenderBuildingBounds(g, Globals.PreviewTileSize, buildingList);
|
||||
RenderBuildingLabels(g, mockBuilding, new Point(0, 0), Globals.PreviewTileSize, Globals.PreviewTileScale, MapLayerFlag.All, false);
|
||||
}
|
||||
buildingTypeMapPanel.MapImage = buildingPreview;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -636,6 +653,7 @@ namespace MobiusEditor.Tools
|
||||
try { oldImage.Dispose(); }
|
||||
catch { /* ignore */ }
|
||||
}
|
||||
buildingTypeMapPanel.Invalidate();
|
||||
}
|
||||
|
||||
private void UpdateStatus()
|
||||
@ -676,8 +694,18 @@ namespace MobiusEditor.Tools
|
||||
protected override void PostRenderMap(Graphics graphics)
|
||||
{
|
||||
base.PostRenderMap(graphics);
|
||||
float boundsPenSize = Math.Max(1, Globals.MapTileSize.Width / 16.0f);
|
||||
float occupyPenSize = Math.Max(0.5f, Globals.MapTileSize.Width / 32.0f);
|
||||
RenderBuildingBounds(graphics, Globals.MapTileSize, previewMap.Buildings.OfType<Building>());
|
||||
foreach (var (topLeft, building) in previewMap.Buildings.OfType<Building>())
|
||||
{
|
||||
RenderBuildingLabels(graphics, building, topLeft, Globals.MapTileSize, Globals.MapTileScale, Layers, false);
|
||||
}
|
||||
RenderTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
}
|
||||
|
||||
private static void RenderBuildingBounds(Graphics graphics, Size tileSize, IEnumerable<(Point, Building)> buildings)
|
||||
{
|
||||
float boundsPenSize = Math.Max(1, tileSize.Width / 16.0f);
|
||||
float occupyPenSize = Math.Max(0.5f, tileSize.Width / 32.0f);
|
||||
if (occupyPenSize == boundsPenSize)
|
||||
{
|
||||
boundsPenSize += 2;
|
||||
@ -685,16 +713,16 @@ namespace MobiusEditor.Tools
|
||||
using (var boundsPen = new Pen(Color.Green, boundsPenSize))
|
||||
using (var occupyPen = new Pen(Color.Red, occupyPenSize))
|
||||
{
|
||||
foreach (var (topLeft, building) in map.Buildings.OfType<Building>())
|
||||
foreach (var (topLeft, building) in buildings)
|
||||
{
|
||||
Rectangle typeBounds = building.Type.OverlapBounds;
|
||||
var bounds = new Rectangle(
|
||||
new Point(topLeft.X * Globals.MapTileWidth, topLeft.Y * Globals.MapTileHeight),
|
||||
new Size(typeBounds.Width * Globals.MapTileWidth, typeBounds.Height * Globals.MapTileHeight)
|
||||
new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height),
|
||||
new Size(typeBounds.Width * tileSize.Width, typeBounds.Height * tileSize.Height)
|
||||
);
|
||||
graphics.DrawRectangle(boundsPen, bounds);
|
||||
}
|
||||
foreach (var (topLeft, building) in map.Buildings.OfType<Building>())
|
||||
foreach (var (topLeft, building) in buildings)
|
||||
{
|
||||
for (var y = 0; y < building.Type.BaseOccupyMask.GetLength(0); ++y)
|
||||
{
|
||||
@ -703,29 +731,13 @@ namespace MobiusEditor.Tools
|
||||
if (building.Type.BaseOccupyMask[y, x])
|
||||
{
|
||||
var occupyBounds = new Rectangle(
|
||||
new Point((topLeft.X + x) * Globals.MapTileWidth, (topLeft.Y + y) * Globals.MapTileHeight),
|
||||
Globals.MapTileSize
|
||||
);
|
||||
new Point((topLeft.X + x) * tileSize.Width, (topLeft.Y + y) * tileSize.Height), tileSize);
|
||||
graphics.DrawRectangle(occupyPen, occupyBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var (topLeft, building) in map.Buildings.OfType<Building>())
|
||||
{
|
||||
RenderBuildingLabels(graphics, building, topLeft, Globals.MapTileSize, Globals.MapTileScale, Layers, false);
|
||||
}
|
||||
// Find the preview and add labels to it too.
|
||||
foreach (var (topLeft, building) in previewMap.Buildings.OfType<Building>())
|
||||
{
|
||||
if (placementMode && building.Type.ID == mockBuilding.Type.ID && navigationWidget.MouseCell == topLeft && map.Technos.CanAdd(topLeft, building, building.Type.BaseOccupyMask))
|
||||
{
|
||||
RenderBuildingLabels(graphics, building, topLeft, Globals.MapTileSize, Globals.MapTileScale, Layers, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RenderTechnoTriggers(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
}
|
||||
|
||||
public override void Activate()
|
||||
|
@ -36,6 +36,11 @@ namespace MobiusEditor.Tools
|
||||
/// </summary>
|
||||
protected override MapLayerFlag ManuallyHandledLayers => MapLayerFlag.CellTriggers;
|
||||
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
// This tool has no panel.
|
||||
}
|
||||
|
||||
private readonly ComboBox triggerComboBox;
|
||||
|
||||
private readonly Dictionary<int, CellTrigger> undoCellTriggers = new Dictionary<int, CellTrigger>();
|
||||
|
@ -19,7 +19,7 @@ namespace MobiusEditor.Tools.Dialogs
|
||||
protected override void InitializeInternal(MapPanel mapPanel, MapLayerFlag activeLayers, ToolStripStatusLabel toolStatusLabel, ToolTip mouseToolTip, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> undoRedoList)
|
||||
{
|
||||
ObjectTypeListBox.Types = plugin.Map.BuildingTypes
|
||||
.Where(t => (t.Theaters == null) || t.Theaters.Contains(plugin.Map.Theater))
|
||||
.Where(t => !Globals.FilterTheaterObjects || t.Theaters == null || t.Theaters.Contains(plugin.Map.Theater))
|
||||
.OrderBy(t => t.ID);
|
||||
Tool = new BuildingTool(mapPanel, activeLayers, toolStatusLabel, ObjectTypeListBox,
|
||||
ObjectTypeMapPanel, ObjectProperties, plugin, undoRedoList);
|
||||
|
@ -45,7 +45,7 @@ namespace MobiusEditor.Tools.Dialogs
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
CustomComponentResourceManager resources = new CustomComponentResourceManager(typeof(ObjectToolDialog<>), "ObjectToolDialog");
|
||||
CustomComponentResourceManager resources = new CustomComponentResourceManager(typeof(GenericToolDialog<>), "GenericToolDialog");
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.genericTypeMapPanel = new MobiusEditor.Controls.MapPanel();
|
||||
this.genericTypeListBox = new MobiusEditor.Controls.TypeListBox();
|
||||
|
@ -19,7 +19,7 @@ namespace MobiusEditor.Tools.Dialogs
|
||||
protected override void InitializeInternal(MapPanel mapPanel, MapLayerFlag activeLayers, ToolStripStatusLabel toolStatusLabel, ToolTip mouseToolTip, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> undoRedoList)
|
||||
{
|
||||
GenericTypeListBox.Types = plugin.Map.OverlayTypes.
|
||||
Where(t => t.IsPlaceable && ((t.Theaters == null) || t.Theaters.Contains(plugin.Map.Theater))).
|
||||
Where(t => t.IsPlaceable && (!Globals.FilterTheaterObjects || t.Theaters == null || t.Theaters.Contains(plugin.Map.Theater))).
|
||||
OrderBy(t => t.ID);
|
||||
|
||||
Tool = new OverlaysTool(mapPanel, activeLayers, toolStatusLabel,
|
||||
|
@ -80,7 +80,7 @@ namespace MobiusEditor.Tools.Dialogs
|
||||
this.smudgeTypeListBox.FormattingEnabled = true;
|
||||
this.smudgeTypeListBox.Location = new System.Drawing.Point(4, 4);
|
||||
this.smudgeTypeListBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
|
||||
this.smudgeTypeListBox.MissingThumbnail = ((System.Drawing.Image)(resources.GetObject("smudgeTypeComboBox.MissingThumbnail")));
|
||||
this.smudgeTypeListBox.MissingThumbnail = ((System.Drawing.Image)(resources.GetObject("smudgeTypeListBox.MissingThumbnail")));
|
||||
this.smudgeTypeListBox.Name = "smudgeTypeListBox";
|
||||
this.smudgeTypeListBox.Size = new System.Drawing.Size(244, 310);
|
||||
this.smudgeTypeListBox.TabIndex = 2;
|
||||
|
@ -26,7 +26,7 @@ namespace MobiusEditor.Tools.Dialogs
|
||||
ToolTip mouseToolTip, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> undoRedoList)
|
||||
{
|
||||
smudgeTypeListBox.Types = plugin.Map.SmudgeTypes
|
||||
.Where(t => !t.IsAutoBib && ((t.Theaters == null) || t.Theaters.Contains(plugin.Map.Theater)))
|
||||
.Where(t => !t.IsAutoBib && (!Globals.FilterTheaterObjects || t.Theaters == null || t.Theaters.Contains(plugin.Map.Theater)))
|
||||
.OrderBy(t => t.ID);
|
||||
Tool = new SmudgeTool(mapPanel, activeLayers, toolStatusLabel, smudgeTypeListBox, smudgeTypeMapPanel, smudgeProperties, plugin, undoRedoList);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace MobiusEditor.Tools.Dialogs
|
||||
|
||||
protected override void InitializeInternal(MapPanel mapPanel, MapLayerFlag activeLayers, ToolStripStatusLabel toolStatusLabel, ToolTip mouseToolTip, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> undoRedoList)
|
||||
{
|
||||
TerrainTypeListBox.Types = plugin.Map.TerrainTypes.Where(t => t.Theaters.Contains(plugin.Map.Theater)).OrderBy(t => t.ID);
|
||||
TerrainTypeListBox.Types = plugin.Map.TerrainTypes.Where(t => !Globals.FilterTheaterObjects || t.Theaters.Contains(plugin.Map.Theater)).OrderBy(t => t.ID);
|
||||
Tool = new TerrainTool(mapPanel, activeLayers, toolStatusLabel, TerrainTypeListBox,
|
||||
TerrainTypeMapPanel, TerrainProperties, plugin, undoRedoList);
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ namespace MobiusEditor.Tools
|
||||
|
||||
mockInfantry.Type = selectedInfantryType;
|
||||
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,7 +205,7 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void MockInfantry_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
|
||||
private void SelectedInfantry_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
@ -617,7 +617,7 @@ namespace MobiusEditor.Tools
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
private void RefreshMapPanel()
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
var oldImage = infantryTypeMapPanel.MapImage;
|
||||
if (mockInfantry.Type != null)
|
||||
@ -705,13 +705,13 @@ namespace MobiusEditor.Tools
|
||||
base.PostRenderMap(graphics);
|
||||
using (var infantryPen = new Pen(Color.Green, Math.Max(1, Globals.MapTileSize.Width / 16)))
|
||||
{
|
||||
foreach (var (topLeft, _) in map.Technos.OfType<InfantryGroup>())
|
||||
foreach (var (topLeft, _) in previewMap.Technos.OfType<InfantryGroup>())
|
||||
{
|
||||
var bounds = new Rectangle(new Point(topLeft.X * Globals.MapTileWidth, topLeft.Y * Globals.MapTileHeight), Globals.MapTileSize);
|
||||
graphics.DrawRectangle(infantryPen, bounds);
|
||||
}
|
||||
}
|
||||
RenderTechnoTriggers(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
RenderTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
}
|
||||
|
||||
public override void Activate()
|
||||
|
@ -16,6 +16,7 @@ using MobiusEditor.Controls;
|
||||
using MobiusEditor.Event;
|
||||
using MobiusEditor.Interface;
|
||||
using MobiusEditor.Model;
|
||||
using MobiusEditor.Render;
|
||||
using MobiusEditor.Utility;
|
||||
using MobiusEditor.Widgets;
|
||||
using System;
|
||||
@ -61,7 +62,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
selectedOverlayType = value;
|
||||
overlayTypeComboBox.SelectedValue = selectedOverlayType;
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -295,9 +296,49 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshMapPanel()
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
overlayTypeMapPanel.MapImage = SelectedOverlayType?.Thumbnail;
|
||||
var oldImage = overlayTypeMapPanel.MapImage;
|
||||
if (SelectedOverlayType != null)
|
||||
{
|
||||
var overlayPreview = new Bitmap(Globals.PreviewTileWidth, Globals.PreviewTileHeight);
|
||||
Overlay mockOverlay = new Overlay()
|
||||
{
|
||||
Type = SelectedOverlayType,
|
||||
Icon = 0
|
||||
};
|
||||
var render = MapRenderer.Render(plugin.GameType, map.Theater, new OverlayType[0], new OverlayType[0], new Point(0,0), Globals.PreviewTileSize, Globals.PreviewTileScale, mockOverlay);
|
||||
if (!render.Item1.IsEmpty)
|
||||
{
|
||||
using (var g = Graphics.FromImage(overlayPreview))
|
||||
{
|
||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||
render.Item2(g);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This should never happen; the map renderer renders dummy graphics for overlay now.
|
||||
using (var g = Graphics.FromImage(overlayPreview))
|
||||
{
|
||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||
List<(int, Overlay)> overlayList = new List<(int, Overlay)>();
|
||||
overlayList.Add((0, new Overlay() { Type = SelectedOverlayType, Icon = 0 }));
|
||||
RenderOverlayBounds(g, Globals.PreviewTileSize, overlayList, new CellMetrics(new Size(1, 1)));
|
||||
}
|
||||
}
|
||||
overlayTypeMapPanel.MapImage = overlayPreview;
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayTypeMapPanel.MapImage = null;
|
||||
}
|
||||
if (oldImage != null)
|
||||
{
|
||||
try { oldImage.Dispose(); }
|
||||
catch { /* ignore */ }
|
||||
}
|
||||
overlayTypeMapPanel.Invalidate();
|
||||
}
|
||||
|
||||
private void UpdateStatus()
|
||||
@ -336,12 +377,17 @@ namespace MobiusEditor.Tools
|
||||
protected override void PostRenderMap(Graphics graphics)
|
||||
{
|
||||
base.PostRenderMap(graphics);
|
||||
using (var overlayPen = new Pen(Color.Green, Math.Max(1, Globals.MapTileSize.Width / 16.0f)))
|
||||
RenderOverlayBounds(graphics, Globals.MapTileSize, previewMap.Overlay.Where(x => x.Value.Type.IsPlaceable), previewMap.Metrics);
|
||||
}
|
||||
|
||||
private static void RenderOverlayBounds(Graphics graphics, Size tileSize, IEnumerable<(int, Overlay)> overlayList, CellMetrics metrics)
|
||||
{
|
||||
using (var overlayPen = new Pen(Color.Green, Math.Max(1, tileSize.Width / 16.0f)))
|
||||
{
|
||||
foreach (var (cell, overlay) in previewMap.Overlay.Where(x => x.Value.Type.IsPlaceable))
|
||||
foreach (var (cell, overlay) in overlayList)
|
||||
{
|
||||
previewMap.Metrics.GetLocation(cell, out Point topLeft);
|
||||
var bounds = new Rectangle(new Point(topLeft.X * Globals.MapTileWidth, topLeft.Y * Globals.MapTileHeight), Globals.MapTileSize);
|
||||
metrics.GetLocation(cell, out Point topLeft);
|
||||
var bounds = new Rectangle(new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height), tileSize);
|
||||
graphics.DrawRectangle(overlayPen, bounds);
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,11 @@ namespace MobiusEditor.Tools
|
||||
/// </summary>
|
||||
protected override MapLayerFlag ManuallyHandledLayers => MapLayerFlag.None;
|
||||
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
// This tool has no panel.
|
||||
}
|
||||
|
||||
private readonly Label totalResourcesLbl;
|
||||
private readonly NumericUpDown brushSizeNud;
|
||||
private readonly CheckBox gemsCheckBox;
|
||||
|
@ -72,9 +72,9 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, selectedSmudgeType.Size));
|
||||
}
|
||||
mockSmudge.Icon = 0;
|
||||
mockSmudge.Icon = Math.Min(selectedSmudgeType.Icons - 1, mockSmudge.Icon);
|
||||
mockSmudge.Type = selectedSmudgeType;
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,7 +155,7 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void MockSmudge_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
|
||||
private void SelectedSmudge_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
@ -500,24 +500,38 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshMapPanel()
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
var oldImage = smudgeTypeMapPanel.MapImage;
|
||||
SmudgeType mockType = mockSmudge?.Type;
|
||||
if (mockType != null)
|
||||
{
|
||||
var smudgePreview = new Bitmap(Globals.PreviewTileWidth * mockType.Size.Width, Globals.PreviewTileWidth * mockType.Size.Height);
|
||||
Size mockSize = mockType.Size;
|
||||
CellMetrics mockMetrics = new CellMetrics(mockSize);
|
||||
var smudgePreview = new Bitmap(Globals.PreviewTileWidth * mockSize.Width, Globals.PreviewTileWidth * mockSize.Height);
|
||||
using (var g = Graphics.FromImage(smudgePreview))
|
||||
{
|
||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||
if (mockType.Icons > 1)
|
||||
List<(int, Smudge)> smudgeList = new List<(int, Smudge)>();
|
||||
int icons = mockSize.Width * mockSize.Height;
|
||||
for (int i = 0; i < icons; ++i)
|
||||
{
|
||||
MapRenderer.Render(map.Theater, new Point(0, 0), Globals.PreviewTileSize, Globals.PreviewTileScale, mockSmudge).Item2(g);
|
||||
}
|
||||
else if (mockType.Thumbnail != null && mockType.Icons == 1)
|
||||
{
|
||||
g.DrawImage(mockType.Thumbnail, new Rectangle(new Point(0, 0), mockType.Thumbnail.Size));
|
||||
Smudge smudge = new Smudge()
|
||||
{
|
||||
Type = mockType,
|
||||
Icon = mockType.IsMultiCell ? i : mockSmudge.Icon
|
||||
};
|
||||
smudgeList.Add((i, smudge));
|
||||
mockMetrics.GetLocation(i, out Point p);
|
||||
var render = MapRenderer.Render(map.Theater, p, Globals.PreviewTileSize, Globals.PreviewTileScale, smudge);
|
||||
if (!render.Item1.IsEmpty)
|
||||
{
|
||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||
render.Item2(g);
|
||||
}
|
||||
}
|
||||
RenderSmudgeBounds(g, Globals.PreviewTileSize, smudgeList, mockMetrics);
|
||||
|
||||
}
|
||||
smudgeTypeMapPanel.MapImage = smudgePreview;
|
||||
}
|
||||
@ -530,6 +544,7 @@ namespace MobiusEditor.Tools
|
||||
try { oldImage.Dispose(); }
|
||||
catch { /* ignore */ }
|
||||
}
|
||||
smudgeTypeMapPanel.Invalidate();
|
||||
}
|
||||
|
||||
private void UpdateStatus()
|
||||
@ -595,12 +610,17 @@ namespace MobiusEditor.Tools
|
||||
protected override void PostRenderMap(Graphics graphics)
|
||||
{
|
||||
base.PostRenderMap(graphics);
|
||||
using (var smudgePen = new Pen(Color.Green, Math.Max(1, Globals.MapTileSize.Width / 16.0f)))
|
||||
RenderSmudgeBounds(graphics, Globals.MapTileSize, previewMap.Smudge.Where(x => !x.Value.Type.IsAutoBib), previewMap.Metrics);
|
||||
}
|
||||
|
||||
public static void RenderSmudgeBounds(Graphics graphics, Size tileSize, IEnumerable<(int, Smudge)> smudgeList, CellMetrics metrics)
|
||||
{
|
||||
using (var smudgePen = new Pen(Color.Green, Math.Max(1, tileSize.Width / 16.0f)))
|
||||
{
|
||||
foreach (var (cell, smudge) in previewMap.Smudge.Where(x => !x.Value.Type.IsAutoBib))
|
||||
foreach (var (cell, smudge) in smudgeList)
|
||||
{
|
||||
previewMap.Metrics.GetLocation(cell, out Point topLeft);
|
||||
var bounds = new Rectangle(new Point(topLeft.X * Globals.MapTileWidth, topLeft.Y * Globals.MapTileHeight), Globals.MapTileSize);
|
||||
metrics.GetLocation(cell, out Point topLeft);
|
||||
var bounds = new Rectangle(new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height), tileSize);
|
||||
graphics.DrawRectangle(smudgePen, bounds);
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
}
|
||||
RefreshPreviewMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,108 +444,135 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void HandleFill(MouseButtons button)
|
||||
{
|
||||
bool place = button == MouseButtons.Left;
|
||||
bool clear = button == MouseButtons.Right;
|
||||
TemplateType selected = SelectedTemplateType;
|
||||
Point? icon = SelectedIcon;
|
||||
if (place && selected == null)
|
||||
if (selected == null)
|
||||
{
|
||||
place = false;
|
||||
clear = true;
|
||||
return;
|
||||
}
|
||||
if ((!place && !clear) || place && clear)
|
||||
Point? icon = SelectedIcon;
|
||||
bool clear = button == MouseButtons.Right;
|
||||
bool place = button == MouseButtons.Left;
|
||||
// beware: mask has this odd quirk that x comes first, like in coords.
|
||||
// This means flattening it to an array will mess up the order.
|
||||
bool[,] mask = selected.IconMask;
|
||||
bool is1x1 = selected.IconWidth == 1 && selected.IconHeight == 1;
|
||||
if ((!place && !clear) || (place && clear))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Point currentCell = navigationWidget.MouseCell;
|
||||
TemplateType toFind = null;
|
||||
String[] groupToFind = null;
|
||||
if (selected != null)
|
||||
// Determine which types to include in the fill detection
|
||||
HashSet<TemplateType> templatesToFind = new HashSet<TemplateType>();
|
||||
if (place || is1x1)
|
||||
{
|
||||
if (selected.IconHeight == 1 && selected.IconWidth == 1 || place)
|
||||
TemplateType toFind = map.Templates[currentCell]?.Type;
|
||||
if (toFind != null && (toFind.Flag & TemplateTypeFlag.IsGrouped) != TemplateTypeFlag.None && toFind.GroupTiles.Length == 1)
|
||||
{
|
||||
Template cellToFind = map.Templates[currentCell];
|
||||
toFind = cellToFind == null ? null : cellToFind.Type;
|
||||
|
||||
if (toFind != null && (toFind.Flag & TemplateTypeFlag.IsGrouped) != TemplateTypeFlag.None && toFind.GroupTiles.Length == 1)
|
||||
{
|
||||
string owningType = toFind.GroupTiles[0];
|
||||
TemplateType group = map.TemplateTypes.Where(t => t.Name.Equals(owningType, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
|
||||
groupToFind = group.GroupTiles.ToArray();
|
||||
}
|
||||
string owningType = toFind.GroupTiles[0];
|
||||
TemplateType group = map.TemplateTypes.Where(t => t.Name.Equals(owningType, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
|
||||
templatesToFind.UnionWith(map.TemplateTypes.Where(t => group.GroupTiles.Contains(t.Name, StringComparer.InvariantCultureIgnoreCase)));
|
||||
}
|
||||
else if (clear)
|
||||
else
|
||||
{
|
||||
// For Clear, it'll evaluate all cell types under the full selected tile, and clear all adjacent tiles of all those types.
|
||||
List<TemplateType> typesToFind = new List<TemplateType>();
|
||||
int endY = currentCell.Y + selected.IconHeight;
|
||||
int endX = currentCell.X + selected.IconWidth;
|
||||
for (int y = currentCell.Y; y < endY; ++y)
|
||||
{
|
||||
for (int x = currentCell.X; x < endX; ++x)
|
||||
{
|
||||
if (map.Metrics.GetCell(new Point(x, y), out int cell))
|
||||
{
|
||||
typesToFind.Add(map.Templates[cell]?.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Detect any group types inside it and get the full list.
|
||||
List<string> listToFind = new List<string>();
|
||||
foreach (TemplateType tp in typesToFind)
|
||||
{
|
||||
if (tp != null && (tp.Flag & TemplateTypeFlag.IsGrouped) != TemplateTypeFlag.None && tp.GroupTiles.Length == 1)
|
||||
{
|
||||
string owningType = tp.GroupTiles[0];
|
||||
TemplateType group = map.TemplateTypes.Where(t => t.Name.Equals(owningType, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
|
||||
listToFind.AddRange(group.GroupTiles);
|
||||
}
|
||||
else
|
||||
{
|
||||
listToFind.Add(tp?.Name);
|
||||
}
|
||||
}
|
||||
groupToFind = listToFind.Distinct().ToArray();
|
||||
templatesToFind.Add(toFind);
|
||||
}
|
||||
}
|
||||
else if (clear)
|
||||
{
|
||||
// For Clear, it'll evaluate all cell types under the full selected tile, and clear all adjacent tiles of all those types.
|
||||
List<TemplateType> typesToFind = new List<TemplateType>();
|
||||
for (int y = 0; y < selected.IconHeight; ++y)
|
||||
{
|
||||
for (int x = 0; x < selected.IconWidth; ++x)
|
||||
{
|
||||
Point toCheck = new Point(x + currentCell.X, y + currentCell.Y);
|
||||
if (mask[x, y] && map.Metrics.GetCell(toCheck, out int cell))
|
||||
{
|
||||
typesToFind.Add(map.Templates[cell]?.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Detect any group types inside it and get the full list.
|
||||
foreach (TemplateType tp in typesToFind)
|
||||
{
|
||||
if (tp != null && (tp.Flag & TemplateTypeFlag.IsGrouped) != TemplateTypeFlag.None && tp.GroupTiles.Length == 1)
|
||||
{
|
||||
string owningType = tp.GroupTiles[0];
|
||||
TemplateType group = map.TemplateTypes.Where(t => t.Name.Equals(owningType, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
|
||||
templatesToFind.UnionWith(map.TemplateTypes.Where(t => group.GroupTiles.Contains(t.Name, StringComparer.InvariantCultureIgnoreCase)));
|
||||
}
|
||||
else
|
||||
{
|
||||
templatesToFind.Add(tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Transform map data to simpler array.
|
||||
int mapWidth = map.Metrics.Width;
|
||||
int mapHeight = map.Metrics.Height;
|
||||
Template[] scanData = new Template[mapHeight * mapWidth];
|
||||
|
||||
foreach ((int cell, Template t) in map.Templates)
|
||||
{
|
||||
scanData[cell] = t;
|
||||
}
|
||||
Boolean containsType(Template[] mapData, int yVal, int xVal)
|
||||
// Determine which cells to perform the blob search on.
|
||||
List<Point> detectPoints = new List<Point>();
|
||||
if (place || is1x1)
|
||||
{
|
||||
TemplateType typeAtPoint = mapData[mapWidth * yVal + xVal]?.Type;
|
||||
if (toFind == null && groupToFind == null)
|
||||
{
|
||||
return typeAtPoint == null;
|
||||
}
|
||||
if (typeAtPoint == null)
|
||||
{
|
||||
// If the group contains null; it fits.
|
||||
return groupToFind != null && groupToFind.Any(t => t == null);
|
||||
}
|
||||
if (groupToFind != null)
|
||||
{
|
||||
return groupToFind.Any(t => String.Equals(t, typeAtPoint.Name, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
return typeAtPoint.Equals(toFind);
|
||||
// Placement mode: only fill from the actual mouse point.
|
||||
detectPoints.Add(currentCell);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear mode: fill with all cells in the grid that are in the icon mask.
|
||||
for (int y = 0; y < selected.IconHeight; ++y)
|
||||
{
|
||||
for (int x = 0; x < selected.IconWidth; ++x)
|
||||
{
|
||||
Point toAdd = new Point(x + currentCell.X, y + currentCell.Y);
|
||||
if (mask[x, y] && map.Metrics.GetCell(toAdd, out int cell))
|
||||
{
|
||||
detectPoints.Add(toAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Actual flood fill part.
|
||||
Rectangle bounds = map.Bounds;
|
||||
bool inBounds = bounds.Contains(currentCell);
|
||||
bool validCell(Template[] mapData, int yVal, int xVal)
|
||||
{
|
||||
if (Globals.BoundsObstructFill)
|
||||
{
|
||||
bool pointInBounds = bounds.Contains(xVal, yVal);
|
||||
if ((inBounds && !pointInBounds) || (!inBounds && pointInBounds))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return templatesToFind.Contains(mapData[mapWidth * yVal + xVal]?.Type);
|
||||
}
|
||||
HashSet<Point> fillPoints = new HashSet<Point>();
|
||||
foreach (Point p in detectPoints)
|
||||
{
|
||||
if (!fillPoints.Contains(p))
|
||||
{
|
||||
List<Point> blobPoints = BlobDetection.MakeBlobForPoint(p.X, p.Y, scanData, mapWidth, mapHeight,
|
||||
validCell, false, false, null, out _);
|
||||
fillPoints.UnionWith(blobPoints);
|
||||
}
|
||||
}
|
||||
List<Point> fillPoints = BlobDetection.MakeBlobForPoint(currentCell.X, currentCell.Y, scanData, mapWidth, mapHeight,
|
||||
containsType, false, false, null, out Boolean[,] inBlob);
|
||||
undoTemplates.Clear();
|
||||
redoTemplates.Clear();
|
||||
bool is1x1 = selected.IconWidth == 1 && selected.IconHeight == 1;
|
||||
if (clear || icon.HasValue || is1x1)
|
||||
// Prevent it from placing down actual clear terrain.
|
||||
bool isClear = clear || (selected.Flag & TemplateTypeFlag.Clear) == TemplateTypeFlag.Clear;
|
||||
if (isClear || icon.HasValue || is1x1)
|
||||
{
|
||||
foreach (Point fill in fillPoints)
|
||||
{
|
||||
if (map.Metrics.GetCell(fill, out int cell))
|
||||
{
|
||||
if (clear)
|
||||
if (isClear)
|
||||
{
|
||||
undoTemplates[cell] = map.Templates[fill];
|
||||
map.Templates[cell] = null;
|
||||
@ -557,6 +584,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
}
|
||||
mapPanel.Invalidate(map, fillPoints);
|
||||
}
|
||||
else if (place)
|
||||
{
|
||||
@ -565,7 +593,6 @@ namespace MobiusEditor.Tools
|
||||
// get offset
|
||||
int originX = currentCell.X % width;
|
||||
int originY = currentCell.Y % height;
|
||||
bool[] toFill = selected.IconMask.Cast<bool>().ToArray();
|
||||
List<Point> refreshList = new List<Point>();
|
||||
foreach (Point p in fillPoints)
|
||||
{
|
||||
@ -576,7 +603,7 @@ namespace MobiusEditor.Tools
|
||||
if (diffY < 0)
|
||||
diffY += height;
|
||||
int paintIcon = diffY * width + diffX;
|
||||
if (!toFill[paintIcon])
|
||||
if (!mask[diffX,diffY])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -593,11 +620,10 @@ namespace MobiusEditor.Tools
|
||||
redoTemplates[cell] = tmp;
|
||||
}
|
||||
}
|
||||
// Exclude nonexistent tiles that didn't get replaced.
|
||||
fillPoints = refreshList;
|
||||
// Exclude nonexistent tiles that didn't get replaced from the refresh.
|
||||
mapPanel.Invalidate(map, refreshList);
|
||||
}
|
||||
CommitTileChanges(true);
|
||||
mapPanel.Invalidate(map, fillPoints);
|
||||
}
|
||||
|
||||
private void MapPanel_MouseUp(object sender, MouseEventArgs e)
|
||||
@ -773,7 +799,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshPreviewMapPanel()
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
if (templateTypeNavigationWidget != null)
|
||||
{
|
||||
@ -1302,7 +1328,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
else if (fillMode)
|
||||
{
|
||||
statusLbl.Text = "Left-Click to fill, Right-Click to clear-fill; affects all neighboring tiles of the underlying type.";
|
||||
statusLbl.Text = "Left-Click to fill all tiles adjacent to the mouse cell of the type under the mouse cell, Right-Click to clear all adjacent tiles of all types under the selected template's cells.";
|
||||
}
|
||||
else if (boundsMode)
|
||||
{
|
||||
|
@ -16,9 +16,11 @@ using MobiusEditor.Controls;
|
||||
using MobiusEditor.Event;
|
||||
using MobiusEditor.Interface;
|
||||
using MobiusEditor.Model;
|
||||
using MobiusEditor.Render;
|
||||
using MobiusEditor.Utility;
|
||||
using MobiusEditor.Widgets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
@ -72,7 +74,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
mockTerrain.Type = selectedTerrainType;
|
||||
mockTerrain.Icon = selectedTerrainType.DisplayIcon;
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,7 +162,7 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void MockTerrain_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
|
||||
private void TerrainTypeCombo_SelectedIndexChanged(object sender, EventArgs e)
|
||||
@ -392,9 +394,37 @@ namespace MobiusEditor.Tools
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
private void RefreshMapPanel()
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
terrainTypeMapPanel.MapImage = mockTerrain.Type.Thumbnail;
|
||||
var oldImage = terrainTypeMapPanel.MapImage;
|
||||
if (mockTerrain.Type != null)
|
||||
{
|
||||
Size previewSize = mockTerrain.Type.OverlapBounds.Size;
|
||||
var terrainPreview = new Bitmap(previewSize.Width * Globals.PreviewTileWidth, previewSize.Height * Globals.PreviewTileHeight);
|
||||
using (var g = Graphics.FromImage(terrainPreview))
|
||||
{
|
||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||
var render = MapRenderer.Render(plugin.GameType, map.Theater, new Point(0, 0), Globals.PreviewTileSize, Globals.PreviewTileScale, mockTerrain);
|
||||
if (!render.Item1.IsEmpty)
|
||||
{
|
||||
render.Item2(g);
|
||||
}
|
||||
List<(Point p, Terrain ter)> terrainList = new List<(Point p, Terrain ter)>();
|
||||
terrainList.Add((new Point(0, 0), mockTerrain));
|
||||
RenderTerrainBounds(g, Globals.PreviewTileSize, terrainList);
|
||||
}
|
||||
terrainTypeMapPanel.MapImage = terrainPreview;
|
||||
}
|
||||
else
|
||||
{
|
||||
terrainTypeMapPanel.MapImage = null;
|
||||
}
|
||||
if (oldImage != null)
|
||||
{
|
||||
try { oldImage.Dispose(); }
|
||||
catch { /* ignore */ }
|
||||
}
|
||||
terrainTypeMapPanel.Invalidate();
|
||||
}
|
||||
|
||||
private void UpdateStatus()
|
||||
@ -443,8 +473,14 @@ namespace MobiusEditor.Tools
|
||||
protected override void PostRenderMap(Graphics graphics)
|
||||
{
|
||||
base.PostRenderMap(graphics);
|
||||
float boundsPenSize = Math.Max(1, Globals.MapTileSize.Width / 16.0f);
|
||||
float occupyPenSize = Math.Max(0.5f, Globals.MapTileSize.Width / 32.0f);
|
||||
RenderTerrainBounds(graphics, Globals.MapTileSize, previewMap.Technos.OfType<Terrain>());
|
||||
RenderTechnoTriggers(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
}
|
||||
|
||||
private static void RenderTerrainBounds(Graphics graphics, Size tileSize, IEnumerable<(Point p, Terrain ter)> terrainList)
|
||||
{
|
||||
float boundsPenSize = Math.Max(1, tileSize.Width / 16.0f);
|
||||
float occupyPenSize = Math.Max(0.5f, tileSize.Width / 32.0f);
|
||||
if (occupyPenSize == boundsPenSize)
|
||||
{
|
||||
boundsPenSize++;
|
||||
@ -452,12 +488,12 @@ namespace MobiusEditor.Tools
|
||||
using (var boundsPen = new Pen(Color.Green, boundsPenSize))
|
||||
using (var occupyPen = new Pen(Color.Red, occupyPenSize))
|
||||
{
|
||||
foreach (var (topLeft, terrain) in previewMap.Technos.OfType<Terrain>())
|
||||
foreach (var (topLeft, terrain) in terrainList)
|
||||
{
|
||||
var bounds = new Rectangle(new Point(topLeft.X * Globals.MapTileWidth, topLeft.Y * Globals.MapTileHeight), terrain.Type.GetRenderSize(Globals.MapTileSize));
|
||||
var bounds = new Rectangle(new Point(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height), terrain.Type.GetRenderSize(tileSize));
|
||||
graphics.DrawRectangle(boundsPen, bounds);
|
||||
}
|
||||
foreach (var (topLeft, terrain) in previewMap.Technos.OfType<Terrain>())
|
||||
foreach (var (topLeft, terrain) in terrainList)
|
||||
{
|
||||
for (var y = 0; y < terrain.Type.OccupyMask.GetLength(0); ++y)
|
||||
{
|
||||
@ -466,16 +502,14 @@ namespace MobiusEditor.Tools
|
||||
if (!terrain.Type.OccupyMask[y, x])
|
||||
continue;
|
||||
var occupyBounds = new Rectangle(
|
||||
new Point((topLeft.X + x) * Globals.MapTileWidth, (topLeft.Y + y) * Globals.MapTileHeight),
|
||||
Globals.MapTileSize
|
||||
);
|
||||
new Point((topLeft.X + x) * tileSize.Width, (topLeft.Y + y) * tileSize.Height), tileSize);
|
||||
graphics.DrawRectangle(occupyPen, occupyBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RenderTechnoTriggers(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
}
|
||||
|
||||
|
||||
public override void Activate()
|
||||
{
|
||||
|
@ -72,7 +72,7 @@ namespace MobiusEditor.Tools
|
||||
mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));
|
||||
}
|
||||
mockUnit.Type = selectedUnitType;
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -197,7 +197,7 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void MockUnit_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
RefreshMapPanel();
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
|
||||
private void SelectedUnit_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
@ -434,7 +434,7 @@ namespace MobiusEditor.Tools
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
private void RefreshMapPanel()
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
var oldImage = unitTypeMapPanel.MapImage;
|
||||
if (mockUnit.Type != null)
|
||||
@ -497,13 +497,13 @@ namespace MobiusEditor.Tools
|
||||
base.PostRenderMap(graphics);
|
||||
using (var unitPen = new Pen(Color.Green, Math.Max(1, Globals.MapTileSize.Width / 16.0f)))
|
||||
{
|
||||
foreach (var (topLeft, _) in map.Technos.OfType<Unit>())
|
||||
foreach (var (topLeft, _) in previewMap.Technos.OfType<Unit>())
|
||||
{
|
||||
var bounds = new Rectangle(new Point(topLeft.X * Globals.MapTileWidth, topLeft.Y * Globals.MapTileHeight), Globals.MapTileSize);
|
||||
graphics.DrawRectangle(unitPen, bounds);
|
||||
}
|
||||
}
|
||||
RenderTechnoTriggers(graphics, map, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
RenderTechnoTriggers(graphics, previewMap, Globals.MapTileSize, Globals.MapTileScale, Layers);
|
||||
}
|
||||
|
||||
public override void Activate()
|
||||
|
@ -56,8 +56,11 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
if (layers != value)
|
||||
{
|
||||
MapLayerFlag modifiedBits = layers ^ value;
|
||||
bool refreshIndicatorsOnly = (modifiedBits & ~MapLayerFlag.Indicators) == 0;
|
||||
layers = value;
|
||||
Invalidate();
|
||||
Invalidate(refreshIndicatorsOnly);
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,9 +77,17 @@ namespace MobiusEditor.Tools
|
||||
navigationWidget = new NavigationWidget(mapPanel, map.Metrics, Globals.MapTileSize);
|
||||
}
|
||||
|
||||
protected void Invalidate()
|
||||
protected void Invalidate(bool refreshIndicatorsOnly)
|
||||
{
|
||||
mapPanel.Invalidate(RenderMap);
|
||||
if (refreshIndicatorsOnly)
|
||||
{
|
||||
mapPanel.Invalidate();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Full repaint.
|
||||
mapPanel.Invalidate(RenderMap);
|
||||
}
|
||||
}
|
||||
|
||||
private void BasicSection_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
@ -172,6 +183,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void RefreshPreviewPanel();
|
||||
|
||||
private void Map_RulesChanged(Object sender, EventArgs e)
|
||||
{
|
||||
@ -179,9 +191,13 @@ namespace MobiusEditor.Tools
|
||||
foreach ((Point p, Building bld) in map.Buildings.OfType<Building>())
|
||||
{
|
||||
Dictionary<Point, Smudge> bibPoints = bld.GetBib(p, map.SmudgeTypes, true);
|
||||
mapPanel.Invalidate(map, bibPoints.Keys);
|
||||
SmudgeTool.RestoreNearbySmudge(map, bibPoints.Keys, null);
|
||||
if (bibPoints != null)
|
||||
{
|
||||
mapPanel.Invalidate(map, bibPoints.Keys);
|
||||
SmudgeTool.RestoreNearbySmudge(map, bibPoints.Keys, null);
|
||||
}
|
||||
}
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
|
||||
private void MapPanel_PreRender(object sender, RenderEventArgs e)
|
||||
@ -265,7 +281,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenderAllBuildingLabels(Graphics graphics, Map map, Size tileSize, double tileScale, MapLayerFlag layersToRender)
|
||||
public static void RenderAllBuildingLabels(Graphics graphics, Map map, Size tileSize, double tileScale, MapLayerFlag layersToRender)
|
||||
{
|
||||
if ((layersToRender & MapLayerFlag.Buildings) == MapLayerFlag.None
|
||||
|| ((layersToRender & MapLayerFlag.BuildingRebuild) == MapLayerFlag.None && (layersToRender & MapLayerFlag.BuildingFakes) == MapLayerFlag.None))
|
||||
@ -278,36 +294,7 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
protected static void RenderBuildingFakeLabel(Graphics graphics, Building building, Point topLeft, Size tileSize, double tileScale, MapLayerFlag layersToRender)
|
||||
{
|
||||
if ((layersToRender & MapLayerFlag.BuildingFakes) == MapLayerFlag.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var size = new Size(building.Type.Size.Width * tileSize.Width, building.Type.Size.Height * tileSize.Height);
|
||||
string fakeText = Globals.TheGameTextManager["TEXT_UI_FAKE"];
|
||||
Rectangle bounds = new Rectangle(topLeft.X * tileSize.Width, topLeft.Y * tileSize.Height, size.Width, size.Height);
|
||||
using (var fakeBackgroundBrush = new SolidBrush(Color.FromArgb(96, Color.Black)))
|
||||
using (var fakeBrush = new SolidBrush(Color.LimeGreen))
|
||||
{
|
||||
StringFormat stringFormat = new StringFormat
|
||||
{
|
||||
Alignment = StringAlignment.Center,
|
||||
LineAlignment = StringAlignment.Center
|
||||
};
|
||||
using (var font = graphics.GetAdjustedFont(fakeText, SystemFonts.DefaultFont, bounds.Width,
|
||||
Math.Max(1, (int)(12 * tileScale)), Math.Max(1, (int)(24 * tileScale)), true))
|
||||
{
|
||||
var textBounds = graphics.MeasureString(fakeText, font, bounds.Width, stringFormat);
|
||||
var backgroundBounds = new RectangleF(bounds.Location, textBounds);
|
||||
//backgroundBounds.Offset((bounds.Width - textBounds.Width) / 2.0f, (bounds.Height - textBounds.Height) / 2.0f);
|
||||
graphics.FillRectangle(fakeBackgroundBrush, backgroundBounds);
|
||||
graphics.DrawString(fakeText, font, fakeBrush, bounds, stringFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static void RenderBuildingLabels(Graphics graphics, Building building, Point topLeft, Size tileSize, double tileScale, MapLayerFlag layersToRender, Boolean forPreview)
|
||||
public static void RenderBuildingLabels(Graphics graphics, Building building, Point topLeft, Size tileSize, double tileScale, MapLayerFlag layersToRender, Boolean forPreview)
|
||||
{
|
||||
if ((layersToRender & MapLayerFlag.Buildings) == MapLayerFlag.None)
|
||||
{
|
||||
|
@ -36,6 +36,11 @@ namespace MobiusEditor.Tools
|
||||
/// </summary>
|
||||
protected override MapLayerFlag ManuallyHandledLayers => MapLayerFlag.None;
|
||||
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
// This tool has no panel.
|
||||
}
|
||||
|
||||
private readonly TypeListBox wallTypeComboBox;
|
||||
private readonly MapPanel wallTypeMapPanel;
|
||||
|
||||
|
@ -36,6 +36,11 @@ namespace MobiusEditor.Tools
|
||||
/// </summary>
|
||||
protected override MapLayerFlag ManuallyHandledLayers => MapLayerFlag.Waypoints;
|
||||
|
||||
protected override void RefreshPreviewPanel()
|
||||
{
|
||||
// This tool has no panel.
|
||||
}
|
||||
|
||||
private readonly ComboBox waypointCombo;
|
||||
private readonly Button jumpToButton;
|
||||
|
||||
|
@ -5,12 +5,10 @@ using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MobiusEditor.Utility
|
||||
{
|
||||
|
||||
|
||||
public class CustomComponentResourceManager : ComponentResourceManager
|
||||
{
|
||||
public CustomComponentResourceManager(Type type, string resourceName)
|
||||
|
Loading…
x
Reference in New Issue
Block a user