v1.4.3.3 stuff initial commit
This commit is contained in:
parent
60b6eebf41
commit
de53479e32
@ -316,6 +316,7 @@
|
||||
<Compile Include="Model\Infantry.cs" />
|
||||
<Compile Include="Model\Map.cs" />
|
||||
<Compile Include="Model\MapSection.cs" />
|
||||
<Compile Include="Model\NotifiableIniSection.cs" />
|
||||
<Compile Include="Model\OccupierSet.cs" />
|
||||
<Compile Include="Model\OverlapperSet.cs" />
|
||||
<Compile Include="Model\Overlay.cs" />
|
||||
@ -559,6 +560,7 @@
|
||||
<Compile Include="Utility\GeneralUtils.cs" />
|
||||
<Compile Include="Utility\GenericBooleanTypeConverter.cs" />
|
||||
<Compile Include="Utility\INI.cs" />
|
||||
<Compile Include="Utility\Keyboard.cs" />
|
||||
<Compile Include="Utility\ListItem.cs" />
|
||||
<Compile Include="Utility\Megafile.cs" />
|
||||
<Compile Include="Utility\MegafileBuilder.cs" />
|
||||
|
@ -13,6 +13,7 @@
|
||||
// GNU General Public License along with permitted additional restrictions
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
using MobiusEditor.Interface;
|
||||
using MobiusEditor.Model;
|
||||
using MobiusEditor.Utility;
|
||||
using System;
|
||||
using System.Data;
|
||||
@ -23,7 +24,7 @@ namespace MobiusEditor.Controls
|
||||
{
|
||||
public partial class BasicSettings : UserControl
|
||||
{
|
||||
public BasicSettings(IGamePlugin plugin, dynamic basicSection)
|
||||
public BasicSettings(IGamePlugin plugin, PropertyTracker<BasicSection> basicSection)
|
||||
{
|
||||
InitializeComponent();
|
||||
playerComboBox.DataSource = plugin.Map.Houses.Select(h => h.Type.Name).ToArray();
|
||||
|
@ -13,13 +13,15 @@
|
||||
// GNU General Public License along with permitted additional restrictions
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
using MobiusEditor.Interface;
|
||||
using MobiusEditor.Model;
|
||||
using MobiusEditor.Utility;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MobiusEditor.Controls
|
||||
{
|
||||
public partial class BriefingSettings : UserControl
|
||||
{
|
||||
public BriefingSettings(IGamePlugin plugin, dynamic briefingSection)
|
||||
public BriefingSettings(IGamePlugin plugin, PropertyTracker<BriefingSection> briefingSection)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
|
@ -269,11 +269,7 @@ namespace MobiusEditor.Controls
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
if (!isMockObject)
|
||||
{
|
||||
Plugin.Dirty = true;
|
||||
}
|
||||
// The undo/redo system now handles plugin dirty state.
|
||||
}
|
||||
|
||||
private void AdjustToStructurePrebuiltStatus(Building building)
|
||||
|
@ -52,12 +52,12 @@ namespace MobiusEditor.Controls
|
||||
// txtRules
|
||||
//
|
||||
this.txtRules.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.txtRules.Location = new System.Drawing.Point(2, 36);
|
||||
this.txtRules.Location = new System.Drawing.Point(2, 49);
|
||||
this.txtRules.Margin = new System.Windows.Forms.Padding(2, 10, 2, 2);
|
||||
this.txtRules.Multiline = true;
|
||||
this.txtRules.Name = "txtRules";
|
||||
this.txtRules.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txtRules.Size = new System.Drawing.Size(596, 362);
|
||||
this.txtRules.Size = new System.Drawing.Size(596, 349);
|
||||
this.txtRules.TabIndex = 1;
|
||||
this.txtRules.Leave += new System.EventHandler(this.txtRules_Leave);
|
||||
//
|
||||
@ -67,7 +67,7 @@ namespace MobiusEditor.Controls
|
||||
this.lblRules.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lblRules.Location = new System.Drawing.Point(3, 0);
|
||||
this.lblRules.Name = "lblRules";
|
||||
this.lblRules.Size = new System.Drawing.Size(594, 26);
|
||||
this.lblRules.Size = new System.Drawing.Size(594, 39);
|
||||
this.lblRules.TabIndex = 0;
|
||||
this.lblRules.Text = resources.GetString("lblRules.Text");
|
||||
//
|
||||
|
@ -118,6 +118,6 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="lblRules.Text" xml:space="preserve">
|
||||
<value>The text below shows all INI sections not managed by the editor. Add any rule changes you need. Sections managed by the editor ([Basic], [Units], [Trigs] etc.) will be ignored. Rule changes will be applied in the editor</value>
|
||||
<value>The text below shows all INI sections not managed by the editor. Add any rule changes you need. Sections managed by the editor ([Basic], [Units], [Trigs] etc.) will be ignored. Rule changes will be applied in the editor. [Aftermath] can be added, but its "NewUnitsEnabled" option is managed by the editor (in "Basic") and will be ignored here.</value>
|
||||
</data>
|
||||
</root>
|
@ -13,6 +13,7 @@
|
||||
// GNU General Public License along with permitted additional restrictions
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
using MobiusEditor.Interface;
|
||||
using MobiusEditor.Model;
|
||||
using MobiusEditor.Utility;
|
||||
using System;
|
||||
using System.Data;
|
||||
@ -23,7 +24,7 @@ namespace MobiusEditor.Controls
|
||||
{
|
||||
public partial class ScenarioSettings : UserControl
|
||||
{
|
||||
public ScenarioSettings(dynamic basicSection)
|
||||
public ScenarioSettings(PropertyTracker<BasicSection> basicSection)
|
||||
{
|
||||
InitializeComponent();
|
||||
chkToCarryOver.DataBindings.Add("Checked", basicSection, "ToCarryOver");
|
||||
|
@ -99,10 +99,7 @@ namespace MobiusEditor.Controls
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!isMockObject)
|
||||
{
|
||||
Plugin.Dirty = true;
|
||||
}
|
||||
// The undo/redo system now handles plugin dirty state.
|
||||
}
|
||||
|
||||
private void comboBox_SelectedValueChanged(object sender, EventArgs e)
|
||||
|
@ -116,10 +116,7 @@ namespace MobiusEditor.Controls
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!isMockObject)
|
||||
{
|
||||
Plugin.Dirty = true;
|
||||
}
|
||||
// The undo/redo system now handles plugin dirty state.
|
||||
}
|
||||
|
||||
private void comboBox_SelectedValueChanged(object sender, EventArgs e)
|
||||
|
@ -111,7 +111,8 @@ namespace MobiusEditor.Dialogs
|
||||
foreach (var player in this.plugin.Map.Houses)
|
||||
{
|
||||
var playerNode = playersNode.Nodes.Add(player.Type.Name, player.Type.Name);
|
||||
playerNode.Checked = player.Enabled;
|
||||
bool enabled = houseSettingsTrackers[player].TryGetMember("Enabled", out object res) && (res is bool en) && en;
|
||||
playerNode.Checked = enabled;
|
||||
}
|
||||
playersNode.Expand();
|
||||
settingsTreeView.EndUpdate();
|
||||
@ -158,7 +159,6 @@ namespace MobiusEditor.Dialogs
|
||||
break;
|
||||
case "RULES":
|
||||
{
|
||||
// TODO clone briefing panel, add extra logic.
|
||||
RulesSettings rulesPanel = new RulesSettings(ExtraIniText);
|
||||
rulesPanel.TextNeedsUpdating += this.RulesPanel_TextNeedsUpdating;
|
||||
settingsPanel.Controls.Add(rulesPanel);
|
||||
@ -235,7 +235,9 @@ namespace MobiusEditor.Dialogs
|
||||
var player = plugin.Map.Houses.Where(h => h.Type.Name == e.Node.Name).FirstOrDefault();
|
||||
if (player != null)
|
||||
{
|
||||
((dynamic)houseSettingsTrackers[player]).Enabled = e.Node.Checked;
|
||||
// I don't think I like "dynamic". With "TrySetMember" you at least SEE that the variable is looked up by string.
|
||||
//((dynamic)houseSettingsTrackers[player]).Enabled = e.Node.Checked;
|
||||
houseSettingsTrackers[player].TrySetMember("Enabled", e.Node.Checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
// GNU General Public License along with permitted additional restrictions
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
using MobiusEditor.Controls;
|
||||
using MobiusEditor.Interface;
|
||||
using MobiusEditor.Model;
|
||||
|
||||
namespace MobiusEditor.Event
|
||||
@ -21,11 +22,21 @@ namespace MobiusEditor.Event
|
||||
{
|
||||
public MapPanel MapPanel { get; private set; }
|
||||
|
||||
public IGamePlugin Plugin { get; private set; }
|
||||
|
||||
public Map Map { get; private set; }
|
||||
|
||||
public UndoRedoEventArgs(MapPanel mapPanel, Map map)
|
||||
public UndoRedoEventArgs(MapPanel mapPanel, IGamePlugin plugin)
|
||||
{
|
||||
MapPanel = mapPanel;
|
||||
Plugin = plugin;
|
||||
Map = plugin.Map;
|
||||
}
|
||||
|
||||
public UndoRedoEventArgs(MapPanel mapPanel, Map map, IGamePlugin plugin)
|
||||
{
|
||||
MapPanel = mapPanel;
|
||||
Plugin = plugin;
|
||||
Map = map;
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace MobiusEditor.Interface
|
||||
|
||||
void New(string theater);
|
||||
|
||||
IEnumerable<string> Load(string path, FileType fileType);
|
||||
IEnumerable<string> Load(string path, FileType fileType, out bool modified);
|
||||
|
||||
bool Save(string path, FileType fileType);
|
||||
|
||||
|
@ -5,17 +5,18 @@ namespace MobiusEditor.Interface
|
||||
[Flags]
|
||||
public enum ToolType
|
||||
{
|
||||
None = 0,
|
||||
Map = 1 << 0,
|
||||
Smudge = 1 << 1,
|
||||
Overlay = 1 << 2,
|
||||
Terrain = 1 << 3,
|
||||
Infantry = 1 << 4,
|
||||
Unit = 1 << 5,
|
||||
Building = 1 << 6,
|
||||
Resources = 1 << 7,
|
||||
Wall = 1 << 8,
|
||||
Waypoint = 1 << 9,
|
||||
CellTrigger = 1 << 10
|
||||
None = 0,
|
||||
Map = 1 << 0,
|
||||
Smudge = 1 << 1,
|
||||
Overlay = 1 << 2,
|
||||
Terrain = 1 << 3,
|
||||
Infantry = 1 << 4,
|
||||
Unit = 1 << 5,
|
||||
Building = 1 << 6,
|
||||
Resources = 1 << 7,
|
||||
Wall = 1 << 8,
|
||||
Waypoint = 1 << 9,
|
||||
CellTrigger = 1 << 10,
|
||||
Select = 1 << 11
|
||||
}
|
||||
}
|
||||
|
55
CnCTDRAMapEditor/MainForm.Designer.cs
generated
55
CnCTDRAMapEditor/MainForm.Designer.cs
generated
@ -68,6 +68,8 @@ namespace MobiusEditor
|
||||
this.settingsTriggersMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolsPowerMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolsStorageMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolsRandomizeTilesMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolsExportImageMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@ -112,8 +114,8 @@ namespace MobiusEditor
|
||||
this.wallsToolStripButton = new MobiusEditor.Controls.ViewToolStripButton();
|
||||
this.waypointsToolStripButton = new MobiusEditor.Controls.ViewToolStripButton();
|
||||
this.cellTriggersToolStripButton = new MobiusEditor.Controls.ViewToolStripButton();
|
||||
this.selectToolStripButton = new MobiusEditor.Controls.ViewToolStripButton();
|
||||
this.mapPanel = new MobiusEditor.Controls.MapPanel();
|
||||
this.toolsStorageMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mainMenuStrip.SuspendLayout();
|
||||
this.mainStatusStrip.SuspendLayout();
|
||||
this.mainToolStrip.SuspendLayout();
|
||||
@ -131,7 +133,7 @@ namespace MobiusEditor
|
||||
this.developerToolStripMenuItem});
|
||||
this.mainMenuStrip.Location = new System.Drawing.Point(0, 0);
|
||||
this.mainMenuStrip.Name = "mainMenuStrip";
|
||||
this.mainMenuStrip.Size = new System.Drawing.Size(1027, 24);
|
||||
this.mainMenuStrip.Size = new System.Drawing.Size(1008, 24);
|
||||
this.mainMenuStrip.TabIndex = 1;
|
||||
this.mainMenuStrip.Text = "menuStrip1";
|
||||
//
|
||||
@ -302,6 +304,7 @@ namespace MobiusEditor
|
||||
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.toolsPowerMenuItem,
|
||||
this.toolsStorageMenuItem,
|
||||
this.toolsRandomizeTilesMenuItem,
|
||||
this.toolsExportImageMenuItem});
|
||||
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
|
||||
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(46, 20);
|
||||
@ -315,6 +318,20 @@ namespace MobiusEditor
|
||||
this.toolsPowerMenuItem.Text = "&Power Balance...";
|
||||
this.toolsPowerMenuItem.Click += new System.EventHandler(this.ToolsPowerMenuItem_Click);
|
||||
//
|
||||
// toolsStorageMenuItem
|
||||
//
|
||||
this.toolsStorageMenuItem.Name = "toolsStorageMenuItem";
|
||||
this.toolsStorageMenuItem.Size = new System.Drawing.Size(204, 22);
|
||||
this.toolsStorageMenuItem.Text = "Silo Storage...";
|
||||
this.toolsStorageMenuItem.Click += new System.EventHandler(this.ToolsStorageMenuItem_Click);
|
||||
//
|
||||
// toolsRandomizeTilesMenuItem
|
||||
//
|
||||
this.toolsRandomizeTilesMenuItem.Name = "toolsRandomizeTilesMenuItem";
|
||||
this.toolsRandomizeTilesMenuItem.Size = new System.Drawing.Size(204, 22);
|
||||
this.toolsRandomizeTilesMenuItem.Text = "Re-randomize tiles";
|
||||
this.toolsRandomizeTilesMenuItem.Click += new System.EventHandler(this.ToolsRandomizeTilesMenuItem_Click);
|
||||
//
|
||||
// toolsExportImageMenuItem
|
||||
//
|
||||
this.toolsExportImageMenuItem.Name = "toolsExportImageMenuItem";
|
||||
@ -572,10 +589,10 @@ namespace MobiusEditor
|
||||
this.toolStatusLabel,
|
||||
this.cellStatusLabel,
|
||||
this.copyrightStatusLabel});
|
||||
this.mainStatusStrip.Location = new System.Drawing.Point(0, 527);
|
||||
this.mainStatusStrip.Location = new System.Drawing.Point(0, 539);
|
||||
this.mainStatusStrip.Name = "mainStatusStrip";
|
||||
this.mainStatusStrip.Padding = new System.Windows.Forms.Padding(2, 0, 14, 0);
|
||||
this.mainStatusStrip.Size = new System.Drawing.Size(1027, 22);
|
||||
this.mainStatusStrip.Size = new System.Drawing.Size(1008, 22);
|
||||
this.mainStatusStrip.TabIndex = 2;
|
||||
this.mainStatusStrip.Text = "statusStrip1";
|
||||
//
|
||||
@ -594,7 +611,7 @@ namespace MobiusEditor
|
||||
// copyrightStatusLabel
|
||||
//
|
||||
this.copyrightStatusLabel.Name = "copyrightStatusLabel";
|
||||
this.copyrightStatusLabel.Size = new System.Drawing.Size(1007, 17);
|
||||
this.copyrightStatusLabel.Size = new System.Drawing.Size(988, 17);
|
||||
this.copyrightStatusLabel.Spring = true;
|
||||
this.copyrightStatusLabel.Text = "©2020 Electronic Arts Inc.";
|
||||
this.copyrightStatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
@ -613,11 +630,12 @@ namespace MobiusEditor
|
||||
this.resourcesToolStripButton,
|
||||
this.wallsToolStripButton,
|
||||
this.waypointsToolStripButton,
|
||||
this.cellTriggersToolStripButton});
|
||||
this.cellTriggersToolStripButton,
|
||||
this.selectToolStripButton});
|
||||
this.mainToolStrip.Location = new System.Drawing.Point(0, 24);
|
||||
this.mainToolStrip.Name = "mainToolStrip";
|
||||
this.mainToolStrip.Padding = new System.Windows.Forms.Padding(0, 0, 2, 0);
|
||||
this.mainToolStrip.Size = new System.Drawing.Size(1027, 31);
|
||||
this.mainToolStrip.Size = new System.Drawing.Size(1008, 31);
|
||||
this.mainToolStrip.TabIndex = 3;
|
||||
this.mainToolStrip.Text = "toolStrip1";
|
||||
this.mainToolStrip.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mainToolStrip_MouseMove);
|
||||
@ -732,6 +750,16 @@ namespace MobiusEditor
|
||||
this.cellTriggersToolStripButton.ToolType = MobiusEditor.Interface.ToolType.CellTrigger;
|
||||
this.cellTriggersToolStripButton.Click += new System.EventHandler(this.mainToolStripButton_Click);
|
||||
//
|
||||
// selectToolStripButton
|
||||
//
|
||||
this.selectToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject("selectToolStripButton.Image")));
|
||||
this.selectToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.selectToolStripButton.Name = "selectToolStripButton";
|
||||
this.selectToolStripButton.Size = new System.Drawing.Size(66, 28);
|
||||
this.selectToolStripButton.Text = "Select";
|
||||
this.selectToolStripButton.ToolType = MobiusEditor.Interface.ToolType.Select;
|
||||
this.selectToolStripButton.Visible = false;
|
||||
//
|
||||
// mapPanel
|
||||
//
|
||||
this.mapPanel.AllowDrop = true;
|
||||
@ -743,7 +771,7 @@ namespace MobiusEditor
|
||||
this.mapPanel.MaxZoom = 8D;
|
||||
this.mapPanel.MinZoom = 1D;
|
||||
this.mapPanel.Name = "mapPanel";
|
||||
this.mapPanel.Size = new System.Drawing.Size(1027, 472);
|
||||
this.mapPanel.Size = new System.Drawing.Size(1008, 484);
|
||||
this.mapPanel.SmoothScale = false;
|
||||
this.mapPanel.TabIndex = 4;
|
||||
this.mapPanel.Zoom = 1D;
|
||||
@ -752,18 +780,11 @@ namespace MobiusEditor
|
||||
this.mapPanel.DragEnter += new System.Windows.Forms.DragEventHandler(this.MapPanel_DragEnter);
|
||||
this.mapPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MapPanel_MouseMove);
|
||||
//
|
||||
// toolsStorageMenuItem
|
||||
//
|
||||
this.toolsStorageMenuItem.Name = "toolsStorageMenuItem";
|
||||
this.toolsStorageMenuItem.Size = new System.Drawing.Size(204, 22);
|
||||
this.toolsStorageMenuItem.Text = "Silo Storage...";
|
||||
this.toolsStorageMenuItem.Click += new System.EventHandler(this.ToolsStorageMenuItem_Click);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1027, 549);
|
||||
this.ClientSize = new System.Drawing.Size(1008, 561);
|
||||
this.Controls.Add(this.mapPanel);
|
||||
this.Controls.Add(this.mainToolStrip);
|
||||
this.Controls.Add(this.mainStatusStrip);
|
||||
@ -857,6 +878,8 @@ namespace MobiusEditor
|
||||
private System.Windows.Forms.ToolStripMenuItem viewIndicatorsCellTriggersMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem editClearUndoRedoMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolsStorageMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolsRandomizeTilesMenuItem;
|
||||
private Controls.ViewToolStripButton selectToolStripButton;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,8 @@ namespace MobiusEditor
|
||||
resourcesToolStripButton,
|
||||
wallsToolStripButton,
|
||||
waypointsToolStripButton,
|
||||
cellTriggersToolStripButton
|
||||
cellTriggersToolStripButton,
|
||||
selectToolStripButton,
|
||||
};
|
||||
mru = new MRU("Software\\Petroglyph\\CnCRemasteredEditor", 10, fileRecentFilesMenuItem);
|
||||
mru.FileSelected += Mru_FileSelected;
|
||||
@ -152,16 +153,23 @@ namespace MobiusEditor
|
||||
|
||||
private void SetTitle()
|
||||
{
|
||||
//MessageBox.Show("setting title");
|
||||
string file = filename;
|
||||
if (plugin != null && file == null)
|
||||
{
|
||||
file = "Untitled" + (plugin.GameType == GameType.TiberianDawn ? ".ini" : ".mpr");
|
||||
}
|
||||
const string noname = "Untitled";
|
||||
String mainTitle = GetProgramVersionTitle();
|
||||
if (file != null)
|
||||
if (plugin != null)
|
||||
{
|
||||
this.Text = string.Format("{0} - {1}{2}", mainTitle, file, plugin != null && plugin.Dirty ? "*" : String.Empty);
|
||||
string mapName = plugin.Map.BasicSection.Name;
|
||||
if (String.IsNullOrEmpty(mapName))
|
||||
{
|
||||
if (filename != null)
|
||||
{
|
||||
mapName = Path.GetFileName(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
mapName = noname;
|
||||
}
|
||||
}
|
||||
this.Text = string.Format("{0} - {1} {2}", mainTitle, mapName, plugin != null && plugin.Dirty ? "*" : String.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -202,60 +210,48 @@ namespace MobiusEditor
|
||||
|
||||
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
||||
{
|
||||
if (keyData == Keys.Q)
|
||||
OemScanCode sc = Keyboard.GetScanCode(msg);
|
||||
if ((keyData & (Keys.Shift | Keys.Control | Keys.Alt)) == Keys.None)
|
||||
{
|
||||
mapToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.W)
|
||||
{
|
||||
smudgeToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.E)
|
||||
{
|
||||
overlayToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.R)
|
||||
{
|
||||
terrainToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.T)
|
||||
{
|
||||
infantryToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.Y)
|
||||
{
|
||||
unitToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.A)
|
||||
{
|
||||
buildingToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.S)
|
||||
{
|
||||
resourcesToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.D)
|
||||
{
|
||||
wallsToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.F)
|
||||
{
|
||||
waypointsToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
else if (keyData == Keys.G)
|
||||
{
|
||||
cellTriggersToolStripButton.PerformClick();
|
||||
return true;
|
||||
switch (sc)
|
||||
{
|
||||
case OemScanCode.Q:
|
||||
mapToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.W:
|
||||
smudgeToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.E:
|
||||
overlayToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.R:
|
||||
terrainToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.T:
|
||||
infantryToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.Y:
|
||||
unitToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.A:
|
||||
buildingToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.S:
|
||||
resourcesToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.D:
|
||||
wallsToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.F:
|
||||
waypointsToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.G:
|
||||
cellTriggersToolStripButton.PerformClick();
|
||||
return true;
|
||||
case OemScanCode.H:
|
||||
selectToolStripButton.PerformClick();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (keyData == (Keys.Control | Keys.Z))
|
||||
{
|
||||
@ -518,7 +514,7 @@ namespace MobiusEditor
|
||||
{
|
||||
if (url.CanUndo)
|
||||
{
|
||||
url.Undo(new UndoRedoEventArgs(mapPanel, plugin.Map));
|
||||
url.Undo(new UndoRedoEventArgs(mapPanel, plugin));
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,7 +522,7 @@ namespace MobiusEditor
|
||||
{
|
||||
if (url.CanRedo)
|
||||
{
|
||||
url.Redo(new UndoRedoEventArgs(mapPanel, plugin.Map));
|
||||
url.Redo(new UndoRedoEventArgs(mapPanel, plugin));
|
||||
}
|
||||
}
|
||||
|
||||
@ -546,27 +542,31 @@ namespace MobiusEditor
|
||||
}
|
||||
bool expansionEnabled = plugin.Map.BasicSection.ExpansionEnabled;
|
||||
bool rulesChanged = false;
|
||||
var basicSettings = new PropertyTracker<BasicSection>(plugin.Map.BasicSection);
|
||||
var briefingSettings = new PropertyTracker<BriefingSection>(plugin.Map.BriefingSection);
|
||||
PropertyTracker<BasicSection> basicSettings = new PropertyTracker<BasicSection>(plugin.Map.BasicSection);
|
||||
PropertyTracker<BriefingSection> briefingSettings = new PropertyTracker<BriefingSection>(plugin.Map.BriefingSection);
|
||||
string extraIniText = (plugin.GameType == GameType.RedAlert ? plugin.ExtraIniText : String.Empty).Trim();
|
||||
var houseSettingsTrackers = plugin.Map.Houses.ToDictionary(h => h, h => new PropertyTracker<House>(h));
|
||||
Dictionary<House, PropertyTracker<House>> houseSettingsTrackers = plugin.Map.Houses.ToDictionary(h => h, h => new PropertyTracker<House>(h));
|
||||
using (MapSettingsDialog msd = new MapSettingsDialog(plugin, basicSettings, briefingSettings, houseSettingsTrackers, extraIniText))
|
||||
{
|
||||
msd.StartPosition = FormStartPosition.CenterParent;
|
||||
if (msd.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
bool hasChanges = basicSettings.HasChanges || briefingSettings.HasChanges;
|
||||
basicSettings.Commit();
|
||||
briefingSettings.Commit();
|
||||
foreach (var houseSettingsTracker in houseSettingsTrackers.Values)
|
||||
{
|
||||
if (houseSettingsTracker.HasChanges)
|
||||
hasChanges = true;
|
||||
houseSettingsTracker.Commit();
|
||||
}
|
||||
if (plugin.GameType == GameType.RedAlert && !extraIniText.Equals(msd.ExtraIniText, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
plugin.ExtraIniText = msd.ExtraIniText;
|
||||
rulesChanged = true;
|
||||
hasChanges = true;
|
||||
}
|
||||
plugin.Dirty = true;
|
||||
plugin.Dirty = hasChanges;
|
||||
}
|
||||
}
|
||||
if (rulesChanged || (expansionEnabled && !plugin.Map.BasicSection.ExpansionEnabled))
|
||||
@ -679,6 +679,15 @@ namespace MobiusEditor
|
||||
}
|
||||
}
|
||||
|
||||
private void ToolsRandomizeTilesMenuItem_Click(Object sender, EventArgs e)
|
||||
{
|
||||
if (plugin != null)
|
||||
{
|
||||
String feedback = TemplateTool.RandomizeTiles(plugin, mapPanel, url);
|
||||
MessageBox.Show(feedback, GetProgramVersionTitle());
|
||||
}
|
||||
}
|
||||
|
||||
private void ToolsExportImage_Click(Object sender, EventArgs e)
|
||||
{
|
||||
if (plugin == null)
|
||||
@ -761,10 +770,11 @@ namespace MobiusEditor
|
||||
(mapPoint.X * Globals.PixelWidth / Globals.MapTileWidth) % Globals.PixelWidth,
|
||||
(mapPoint.Y * Globals.PixelHeight / Globals.MapTileHeight) % Globals.PixelHeight
|
||||
);
|
||||
var i = InfantryGroup.ClosestStoppingTypes(subPixel).Cast<int>().First();
|
||||
if (infantryGroup.Infantry[i] != null)
|
||||
InfantryStoppingType i = InfantryGroup.ClosestStoppingTypes(subPixel).First();
|
||||
Infantry inf = infantryGroup.Infantry[(int)i];
|
||||
if (inf != null)
|
||||
{
|
||||
sb.AppendFormat(", Infantry = {0}", infantryGroup.Infantry[i].Type.DisplayName);
|
||||
sb.AppendFormat(", Infantry = {0} ({1})", inf.Type.DisplayName, InfantryGroup.GetStoppingTypeName(i));
|
||||
}
|
||||
}
|
||||
var unit = plugin.Map.Technos[location] as Unit;
|
||||
@ -938,9 +948,12 @@ namespace MobiusEditor
|
||||
break;
|
||||
}
|
||||
string[] errors;
|
||||
bool modifiedByLoad;
|
||||
try
|
||||
{
|
||||
errors = plugin.Load(loadFilename, fileType).ToArray();
|
||||
// Simply being flagged as single play no longer flags maps as "modified by the loading process",
|
||||
// to make it simpler to open classic maps and examine them without getting a save prompt on close.
|
||||
errors = plugin.Load(loadFilename, fileType, out modifiedByLoad).ToArray();
|
||||
LoadIcons(plugin);
|
||||
if (errors.Length > 0)
|
||||
{
|
||||
@ -967,11 +980,12 @@ namespace MobiusEditor
|
||||
mapPanel.MapImage = plugin.MapImage;
|
||||
filename = loadFilename;
|
||||
loadedFileType = fileType;
|
||||
plugin.Dirty = errors != null && errors.Length > 0;
|
||||
plugin.Dirty = modifiedByLoad;
|
||||
url.Clear();
|
||||
ClearAllTools();
|
||||
RefreshAvailableTools();
|
||||
RefreshActiveTool();
|
||||
SetTitle();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1097,6 +1111,7 @@ namespace MobiusEditor
|
||||
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;
|
||||
availableToolTypes |= ToolType.Select;
|
||||
}
|
||||
foreach (var toolStripButton in viewToolStripButtons)
|
||||
{
|
||||
@ -1216,6 +1231,11 @@ namespace MobiusEditor
|
||||
toolDialog = new CellTriggersToolDialog(this);
|
||||
}
|
||||
break;
|
||||
case ToolType.Select:
|
||||
{
|
||||
toolDialog = null; // new SelectToolDialog(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (toolDialog != null)
|
||||
{
|
||||
@ -1231,6 +1251,7 @@ namespace MobiusEditor
|
||||
if (toolDialog != null)
|
||||
{
|
||||
activeToolForm = (Form)toolDialog;
|
||||
// Creates the actual Tool class
|
||||
toolDialog.Initialize(mapPanel, active, toolStatusLabel, mouseToolTip, plugin, url);
|
||||
activeTool = toolDialog.GetTool();
|
||||
activeToolForm.ResizeEnd -= ActiveToolForm_ResizeEnd;
|
||||
@ -1630,7 +1651,10 @@ namespace MobiusEditor
|
||||
|
||||
private void mainToolStrip_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
mainToolStrip.Focus();
|
||||
if (Form.ActiveForm != null)
|
||||
{
|
||||
mainToolStrip.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void MainForm_Shown(object sender, System.EventArgs e)
|
||||
@ -1757,9 +1781,20 @@ namespace MobiusEditor
|
||||
LoadNewIcon(wallsToolStripButton, wall?.Thumbnail, plugin, 8);
|
||||
LoadNewIcon(waypointsToolStripButton, waypoint?.Image, plugin, 9);
|
||||
LoadNewIcon(cellTriggersToolStripButton, cellTrigger?.Image, plugin, 10);
|
||||
// The Texture manager returns a clone of its own cached image. The Tileset manager caches those clones,
|
||||
// and is responsible for their cleanup, but if we use it directly it needs to be disposed.
|
||||
// Icon: chrono cursor from TEXTURES_SRGB.MEG
|
||||
using (Bitmap select = Globals.TheTextureManager.GetTexture(@"DATA\ART\TEXTURES\SRGB\ICON_SELECT_GREEN_04.DDS", null, false).Item1)
|
||||
{
|
||||
LoadNewIcon(selectToolStripButton, select, plugin, 11, false);
|
||||
}
|
||||
}
|
||||
private void LoadNewIcon(ViewToolStripButton button, Bitmap image, IGamePlugin plugin, int index)
|
||||
{
|
||||
LoadNewIcon(button, image, plugin, index, true);
|
||||
}
|
||||
|
||||
private void LoadNewIcon(ViewToolStripButton button, Bitmap image, IGamePlugin plugin, int index)
|
||||
private void LoadNewIcon(ViewToolStripButton button, Bitmap image, IGamePlugin plugin, int index, bool crop)
|
||||
{
|
||||
if (image == null || plugin == null)
|
||||
{
|
||||
@ -1781,7 +1816,7 @@ namespace MobiusEditor
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle opaqueBounds = TextureManager.CalculateOpaqueBounds(image);
|
||||
Rectangle opaqueBounds = crop ? TextureManager.CalculateOpaqueBounds(image) : new Rectangle(0, 0, image.Width, image.Height);
|
||||
Bitmap img = image.FitToBoundingBox(opaqueBounds, 24, 24, Color.Transparent);
|
||||
theaterIcons[id] = img;
|
||||
button.Image = img;
|
||||
|
@ -293,6 +293,21 @@
|
||||
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
|
||||
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
|
||||
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="selectToolStripButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
|
||||
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
|
||||
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
|
||||
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
|
||||
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
|
||||
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
|
||||
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
|
||||
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
|
||||
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
|
||||
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
|
@ -14,15 +14,26 @@
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
using MobiusEditor.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MobiusEditor.Model
|
||||
{
|
||||
public class PercentageTypeConverter : TypeConverter
|
||||
{
|
||||
|
||||
bool addPercentageSign;
|
||||
|
||||
public PercentageTypeConverter()
|
||||
{
|
||||
addPercentageSign = false;
|
||||
}
|
||||
|
||||
public PercentageTypeConverter(bool withSign)
|
||||
{
|
||||
addPercentageSign = withSign;
|
||||
}
|
||||
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
return (context is MapContext) && (sourceType == typeof(string));
|
||||
@ -39,9 +50,11 @@ namespace MobiusEditor.Model
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var mapContext = context as MapContext;
|
||||
return mapContext.FractionalPercentages ? (percent / 100M).ToString("D2") : percent.ToString();
|
||||
string retVal = mapContext != null && mapContext.FractionalPercentages ? (percent / 100M).ToString("D2") : percent.ToString();
|
||||
if (addPercentageSign)
|
||||
retVal += "%";
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
@ -50,9 +63,11 @@ namespace MobiusEditor.Model
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
str = str.Trim();
|
||||
var mapContext = context as MapContext;
|
||||
if (mapContext.FractionalPercentages && str.Contains("."))
|
||||
if (str.EndsWith("%"))
|
||||
str = str.Substring(0, str.Length - 1);
|
||||
if (mapContext != null && mapContext.FractionalPercentages && str.Contains("."))
|
||||
{
|
||||
if (!decimal.TryParse(str, out decimal percent))
|
||||
{
|
||||
@ -71,10 +86,8 @@ namespace MobiusEditor.Model
|
||||
}
|
||||
}
|
||||
|
||||
public class BasicSection : INotifyPropertyChanged
|
||||
public class BasicSection : NotifiableIniSection
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private string name;
|
||||
[DefaultValue(null)]
|
||||
public string Name { get => name; set => SetField(ref name, value); }
|
||||
@ -151,18 +164,5 @@ namespace MobiusEditor.Model
|
||||
private bool soloMission;
|
||||
[DefaultValue(false)]
|
||||
public bool SoloMission { get => soloMission; set => SetField(ref soloMission, value); }
|
||||
|
||||
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(field, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
field = value;
|
||||
OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MobiusEditor.Model
|
||||
{
|
||||
public class Building : ITechno, ICellOverlapper, ICellOccupier, INotifyPropertyChanged, ICloneable
|
||||
public class Building : ITechno, ICellOverlapper, ICellOccupier, INotifyPropertyChanged, ICloneable, IEquatable<Building>
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
@ -137,5 +137,18 @@ namespace MobiusEditor.Model
|
||||
{
|
||||
return Clone();
|
||||
}
|
||||
|
||||
public Boolean Equals(Building other)
|
||||
{
|
||||
return this.Type == other.Type &&
|
||||
this.House == other.House &&
|
||||
this.Strength == other.Strength &&
|
||||
this.Direction == other.Direction &&
|
||||
this.Trigger == other.Trigger &&
|
||||
this.BasePriority == other.BasePriority &&
|
||||
this.IsPrebuilt == other.IsPrebuilt &&
|
||||
this.Sellable == other.Sellable &&
|
||||
this.Rebuild == other.Rebuild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ namespace MobiusEditor.Model
|
||||
LowerRight = 4
|
||||
}
|
||||
|
||||
public class Infantry : ITechno, INotifyPropertyChanged, ICloneable
|
||||
public class Infantry : ITechno, INotifyPropertyChanged, ICloneable, IEquatable<Infantry>
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
@ -97,10 +97,39 @@ namespace MobiusEditor.Model
|
||||
{
|
||||
return Clone();
|
||||
}
|
||||
|
||||
public Boolean Equals(Infantry other)
|
||||
{
|
||||
return this.Type == other.Type &&
|
||||
this.House == other.House &&
|
||||
this.Strength == other.Strength &&
|
||||
this.Direction == other.Direction &&
|
||||
this.Trigger == other.Trigger &&
|
||||
this.Mission == other.Mission;
|
||||
}
|
||||
}
|
||||
|
||||
public class InfantryGroup : ICellOverlapper, ICellOccupier
|
||||
{
|
||||
private static readonly string[] StoppingTypeNames =
|
||||
{
|
||||
"Center",
|
||||
"Top left",
|
||||
"Top right",
|
||||
"Bottom left",
|
||||
"Bottom right"
|
||||
};
|
||||
|
||||
public static String GetStoppingTypeName(InfantryStoppingType stopLocation)
|
||||
{
|
||||
int index = (int)stopLocation;
|
||||
if (index >= 0 && index < Enum.GetValues(typeof(InfantryStoppingType)).Length)
|
||||
{
|
||||
return StoppingTypeNames[index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static readonly Point[] stoppingLocations = new Point[Globals.NumInfantryStops];
|
||||
|
||||
public Rectangle OverlapBounds => new Rectangle(-1, -1, 3, 3);
|
||||
|
@ -87,7 +87,7 @@ namespace MobiusEditor.Model
|
||||
private IDictionary<MapLayerFlag, ISet<Point>> invalidateLayers = new Dictionary<MapLayerFlag, ISet<Point>>();
|
||||
private bool invalidateOverlappers;
|
||||
|
||||
|
||||
public event EventHandler<MapRefreshEventArgs> RulesChanged;
|
||||
public void NotifyRulesChanges(ISet<Point> refreshPoints)
|
||||
{
|
||||
if (RulesChanged != null)
|
||||
@ -96,7 +96,14 @@ namespace MobiusEditor.Model
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<MapRefreshEventArgs> RulesChanged;
|
||||
public event EventHandler<MapRefreshEventArgs> MapContentsChanged;
|
||||
public void NotifyMapContentsChanged(ISet<Point> refreshPoints)
|
||||
{
|
||||
if (MapContentsChanged != null)
|
||||
{
|
||||
this.MapContentsChanged(this, new MapRefreshEventArgs(refreshPoints));
|
||||
}
|
||||
}
|
||||
|
||||
public readonly BasicSection BasicSection;
|
||||
|
||||
|
@ -13,12 +13,10 @@
|
||||
// GNU General Public License along with permitted additional restrictions
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MobiusEditor.Model
|
||||
{
|
||||
@ -56,7 +54,7 @@ namespace MobiusEditor.Model
|
||||
}
|
||||
}
|
||||
|
||||
public class MapSection : INotifyPropertyChanged
|
||||
public class MapSection : NotifiableIniSection
|
||||
{
|
||||
private readonly int fullWidth;
|
||||
private readonly int fullHeight;
|
||||
@ -86,8 +84,6 @@ namespace MobiusEditor.Model
|
||||
Height = fixedHeight;
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private int x;
|
||||
[DefaultValue(1)]
|
||||
public int X
|
||||
@ -140,18 +136,5 @@ namespace MobiusEditor.Model
|
||||
[TypeConverter(typeof(TheaterTypeConverter))]
|
||||
[DefaultValue(null)]
|
||||
public TheaterType Theater { get => theater; set => SetField(ref theater, value); }
|
||||
|
||||
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(field, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
field = value;
|
||||
OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
25
CnCTDRAMapEditor/Model/NotifiableIniSection.cs
Normal file
25
CnCTDRAMapEditor/Model/NotifiableIniSection.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MobiusEditor.Model
|
||||
{
|
||||
public abstract class NotifiableIniSection : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(field, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
field = value;
|
||||
OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MobiusEditor.Model
|
||||
{
|
||||
public class Smudge: ICellOverlapper, INotifyPropertyChanged, ICloneable
|
||||
public class Smudge: ICellOverlapper, INotifyPropertyChanged, ICloneable, IEquatable<Smudge>
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
private SmudgeType type;
|
||||
@ -65,6 +65,10 @@ namespace MobiusEditor.Model
|
||||
Icon = other.Icon;
|
||||
Tint = other.Tint;
|
||||
}
|
||||
|
||||
|
||||
public Boolean Equals(Smudge other)
|
||||
{
|
||||
return this.Type == other.Type && this.Icon == other.Icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,16 +21,13 @@ using MobiusEditor.Interface;
|
||||
|
||||
namespace MobiusEditor.Model
|
||||
{
|
||||
public class Terrain : ITechno, ICellOverlapper, ICellOccupier, INotifyPropertyChanged, ICloneable
|
||||
public class Terrain : ITechno, ICellOverlapper, ICellOccupier, INotifyPropertyChanged, ICloneable, IEquatable<Terrain>
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private TerrainType type;
|
||||
public TerrainType Type { get => type; set => SetField(ref type, value); }
|
||||
|
||||
private int icon;
|
||||
public int Icon { get => icon; set => SetField(ref icon, value); }
|
||||
|
||||
public Rectangle OverlapBounds => Type.OverlapBounds;
|
||||
|
||||
public bool[,] OccupyMask => Type.OccupyMask;
|
||||
@ -56,7 +53,6 @@ namespace MobiusEditor.Model
|
||||
public void CloneDataFrom(Terrain other)
|
||||
{
|
||||
Type = other.Type;
|
||||
Icon = other.Icon;
|
||||
House = other.House;
|
||||
Strength = other.Strength;
|
||||
Trigger = other.Trigger;
|
||||
@ -79,5 +75,13 @@ namespace MobiusEditor.Model
|
||||
{
|
||||
return Clone();
|
||||
}
|
||||
|
||||
public Boolean Equals(Terrain other)
|
||||
{
|
||||
return this.Type == other.Type &&
|
||||
this.House == other.House &&
|
||||
this.Strength == other.Strength &&
|
||||
this.Trigger == other.Trigger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MobiusEditor.Model
|
||||
{
|
||||
public class Unit : ITechno, ICellOverlapper, ICellOccupier, INotifyPropertyChanged, ICloneable
|
||||
public class Unit : ITechno, ICellOverlapper, ICellOccupier, INotifyPropertyChanged, ICloneable, IEquatable<Unit>
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
@ -83,5 +83,15 @@ namespace MobiusEditor.Model
|
||||
{
|
||||
return Clone();
|
||||
}
|
||||
|
||||
public Boolean Equals(Unit other)
|
||||
{
|
||||
return this.Type == other.Type &&
|
||||
this.House == other.House &&
|
||||
this.Strength == other.Strength &&
|
||||
this.Direction == other.Direction &&
|
||||
this.Mission == other.Mission &&
|
||||
this.Trigger == other.Trigger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -293,10 +293,15 @@ namespace MobiusEditor.RedAlert
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Strip "NewUnitsEnabled" from the Aftermath section.
|
||||
INISection amSection = ini.Sections["Aftermath"];
|
||||
if (amSection != null)
|
||||
{
|
||||
amSection.Keys.Remove("NewUnitsEnabled");
|
||||
}
|
||||
// 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");
|
||||
@ -417,12 +422,14 @@ namespace MobiusEditor.RedAlert
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> Load(string path, FileType fileType)
|
||||
public IEnumerable<string> Load(string path, FileType fileType, out bool modified)
|
||||
{
|
||||
try
|
||||
{
|
||||
isLoading = true;
|
||||
var errors = new List<string>();
|
||||
modified = false;
|
||||
bool forceSingle = false;
|
||||
switch (fileType)
|
||||
{
|
||||
case FileType.INI:
|
||||
@ -433,7 +440,7 @@ namespace MobiusEditor.RedAlert
|
||||
{
|
||||
ini.Parse(reader);
|
||||
}
|
||||
bool forceSingle = SinglePlayRegex.IsMatch(Path.GetFileNameWithoutExtension(path));
|
||||
forceSingle = SinglePlayRegex.IsMatch(Path.GetFileNameWithoutExtension(path));
|
||||
errors.AddRange(LoadINI(ini, forceSingle));
|
||||
}
|
||||
break;
|
||||
@ -458,6 +465,11 @@ namespace MobiusEditor.RedAlert
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
if (errors.Count > 0)
|
||||
{
|
||||
// If only one message is inside the errors, and the "force single" boolean is set, the single message is about that.
|
||||
modified = !forceSingle || errors.Count > 1;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
finally
|
||||
@ -500,17 +512,16 @@ namespace MobiusEditor.RedAlert
|
||||
Map.BasicSection.Player = Map.HouseTypes.Where(t => t.Equals(Map.BasicSection.Player)).FirstOrDefault()?.Name ?? Map.HouseTypes.First().Name;
|
||||
Map.BasicSection.BasePlayer = HouseTypes.GetBasePlayer(Map.BasicSection.Player);
|
||||
bool aftermathEnabled = false;
|
||||
var AftermathSection = ini.Sections.Extract("Aftermath");
|
||||
if (AftermathSection != null)
|
||||
// Don't remove from extra sections.
|
||||
INISection aftermathSection = ini.Sections["Aftermath"];
|
||||
if (aftermathSection != null)
|
||||
{
|
||||
foreach (var (Key, Value) in AftermathSection)
|
||||
{
|
||||
if ("NewUnitsEnabled".Equals(Key, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
aftermathEnabled = Int32.TryParse(Value, out int val) && val == 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var amEnabled = aftermathSection["NewUnitsEnabled"];
|
||||
aftermathEnabled = amEnabled != null && Int32.TryParse(amEnabled, out int val) && val == 1;
|
||||
aftermathSection.Keys.Remove("NewUnitsEnabled");
|
||||
// Remove if empty.
|
||||
if (aftermathSection.Empty)
|
||||
ini.Sections.Remove(aftermathSection.Name);
|
||||
}
|
||||
// Needs to be enabled in advance; it determines which units are valid to have placed on the map.
|
||||
Map.BasicSection.ExpansionEnabled = aftermathEnabled;
|
||||
@ -863,7 +874,6 @@ namespace MobiusEditor.RedAlert
|
||||
Terrain newTerr = new Terrain
|
||||
{
|
||||
Type = terrainType,
|
||||
Icon = terrainType.DisplayIcon,
|
||||
Trigger = Trigger.None
|
||||
};
|
||||
if (Map.Technos.Add(cell, newTerr))
|
||||
@ -1963,11 +1973,37 @@ namespace MobiusEditor.RedAlert
|
||||
|
||||
private void SaveINI(INI ini, FileType fileType, string fileName)
|
||||
{
|
||||
INISection aftermathSection = null;
|
||||
List<INISection> addedExtra = new List<INISection>();
|
||||
if (extraSections != null)
|
||||
{
|
||||
ini.Sections.AddRange(extraSections);
|
||||
foreach (INISection section in extraSections)
|
||||
{
|
||||
if ("Aftermath".Equals(section.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
aftermathSection = section;
|
||||
}
|
||||
else
|
||||
{
|
||||
addedExtra.Add(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
Model.BasicSection basic = Map.BasicSection;
|
||||
// Make new section
|
||||
INISection newAftermathSection = new INISection("Aftermath");
|
||||
newAftermathSection["NewUnitsEnabled"] = basic.ExpansionEnabled ? "1" : "0";
|
||||
if (aftermathSection != null)
|
||||
{
|
||||
// If old section is present, remove NewUnitsEnabled value from it, and copy the remainder into the new one.
|
||||
aftermathSection.Keys.Remove("NewUnitsEnabled");
|
||||
foreach ((string key, string value) in aftermathSection)
|
||||
{
|
||||
newAftermathSection[key] = value;
|
||||
}
|
||||
}
|
||||
ini.Sections.Add(newAftermathSection);
|
||||
ini.Sections.AddRange(addedExtra);
|
||||
char[] cutfrom = { ';', '(' };
|
||||
basic.Intro = GeneralUtils.TrimRemarks(basic.Intro, true, cutfrom);
|
||||
basic.Brief = GeneralUtils.TrimRemarks(basic.Brief, true, cutfrom);
|
||||
@ -1999,8 +2035,6 @@ namespace MobiusEditor.RedAlert
|
||||
INI.WriteSection(new MapContext(Map, false), ini.Sections.Add("Steam"), Map.SteamSection);
|
||||
}
|
||||
ini["Basic"]["NewINIFormat"] = "3";
|
||||
var aftermathSection = ini.Sections.Add("Aftermath");
|
||||
aftermathSection["NewUnitsEnabled"] = basic.ExpansionEnabled ? "1" : "0";
|
||||
var smudgeSection = ini.Sections.Add("SMUDGE");
|
||||
// Flatten multi-cell bibs
|
||||
Dictionary<int, Smudge> resolvedSmudge = new Dictionary<int, Smudge>();
|
||||
|
@ -364,9 +364,9 @@ 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))
|
||||
if (!Globals.TheTilesetManager.GetTileData(theater.Tilesets, tileName, terrain.Type.DisplayIcon, out Tile tile))
|
||||
{
|
||||
Debug.Print(string.Format("Terrain {0} ({1}) not found", tileName, terrain.Icon));
|
||||
Debug.Print(string.Format("Terrain {0} ({1}) not found", tileName, terrain.Type.DisplayIcon));
|
||||
return (Rectangle.Empty, (g) => { });
|
||||
}
|
||||
var tint = terrain.Tint;
|
||||
|
@ -249,12 +249,14 @@ namespace MobiusEditor.TiberianDawn
|
||||
UpdateBasePlayerHouse();
|
||||
}
|
||||
|
||||
public IEnumerable<string> Load(string path, FileType fileType)
|
||||
public IEnumerable<string> Load(string path, FileType fileType, out bool modified)
|
||||
{
|
||||
var ini = new INI();
|
||||
var errors = new List<string>();
|
||||
var iniPath = fileType == FileType.INI ? path : Path.ChangeExtension(path, ".ini");
|
||||
var binPath = fileType == FileType.BIN ? path : Path.ChangeExtension(path, ".bin");
|
||||
modified = false;
|
||||
bool forceSingle = false;
|
||||
switch (fileType)
|
||||
{
|
||||
case FileType.INI:
|
||||
@ -264,7 +266,7 @@ namespace MobiusEditor.TiberianDawn
|
||||
{
|
||||
string iniText = FixRoad2Load(iniReader);
|
||||
ini.Parse(iniText);
|
||||
bool forceSingle = SinglePlayRegex.IsMatch(Path.GetFileNameWithoutExtension(path));
|
||||
forceSingle = SinglePlayRegex.IsMatch(Path.GetFileNameWithoutExtension(path));
|
||||
errors.AddRange(LoadINI(ini, forceSingle));
|
||||
if (binReader.BaseStream.Length != 0x2000)
|
||||
{
|
||||
@ -306,6 +308,11 @@ namespace MobiusEditor.TiberianDawn
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
if (errors.Count > 0)
|
||||
{
|
||||
// If only one message is inside the errors, and the "force single" boolean is set, the single message is about that.
|
||||
modified = !forceSingle || errors.Count > 1;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
@ -625,7 +632,6 @@ namespace MobiusEditor.TiberianDawn
|
||||
Terrain newTerr = new Terrain
|
||||
{
|
||||
Type = terrainType,
|
||||
Icon = terrainType.DisplayIcon,
|
||||
Trigger = tokens[1]
|
||||
};
|
||||
if (Map.Technos.Add(cell, newTerr))
|
||||
|
@ -118,7 +118,7 @@ namespace MobiusEditor.Tools
|
||||
selectedObjectProperties.Closed += (cs, ce) =>
|
||||
{
|
||||
navigationWidget.Refresh();
|
||||
AddUndoRedo(building, preEdit);
|
||||
AddPropertiesUndoRedo(building, preEdit);
|
||||
};
|
||||
building.PropertyChanged += SelectedBuilding_PropertyChanged;
|
||||
selectedObjectProperties.Show(mapPanel, mapPanel.PointToClient(Control.MousePosition));
|
||||
@ -127,11 +127,17 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
private void AddUndoRedo(Building building, Building preEdit)
|
||||
private void AddPropertiesUndoRedo(Building building, Building preEdit)
|
||||
{
|
||||
// building = building in its final edited form. Clone for preservation
|
||||
Building redoBuilding = building.Clone();
|
||||
Building undoBuilding = preEdit;
|
||||
if (redoBuilding.Equals(undoBuilding))
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
building.CloneDataFrom(undoBuilding);
|
||||
@ -141,6 +147,10 @@ namespace MobiusEditor.Tools
|
||||
building.Trigger = Trigger.None;
|
||||
}
|
||||
ev.MapPanel.Invalidate(ev.Map, building);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -151,6 +161,10 @@ namespace MobiusEditor.Tools
|
||||
building.Trigger = Trigger.None;
|
||||
}
|
||||
ev.MapPanel.Invalidate(ev.Map, building);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
@ -249,6 +263,8 @@ namespace MobiusEditor.Tools
|
||||
Dictionary<Point, Smudge> eaten = selectedBuildingEatenSmudge.ToDictionary(p => p.Key, p => p.Value);
|
||||
if (finalLocation.HasValue && finalLocation.Value != selectedBuildingLocation)
|
||||
{
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
Point endLocation = finalLocation.Value;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -268,6 +284,10 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
ev.Map.Buildings.Add(startLocation, toMove);
|
||||
ev.MapPanel.Invalidate(ev.Map, toMove);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -287,6 +307,10 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
ev.Map.Buildings.Add(endLocation, toMove);
|
||||
ev.MapPanel.Invalidate(ev.Map, toMove);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
@ -359,7 +383,6 @@ namespace MobiusEditor.Tools
|
||||
if (map.Technos.CanAdd(newLocation, toMove, toMove.Type.BaseOccupyMask) && map.Buildings.Add(newLocation, toMove))
|
||||
{
|
||||
mapPanel.Invalidate(map, toMove);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -427,6 +450,8 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
mapPanel.Invalidate(map, building);
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.MapPanel.Invalidate(e.Map, building);
|
||||
@ -455,6 +480,10 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
}
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -469,9 +498,12 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
e.MapPanel.Invalidate(e.Map, building);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -501,6 +533,8 @@ namespace MobiusEditor.Tools
|
||||
mapPanel.Invalidate(map, baseBuilding);
|
||||
}
|
||||
}
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.Map.Buildings.Add(actualPoint, building);
|
||||
@ -514,6 +548,10 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
e.MapPanel.Invalidate(e.Map, building);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -529,9 +567,12 @@ namespace MobiusEditor.Tools
|
||||
e.MapPanel.Invalidate(map, bld);
|
||||
}
|
||||
}
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,37 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
EnterPlacementMode();
|
||||
}
|
||||
else if (triggerComboBox.Enabled)
|
||||
{
|
||||
int maxVal = triggerComboBox.Items.Count - 1;
|
||||
int curVal = triggerComboBox.SelectedIndex;
|
||||
int newVal = curVal;
|
||||
switch (e.KeyCode)
|
||||
{
|
||||
case Keys.Home:
|
||||
newVal = 0;
|
||||
break;
|
||||
case Keys.End:
|
||||
newVal = maxVal;
|
||||
break;
|
||||
case Keys.PageDown:
|
||||
newVal = Math.Min(curVal + 10, maxVal);
|
||||
break;
|
||||
case Keys.PageUp:
|
||||
newVal = Math.Max(curVal - 10, 0);
|
||||
break;
|
||||
case Keys.Down:
|
||||
newVal = Math.Min(curVal + 1, maxVal);
|
||||
break;
|
||||
case Keys.Up:
|
||||
newVal = Math.Max(curVal - 1, 0);
|
||||
break;
|
||||
}
|
||||
if (curVal != newVal)
|
||||
{
|
||||
triggerComboBox.SelectedIndex = newVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CellTriggersTool_KeyUp(object sender, KeyEventArgs e)
|
||||
@ -173,7 +204,6 @@ namespace MobiusEditor.Tools
|
||||
map.CellTriggers[cell] = cellTrigger;
|
||||
redoCellTriggers[cell] = cellTrigger;
|
||||
mapPanel.Invalidate();
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -193,7 +223,6 @@ namespace MobiusEditor.Tools
|
||||
map.CellTriggers[cell] = null;
|
||||
redoCellTriggers[cell] = null;
|
||||
mapPanel.Invalidate();
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -232,6 +261,8 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void CommitChange()
|
||||
{
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
var undoCellTriggers2 = new Dictionary<int, CellTrigger>(undoCellTriggers);
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -243,6 +274,10 @@ namespace MobiusEditor.Tools
|
||||
e.Map.CellTriggers[kv.Key] = isValid ? cellTrig : null;
|
||||
}
|
||||
e.MapPanel.Invalidate();
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
var redoCellTriggers2 = new Dictionary<int, CellTrigger>(redoCellTriggers);
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
@ -255,6 +290,10 @@ namespace MobiusEditor.Tools
|
||||
e.Map.CellTriggers[kv.Key] = isValid ? cellTrig : null;
|
||||
}
|
||||
e.MapPanel.Invalidate();
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
undoCellTriggers.Clear();
|
||||
redoCellTriggers.Clear();
|
||||
|
@ -163,7 +163,7 @@ namespace MobiusEditor.Tools
|
||||
selectedObjectProperties.Closed += (cs, ce) =>
|
||||
{
|
||||
navigationWidget.Refresh();
|
||||
AddUndoRedo(infantry, preEdit);
|
||||
AddPropertiesUndoRedo(infantry, preEdit);
|
||||
};
|
||||
infantry.PropertyChanged += SelectedInfantry_PropertyChanged;
|
||||
selectedObjectProperties.Show(mapPanel, mapPanel.PointToClient(Control.MousePosition));
|
||||
@ -173,11 +173,17 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
private void AddUndoRedo(Infantry infantry, Infantry preEdit)
|
||||
private void AddPropertiesUndoRedo(Infantry infantry, Infantry preEdit)
|
||||
{
|
||||
// infantry = infantry in its final edited form. Clone for preservation
|
||||
Infantry redoInf = infantry.Clone();
|
||||
Infantry undoInf = preEdit;
|
||||
if (redoInf.Equals(undoInf))
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
infantry.CloneDataFrom(undoInf);
|
||||
@ -187,6 +193,10 @@ namespace MobiusEditor.Tools
|
||||
infantry.Trigger = Trigger.None;
|
||||
}
|
||||
ev.MapPanel.Invalidate(ev.Map, infantry.InfantryGroup);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -197,6 +207,10 @@ namespace MobiusEditor.Tools
|
||||
infantry.Trigger = Trigger.None;
|
||||
}
|
||||
ev.MapPanel.Invalidate(ev.Map, infantry.InfantryGroup);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
@ -286,7 +300,6 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
selectedInfantry.InfantryGroup = infantryGroup;
|
||||
mapPanel.Invalidate(map, infantryGroup);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
if (infantryGroup == selectedInfantry.InfantryGroup)
|
||||
{
|
||||
@ -338,6 +351,8 @@ namespace MobiusEditor.Tools
|
||||
int finalStop = Array.IndexOf(toMove.InfantryGroup.Infantry, selectedInfantry);
|
||||
if (finalLocation.HasValue && finalStop != -1 && (finalLocation.Value != startLocation || finalStop != startStop))
|
||||
{
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
Point endLocation = finalLocation.Value;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -367,6 +382,10 @@ namespace MobiusEditor.Tools
|
||||
ev.Map.Technos.Remove(finalGroup);
|
||||
}
|
||||
}
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -396,6 +415,10 @@ namespace MobiusEditor.Tools
|
||||
ev.Map.Technos.Remove(startGroup);
|
||||
}
|
||||
}
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
@ -446,6 +469,8 @@ namespace MobiusEditor.Tools
|
||||
infantryGroup.Infantry[placeStop] = infantry;
|
||||
infantry.InfantryGroup = infantryGroup;
|
||||
mapPanel.Invalidate(map, infantryGroup);
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
InfantryGroup placeGroup = ev.Map.Technos[cell] as InfantryGroup;
|
||||
@ -457,7 +482,10 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
ev.Map.Technos.Remove(placeGroup);
|
||||
}
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
@ -475,9 +503,12 @@ namespace MobiusEditor.Tools
|
||||
placeGroup.Infantry[placeStop] = infantry;
|
||||
infantry.InfantryGroup = placeGroup;
|
||||
}
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
plugin.Dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -502,11 +533,12 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
infantryGroup.Infantry[placeStop] = null;
|
||||
mapPanel.Invalidate(map, infantryGroup);
|
||||
plugin.Dirty = true;
|
||||
if (infantryGroup.Infantry.All(x => x == null))
|
||||
{
|
||||
map.Technos.Remove(infantryGroup);
|
||||
}
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
ICellOccupier occupier = ev.Map.Technos[cell];
|
||||
@ -522,6 +554,10 @@ namespace MobiusEditor.Tools
|
||||
placeGroup.Infantry[placeStop] = delInf;
|
||||
delInf.InfantryGroup = placeGroup;
|
||||
}
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -534,7 +570,10 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
ev.Map.Technos.Remove(placeGroup);
|
||||
}
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
|
@ -180,7 +180,6 @@ namespace MobiusEditor.Tools
|
||||
map.Overlay[cell] = overlay;
|
||||
redoOverlays[cell] = overlay;
|
||||
mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1));
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -197,18 +196,16 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
undoOverlays[cell] = map.Overlay[cell];
|
||||
}
|
||||
|
||||
map.Overlay[cell] = null;
|
||||
redoOverlays[cell] = null;
|
||||
|
||||
mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1));
|
||||
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void CommitChange()
|
||||
{
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
var undoOverlays2 = new Dictionary<int, Overlay>(undoOverlays);
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -221,8 +218,11 @@ namespace MobiusEditor.Tools
|
||||
e.Map.Metrics.GetLocation(k, out Point location);
|
||||
return Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1);
|
||||
}));
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
|
||||
var redoOverlays2 = new Dictionary<int, Overlay>(redoOverlays);
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -235,11 +235,13 @@ namespace MobiusEditor.Tools
|
||||
e.Map.Metrics.GetLocation(k, out Point location);
|
||||
return Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1);
|
||||
}));
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
undoOverlays.Clear();
|
||||
redoOverlays.Clear();
|
||||
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
|
||||
@ -249,16 +251,12 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
placementMode = true;
|
||||
|
||||
navigationWidget.MouseoverSize = Size.Empty;
|
||||
|
||||
if (SelectedOverlayType != null)
|
||||
{
|
||||
mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));
|
||||
}
|
||||
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
@ -268,16 +266,12 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
placementMode = false;
|
||||
|
||||
navigationWidget.MouseoverSize = new Size(1, 1);
|
||||
|
||||
if (SelectedOverlayType != null)
|
||||
{
|
||||
mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(navigationWidget.MouseCell, new Size(1, 1)), 1, 1));
|
||||
}
|
||||
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,6 @@ namespace MobiusEditor.Tools
|
||||
var overlay = new Overlay { Type = resourceType, Icon = 0 };
|
||||
map.Overlay[cell] = overlay;
|
||||
redoOverlays[cell] = overlay;
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,7 +213,6 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
map.Overlay[cell] = null;
|
||||
redoOverlays[cell] = null;
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -246,6 +244,8 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void CommitChange()
|
||||
{
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
var undoOverlays2 = new Dictionary<int, Overlay>(undoOverlays);
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -260,6 +260,10 @@ namespace MobiusEditor.Tools
|
||||
rectangle.Inflate(1, 1);
|
||||
return rectangle;
|
||||
}));
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
|
||||
var redoOverlays2 = new Dictionary<int, Overlay>(redoOverlays);
|
||||
@ -276,11 +280,13 @@ namespace MobiusEditor.Tools
|
||||
rectangle.Inflate(1, 1);
|
||||
return rectangle;
|
||||
}));
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
undoOverlays.Clear();
|
||||
redoOverlays.Clear();
|
||||
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ namespace MobiusEditor.Tools
|
||||
selectedSmudgeProperties.Closed += (cs, ce) =>
|
||||
{
|
||||
navigationWidget.Refresh();
|
||||
AddUndoRedo(smudge, preEdit);
|
||||
AddPropertiesUndoRedo(smudge, preEdit);
|
||||
};
|
||||
smudge.PropertyChanged += SelectedSmudge_PropertyChanged;
|
||||
selectedSmudgeProperties.Show(mapPanel, mapPanel.PointToClient(Control.MousePosition));
|
||||
@ -132,21 +132,34 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
private void AddUndoRedo(Smudge smudge, Smudge preEdit)
|
||||
private void AddPropertiesUndoRedo(Smudge smudge, Smudge preEdit)
|
||||
{
|
||||
// building = building in its final edited form. Clone for preservation
|
||||
// smudge = smudge in its final edited form. Clone for preservation
|
||||
Smudge redoSmudge = smudge.Clone();
|
||||
Smudge undoSmudge = preEdit;
|
||||
preEdit = null;
|
||||
if (redoSmudge.Equals(undoSmudge))
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
smudge.CloneDataFrom(undoSmudge);
|
||||
ev.MapPanel.Invalidate(ev.Map, smudge);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
smudge.CloneDataFrom(redoSmudge);
|
||||
ev.MapPanel.Invalidate(ev.Map, smudge);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
@ -286,6 +299,8 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
mapPanel.Invalidate(map, undomap.Keys);
|
||||
mapPanel.Invalidate(map, redomap.Keys);
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.MapPanel.Invalidate(e.Map, undomap.Keys);
|
||||
@ -293,6 +308,10 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
e.Map.Smudge[p] = undomap[p];
|
||||
}
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -300,10 +319,12 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
e.Map.Smudge[p] = redomap[p];
|
||||
}
|
||||
e.MapPanel.Invalidate(e.Map, redomap.Keys);
|
||||
e.MapPanel.Invalidate(e.Map, redomap.Keys); if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
|
||||
private void RemoveSmudge(Point location)
|
||||
@ -318,6 +339,8 @@ namespace MobiusEditor.Tools
|
||||
RestoreNearbySmudge(map, undomap.Keys, redomap);
|
||||
mapPanel.Invalidate(map, undomap.Keys);
|
||||
mapPanel.Invalidate(map, redomap.Keys);
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
// TODO
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -326,6 +349,10 @@ namespace MobiusEditor.Tools
|
||||
e.Map.Smudge[p] = undomap[p];
|
||||
}
|
||||
e.MapPanel.Invalidate(e.Map, undomap.Keys);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -334,9 +361,12 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
e.Map.Smudge[p] = redomap[p];
|
||||
}
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
|
||||
private void RemoveSmudgePoints(Rectangle toClear, Dictionary<Point, Smudge> undomap, Dictionary<Point, Smudge> redomap)
|
||||
|
@ -413,7 +413,6 @@ namespace MobiusEditor.Tools
|
||||
Point startPoint = navigationWidget.MouseCell;
|
||||
dragStartPoint = map.Bounds.Contains(startPoint) ? (Point?)startPoint : null;
|
||||
dragStartBounds = dragBounds;
|
||||
//navigationWidget.CurrentCursor = Cursors.SizeAll;
|
||||
UpdateStatus();
|
||||
}
|
||||
}
|
||||
@ -641,6 +640,37 @@ namespace MobiusEditor.Tools
|
||||
CommitTileChanges(true);
|
||||
}
|
||||
|
||||
public static String RandomizeTiles(IGamePlugin plugin, MapPanel mapPanel, UndoRedoList<UndoRedoEventArgs> url)
|
||||
{
|
||||
Random rnd = new Random();
|
||||
Dictionary<int, Template> undoTemplates = new Dictionary<int, Template>();
|
||||
Dictionary<int, Template> redoTemplates = new Dictionary<int, Template>();
|
||||
TemplateTypeFlag toRandomise = TemplateTypeFlag.RandomCell | TemplateTypeFlag.IsGrouped;
|
||||
Map map = plugin.Map;
|
||||
|
||||
if (map.TemplateTypes.Where(t => t.Theaters == null || t.Theaters.Contains(map.Theater)).All(tm => (tm.Flag & toRandomise) == TemplateTypeFlag.None))
|
||||
{
|
||||
return "This map's theater does not contain randomizable tiles.";
|
||||
}
|
||||
int mapLength = map.Metrics.Length;
|
||||
int mapWidth = map.Metrics.Width;
|
||||
for (int i = 0; i < mapLength; ++i)
|
||||
{
|
||||
Point location = new Point(i / mapWidth, i % mapWidth);
|
||||
TemplateType cur = PickTemplate(map, location, true, out _);
|
||||
if (cur == null || (cur.Flag & TemplateTypeFlag.RandomCell) == TemplateTypeFlag.None)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SetTemplate(map, cur, location, null, undoTemplates, redoTemplates, rnd);
|
||||
}
|
||||
mapPanel.Invalidate(map, redoTemplates.Keys);
|
||||
int count = undoTemplates.Count;
|
||||
// This clears the undo/redo lists, so refresh and count needs to be taken first.
|
||||
CommitTileChanges(url, undoTemplates, redoTemplates, plugin);
|
||||
return String.Format("{0} cells replaced.", count);
|
||||
}
|
||||
|
||||
private void MapPanel_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
CommitEdgeDrag();
|
||||
@ -670,6 +700,15 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
ExitAllModes();
|
||||
}
|
||||
CheckBoundsCursor();
|
||||
if (!boundsMode)
|
||||
{
|
||||
mouseTooltip.Hide(mapPanel);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckBoundsCursor()
|
||||
{
|
||||
var cursor = Cursors.Default;
|
||||
if (boundsMode)
|
||||
{
|
||||
@ -692,7 +731,7 @@ namespace MobiusEditor.Tools
|
||||
cursor = Cursors.SizeNWSE;
|
||||
break;
|
||||
case FacingType.None:
|
||||
if (map.Bounds.Contains(navigationWidget.MouseCell) || dragStartPoint.HasValue && dragStartBounds.HasValue)
|
||||
if (map.Bounds.Contains(navigationWidget.MouseCell) || (dragStartPoint.HasValue && dragStartBounds.HasValue))
|
||||
{
|
||||
cursor = Cursors.SizeAll;
|
||||
}
|
||||
@ -705,10 +744,6 @@ namespace MobiusEditor.Tools
|
||||
UpdateTooltip();
|
||||
}
|
||||
}
|
||||
if (!boundsMode)
|
||||
{
|
||||
mouseTooltip.Hide(mapPanel);
|
||||
}
|
||||
}
|
||||
|
||||
private void MouseoverWidget_ClosestMouseCellBorderChanged(object sender, MouseCellChangedEventArgs e)
|
||||
@ -861,7 +896,18 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void SetTemplate(Point location, bool skipInvalidate)
|
||||
{
|
||||
TemplateType selected = SelectedTemplateType;
|
||||
Dictionary<int, Template> addedRedoTemplates = new Dictionary<int, Template>();
|
||||
SetTemplate(map, SelectedTemplateType, location, SelectedIcon, undoTemplates, addedRedoTemplates, random);
|
||||
addedRedoTemplates.ToList().ForEach(kv => redoTemplates[kv.Key] = kv.Value);
|
||||
if (!skipInvalidate)
|
||||
{
|
||||
mapPanel.Invalidate(map, addedRedoTemplates.Keys);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetTemplate(Map map, TemplateType selected, Point location, Point? SelectedIcon,
|
||||
Dictionary<int, Template> undoTemplates, Dictionary<int, Template> redoTemplates, Random randomiser)
|
||||
{
|
||||
if (selected == null)
|
||||
{
|
||||
return;
|
||||
@ -882,14 +928,9 @@ namespace MobiusEditor.Tools
|
||||
placeType = map.TemplateTypes.Where(t => t.Name == selected.GroupTiles[icon]).FirstOrDefault();
|
||||
icon = 0;
|
||||
}
|
||||
var template = new Template { Type = placeType, Icon = icon };
|
||||
map.Templates[cell] = template;
|
||||
redoTemplates[cell] = template;
|
||||
if (!skipInvalidate)
|
||||
{
|
||||
mapPanel.Invalidate(map, cell);
|
||||
}
|
||||
plugin.Dirty = true;
|
||||
var placeTemplate = new Template { Type = placeType, Icon = icon };
|
||||
map.Templates[cell] = placeTemplate;
|
||||
redoTemplates[cell] = placeTemplate;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -928,13 +969,13 @@ namespace MobiusEditor.Tools
|
||||
TemplateType placeType = selected;
|
||||
if (isGroup)
|
||||
{
|
||||
int randomType = random.Next(0, selected.NumIcons);
|
||||
int randomType = randomiser.Next(0, selected.NumIcons);
|
||||
placeType = map.TemplateTypes.Where(t => t.Name == selected.GroupTiles[randomType]).FirstOrDefault();
|
||||
placeIcon = 0;
|
||||
}
|
||||
else if (isRandom)
|
||||
{
|
||||
placeIcon = random.Next(0, selected.NumIcons);
|
||||
placeIcon = randomiser.Next(0, selected.NumIcons);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -943,11 +984,6 @@ namespace MobiusEditor.Tools
|
||||
var template = new Template { Type = placeType, Icon = placeIcon };
|
||||
map.Templates[cell] = template;
|
||||
redoTemplates[cell] = template;
|
||||
if (!skipInvalidate)
|
||||
{
|
||||
mapPanel.Invalidate(map, cell);
|
||||
}
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -968,7 +1004,6 @@ namespace MobiusEditor.Tools
|
||||
map.Templates[cell] = null;
|
||||
redoTemplates[cell] = null;
|
||||
mapPanel.Invalidate(map, cell);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1005,7 +1040,6 @@ namespace MobiusEditor.Tools
|
||||
map.Templates[cell] = null;
|
||||
redoTemplates[cell] = null;
|
||||
mapPanel.Invalidate(map, cell);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1069,6 +1103,7 @@ namespace MobiusEditor.Tools
|
||||
mapPanel.Invalidate();
|
||||
UpdateTooltip();
|
||||
UpdateStatus();
|
||||
CheckBoundsCursor();
|
||||
}
|
||||
|
||||
private void ExitAllModes()
|
||||
@ -1208,6 +1243,14 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void PickTemplate(Point location, bool wholeTemplate)
|
||||
{
|
||||
SelectedTemplateType = PickTemplate(map, location, wholeTemplate, out Point? selectedIcon);
|
||||
SelectedIcon = selectedIcon;
|
||||
}
|
||||
|
||||
public static TemplateType PickTemplate(Map map, Point location, bool wholeTemplate, out Point? selectedIcon)
|
||||
{
|
||||
TemplateType picked = null;
|
||||
selectedIcon = null;
|
||||
if (map.Metrics.GetCell(location, out int cell))
|
||||
{
|
||||
var template = map.Templates[cell];
|
||||
@ -1218,18 +1261,18 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
groupOwned = true;
|
||||
string owningType = template.Type.GroupTiles[0];
|
||||
SelectedTemplateType = map.TemplateTypes.Where(t => t.Name.Equals(owningType, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
|
||||
picked = map.TemplateTypes.Where(t => t.Name.Equals(owningType, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedTemplateType = template.Type;
|
||||
picked = template.Type;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedTemplateType = map.TemplateTypes.Where(t => t.Name.Equals("clear1", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
|
||||
picked = map.TemplateTypes.Where(t => t.Name.Equals("clear1", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
|
||||
}
|
||||
TemplateType selected = SelectedTemplateType;
|
||||
TemplateType selected = picked;
|
||||
bool isRandom = (selected.Flag & TemplateTypeFlag.RandomCell) != TemplateTypeFlag.None && selected.NumIcons > 1;
|
||||
if (!wholeTemplate && ((selected.IconWidth * selected.IconHeight) > 1 || isRandom))
|
||||
{
|
||||
@ -1244,13 +1287,14 @@ namespace MobiusEditor.Tools
|
||||
icon = template?.Icon ?? 0;
|
||||
}
|
||||
int width = selected.ThumbnailWidth;
|
||||
SelectedIcon = new Point(icon % width, icon / width);
|
||||
selectedIcon = new Point(icon % width, icon / width);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedIcon = null;
|
||||
selectedIcon = null;
|
||||
}
|
||||
}
|
||||
return picked;
|
||||
}
|
||||
|
||||
private FacingType DetectDragEdge()
|
||||
@ -1331,18 +1375,27 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
var oldBounds = map.Bounds;
|
||||
var newBounds = dragBounds;
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ure)
|
||||
{
|
||||
ure.Map.Bounds = oldBounds;
|
||||
ure.MapPanel.Invalidate();
|
||||
if (ure.Plugin != null)
|
||||
{
|
||||
ure.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ure)
|
||||
{
|
||||
ure.Map.Bounds = newBounds;
|
||||
ure.MapPanel.Invalidate();
|
||||
if (ure.Plugin != null)
|
||||
{
|
||||
ure.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
map.Bounds = newBounds;
|
||||
plugin.Dirty = true;
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
dragEdge = FacingType.None;
|
||||
@ -1354,11 +1407,22 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void CommitTileChanges(bool noCheck)
|
||||
{
|
||||
if ((!noCheck && !placementMode) || (undoTemplates.Count == 0) || (redoTemplates.Count == 0))
|
||||
if (!noCheck && !placementMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CommitTileChanges(this.url, this.undoTemplates, this.redoTemplates, plugin);
|
||||
}
|
||||
|
||||
private static void CommitTileChanges(UndoRedoList<UndoRedoEventArgs> url, Dictionary<int, Template> undoTemplates, Dictionary<int, Template> redoTemplates, IGamePlugin plugin)
|
||||
{
|
||||
if (undoTemplates.Count == 0 || redoTemplates.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var undoTemplates2 = new Dictionary<int, Template>(undoTemplates);
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
foreach (var kv in undoTemplates2)
|
||||
@ -1366,6 +1430,10 @@ namespace MobiusEditor.Tools
|
||||
e.Map.Templates[kv.Key] = kv.Value;
|
||||
}
|
||||
e.MapPanel.Invalidate(e.Map, undoTemplates2.Keys);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
var redoTemplates2 = new Dictionary<int, Template>(redoTemplates);
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
@ -1375,6 +1443,10 @@ namespace MobiusEditor.Tools
|
||||
e.Map.Templates[kv.Key] = kv.Value;
|
||||
}
|
||||
e.MapPanel.Invalidate(e.Map, redoTemplates2.Keys);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
undoTemplates.Clear();
|
||||
redoTemplates.Clear();
|
||||
|
@ -71,7 +71,6 @@ namespace MobiusEditor.Tools
|
||||
mapPanel.Invalidate(map, new Rectangle(navigationWidget.MouseCell, selectedTerrainType.OverlapBounds.Size));
|
||||
}
|
||||
mockTerrain.Type = selectedTerrainType;
|
||||
mockTerrain.Icon = selectedTerrainType.DisplayIcon;
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
}
|
||||
@ -121,7 +120,7 @@ namespace MobiusEditor.Tools
|
||||
selectedTerrainProperties.Closed += (cs, ce) =>
|
||||
{
|
||||
navigationWidget.Refresh();
|
||||
AddUndoRedo(terrain, preEdit);
|
||||
AddPropertiesUndoRedo(terrain, preEdit);
|
||||
};
|
||||
selectedTerrainProperties.Show(mapPanel, mapPanel.PointToClient(Control.MousePosition));
|
||||
}
|
||||
@ -130,30 +129,44 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
private void AddUndoRedo(Terrain terrain, Terrain preEdit)
|
||||
private void AddPropertiesUndoRedo(Terrain terrain, Terrain preEdit)
|
||||
{
|
||||
// terrain = terrain in its final edited form. Clone for preservation
|
||||
Terrain redoUnit = terrain.Clone();
|
||||
Terrain undoUnit = preEdit;
|
||||
Terrain redoTerr = terrain.Clone();
|
||||
Terrain undoTerr = preEdit;
|
||||
if (redoTerr.Equals(undoTerr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
terrain.CloneDataFrom(undoUnit);
|
||||
terrain.CloneDataFrom(undoTerr);
|
||||
if (terrain.Trigger == null || (!Trigger.None.Equals(terrain.Trigger, StringComparison.InvariantCultureIgnoreCase)
|
||||
&& !ev.Map.FilterTerrainTriggers().Any(tr => tr.Name.Equals(terrain.Trigger, StringComparison.InvariantCultureIgnoreCase))))
|
||||
{
|
||||
terrain.Trigger = Trigger.None;
|
||||
}
|
||||
ev.MapPanel.Invalidate(ev.Map, terrain);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
terrain.CloneDataFrom(redoUnit);
|
||||
terrain.CloneDataFrom(redoTerr);
|
||||
if (terrain.Trigger == null || (!Trigger.None.Equals(terrain.Trigger, StringComparison.InvariantCultureIgnoreCase)
|
||||
&& !ev.Map.FilterTerrainTriggers().Any(tr => tr.Name.Equals(terrain.Trigger, StringComparison.InvariantCultureIgnoreCase))))
|
||||
{
|
||||
terrain.Trigger = Trigger.None;
|
||||
}
|
||||
ev.MapPanel.Invalidate(ev.Map, terrain);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
@ -225,12 +238,18 @@ namespace MobiusEditor.Tools
|
||||
if (finalLocation.HasValue && finalLocation.Value != startLocation)
|
||||
{
|
||||
Point endLocation = finalLocation.Value;
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
ev.MapPanel.Invalidate(ev.Map, toMove);
|
||||
ev.Map.Technos.Remove(toMove);
|
||||
ev.Map.Technos.Add(startLocation, toMove);
|
||||
ev.MapPanel.Invalidate(ev.Map, toMove);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -238,6 +257,10 @@ namespace MobiusEditor.Tools
|
||||
ev.Map.Technos.Remove(toMove);
|
||||
ev.Map.Technos.Add(endLocation, toMove);
|
||||
ev.MapPanel.Invalidate(ev.Map, toMove);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
@ -275,7 +298,6 @@ namespace MobiusEditor.Tools
|
||||
if (map.Technos.Add(newLocation, toMove))
|
||||
{
|
||||
mapPanel.Invalidate(map, toMove);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -295,19 +317,28 @@ namespace MobiusEditor.Tools
|
||||
var terrain = mockTerrain.Clone();
|
||||
if (map.Technos.Add(location, terrain))
|
||||
{
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
mapPanel.Invalidate(map, terrain);
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.MapPanel.Invalidate(e.Map, location);
|
||||
e.Map.Technos.Remove(terrain);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.Map.Technos.Add(location, terrain);
|
||||
e.MapPanel.Invalidate(e.Map, location);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -318,18 +349,27 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
mapPanel.Invalidate(map, terrain);
|
||||
map.Technos.Remove(location);
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.Map.Technos.Add(location, terrain);
|
||||
e.MapPanel.Invalidate(e.Map, terrain);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.MapPanel.Invalidate(e.Map, terrain);
|
||||
e.Map.Technos.Remove(terrain);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,7 +501,6 @@ namespace MobiusEditor.Tools
|
||||
var terrain = new Terrain
|
||||
{
|
||||
Type = SelectedTerrainType,
|
||||
Icon = SelectedTerrainType.DisplayIcon,
|
||||
Tint = Color.FromArgb(128, Color.White)
|
||||
};
|
||||
previewMap.Technos.Add(location, terrain);
|
||||
|
@ -156,7 +156,7 @@ namespace MobiusEditor.Tools
|
||||
selectedObjectProperties.Closed += (cs, ce) =>
|
||||
{
|
||||
navigationWidget.Refresh();
|
||||
AddUndoRedo(unit, preEdit);
|
||||
AddPropertiesUndoRedo(unit, preEdit);
|
||||
};
|
||||
unit.PropertyChanged += SelectedUnit_PropertyChanged;
|
||||
selectedObjectProperties.Show(mapPanel, mapPanel.PointToClient(Control.MousePosition));
|
||||
@ -165,11 +165,17 @@ namespace MobiusEditor.Tools
|
||||
}
|
||||
}
|
||||
|
||||
private void AddUndoRedo(Unit unit, Unit preEdit)
|
||||
private void AddPropertiesUndoRedo(Unit unit, Unit preEdit)
|
||||
{
|
||||
// unit = unit in its final edited form. Clone for preservation
|
||||
Unit redoUnit = unit.Clone();
|
||||
Unit undoUnit = preEdit;
|
||||
if (redoUnit.Equals(undoUnit))
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
unit.CloneDataFrom(undoUnit);
|
||||
@ -179,6 +185,10 @@ namespace MobiusEditor.Tools
|
||||
unit.Trigger = Trigger.None;
|
||||
}
|
||||
ev.MapPanel.Invalidate(ev.Map, unit);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -189,6 +199,10 @@ namespace MobiusEditor.Tools
|
||||
unit.Trigger = Trigger.None;
|
||||
}
|
||||
ev.MapPanel.Invalidate(ev.Map, unit);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
@ -282,12 +296,18 @@ namespace MobiusEditor.Tools
|
||||
if (finalLocation.HasValue && finalLocation.Value != startLocation)
|
||||
{
|
||||
Point endLocation = finalLocation.Value;
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
ev.MapPanel.Invalidate(ev.Map, toMove);
|
||||
ev.Map.Technos.Remove(toMove);
|
||||
ev.Map.Technos.Add(startLocation, toMove);
|
||||
ev.MapPanel.Invalidate(ev.Map, toMove);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs ev)
|
||||
{
|
||||
@ -295,6 +315,10 @@ namespace MobiusEditor.Tools
|
||||
ev.Map.Technos.Remove(toMove);
|
||||
ev.Map.Technos.Add(endLocation, toMove);
|
||||
ev.MapPanel.Invalidate(ev.Map, toMove);
|
||||
if (ev.Plugin != null)
|
||||
{
|
||||
ev.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
}
|
||||
@ -318,7 +342,6 @@ namespace MobiusEditor.Tools
|
||||
if (map.Technos.Add(e.NewCell, selectedUnit))
|
||||
{
|
||||
mapPanel.Invalidate(map, selectedUnit);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -334,19 +357,28 @@ namespace MobiusEditor.Tools
|
||||
var unit = mockUnit.Clone();
|
||||
if (map.Technos.Add(location, unit))
|
||||
{
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
mapPanel.Invalidate(map, unit);
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.MapPanel.Invalidate(e.Map, unit);
|
||||
e.Map.Technos.Remove(unit);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.Map.Technos.Add(location, unit);
|
||||
e.MapPanel.Invalidate(e.Map, unit);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -357,18 +389,27 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
mapPanel.Invalidate(map, unit);
|
||||
map.Technos.Remove(unit);
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.Map.Technos.Add(location, unit);
|
||||
e.MapPanel.Invalidate(e.Map, unit);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
e.MapPanel.Invalidate(e.Map, unit);
|
||||
e.Map.Technos.Remove(unit);
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
url.Track(undoAction, redoAction);
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,6 +201,12 @@ namespace MobiusEditor.Tools
|
||||
RefreshPreviewPanel();
|
||||
}
|
||||
|
||||
private void Map_MapContentsChanged(Object sender, MapRefreshEventArgs e)
|
||||
{
|
||||
// General event meant to refresh map.
|
||||
mapPanel.Invalidate(map, e.Points);
|
||||
}
|
||||
|
||||
private void MapPanel_PreRender(object sender, RenderEventArgs e)
|
||||
{
|
||||
if ((e.Points != null) && (e.Points.Count == 0))
|
||||
@ -273,10 +279,11 @@ namespace MobiusEditor.Tools
|
||||
/// </summary>
|
||||
public virtual void Activate()
|
||||
{
|
||||
navigationWidget.Activate();
|
||||
this.navigationWidget.Activate();
|
||||
this.mapPanel.PreRender += MapPanel_PreRender;
|
||||
this.mapPanel.PostRender += MapPanel_PostRender;
|
||||
this.map.RulesChanged += this.Map_RulesChanged;
|
||||
this.map.MapContentsChanged += this.Map_MapContentsChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -287,10 +294,11 @@ namespace MobiusEditor.Tools
|
||||
/// </summary>
|
||||
public virtual void Deactivate()
|
||||
{
|
||||
navigationWidget.Deactivate();
|
||||
mapPanel.PreRender -= MapPanel_PreRender;
|
||||
mapPanel.PostRender -= MapPanel_PostRender;
|
||||
this.navigationWidget.Deactivate();
|
||||
this.mapPanel.PreRender -= MapPanel_PreRender;
|
||||
this.mapPanel.PostRender -= MapPanel_PostRender;
|
||||
this.map.RulesChanged -= this.Map_RulesChanged;
|
||||
this.map.MapContentsChanged -= this.Map_MapContentsChanged;
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
|
@ -179,7 +179,6 @@ namespace MobiusEditor.Tools
|
||||
map.Overlay[cell] = overlay;
|
||||
redoOverlays[cell] = overlay;
|
||||
mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1));
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,13 +198,14 @@ namespace MobiusEditor.Tools
|
||||
map.Overlay[cell] = null;
|
||||
redoOverlays[cell] = null;
|
||||
mapPanel.Invalidate(map, Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1));
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CommitChange()
|
||||
{
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
var undoOverlays2 = new Dictionary<int, Overlay>(undoOverlays);
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
@ -218,6 +218,10 @@ namespace MobiusEditor.Tools
|
||||
e.Map.Metrics.GetLocation(k, out Point location);
|
||||
return Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1);
|
||||
}));
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
var redoOverlays2 = new Dictionary<int, Overlay>(redoOverlays);
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
@ -231,6 +235,10 @@ namespace MobiusEditor.Tools
|
||||
e.Map.Metrics.GetLocation(k, out Point location);
|
||||
return Rectangle.Inflate(new Rectangle(location, new Size(1, 1)), 1, 1);
|
||||
}));
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
undoOverlays.Clear();
|
||||
redoOverlays.Clear();
|
||||
|
@ -20,7 +20,6 @@ using MobiusEditor.Render;
|
||||
using MobiusEditor.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
@ -83,6 +82,10 @@ namespace MobiusEditor.Tools
|
||||
{
|
||||
EnterPlacementMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckSelectShortcuts(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void WaypointsTool_KeyUp(object sender, KeyEventArgs e)
|
||||
@ -135,7 +138,6 @@ namespace MobiusEditor.Tools
|
||||
waypointCombo.Items.Clear();
|
||||
waypointCombo.DataSource = wp.ToArray();
|
||||
waypointCombo.SelectedIndex = selected;
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,12 +176,63 @@ namespace MobiusEditor.Tools
|
||||
waypointCombo.Items.Clear();
|
||||
waypointCombo.DataSource = wp.ToArray();
|
||||
waypointCombo.SelectedIndex = waypointIndex;
|
||||
|
||||
plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckSelectShortcuts(KeyEventArgs e)
|
||||
{
|
||||
int maxVal = waypointCombo.Items.Count - 1;
|
||||
int curVal = waypointCombo.SelectedIndex;
|
||||
int? newVal = null;
|
||||
if (Control.ModifierKeys == Keys.Shift)
|
||||
{
|
||||
switch (e.KeyCode)
|
||||
{
|
||||
case (Keys.F):
|
||||
newVal = Enumerable.Range(0, map.Waypoints.Length).Cast<int?>().Where(i => (map.Waypoints[i.Value].Flag & WaypointFlag.Flare) == WaypointFlag.Flare).FirstOrDefault();
|
||||
break;
|
||||
case (Keys.H):
|
||||
newVal = Enumerable.Range(0, map.Waypoints.Length).Cast<int?>().Where(i => (map.Waypoints[i.Value].Flag & WaypointFlag.Home) == WaypointFlag.Home).FirstOrDefault();
|
||||
break;
|
||||
case (Keys.R):
|
||||
newVal = Enumerable.Range(0, map.Waypoints.Length).Cast<int?>().Where(i => (map.Waypoints[i.Value].Flag & WaypointFlag.Reinforce) == WaypointFlag.Reinforce).FirstOrDefault();
|
||||
break;
|
||||
case (Keys.S):
|
||||
newVal = Enumerable.Range(0, map.Waypoints.Length).Cast<int?>().Where(i => (map.Waypoints[i.Value].Flag & WaypointFlag.Special) == WaypointFlag.Special).FirstOrDefault();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (e.KeyCode)
|
||||
{
|
||||
case Keys.Home:
|
||||
newVal = 0;
|
||||
break;
|
||||
case Keys.End:
|
||||
newVal = maxVal;
|
||||
break;
|
||||
case Keys.PageDown:
|
||||
newVal = Math.Min(curVal + 10, maxVal);
|
||||
break;
|
||||
case Keys.PageUp:
|
||||
newVal = Math.Max(curVal - 10, 0);
|
||||
break;
|
||||
case Keys.Down:
|
||||
newVal = Math.Min(curVal + 1, maxVal);
|
||||
break;
|
||||
case Keys.Up:
|
||||
newVal = Math.Max(curVal - 1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newVal.HasValue && curVal != newVal.Value)
|
||||
{
|
||||
waypointCombo.SelectedIndex = newVal.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnterPlacementMode()
|
||||
{
|
||||
if (placementMode)
|
||||
@ -238,17 +291,27 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void CommitChange()
|
||||
{
|
||||
bool origDirtyState = plugin.Dirty;
|
||||
plugin.Dirty = true;
|
||||
var undoWaypoint2 = undoWaypoint;
|
||||
void undoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
undoWaypoint2.Value.waypoint.Cell = undoWaypoint2.Value.cell;
|
||||
mapPanel.Invalidate();
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = origDirtyState;
|
||||
}
|
||||
}
|
||||
var redoWaypoint2 = redoWaypoint;
|
||||
void redoAction(UndoRedoEventArgs e)
|
||||
{
|
||||
redoWaypoint2.Value.waypoint.Cell = redoWaypoint2.Value.cell;
|
||||
mapPanel.Invalidate();
|
||||
if (e.Plugin != null)
|
||||
{
|
||||
e.Plugin.Dirty = true;
|
||||
}
|
||||
}
|
||||
undoWaypoint = null;
|
||||
redoWaypoint = null;
|
||||
@ -302,13 +365,37 @@ namespace MobiusEditor.Tools
|
||||
|
||||
private void UpdateStatus()
|
||||
{
|
||||
WaypointFlag flag = WaypointFlag.None;
|
||||
Waypoint[] wps = map.Waypoints;
|
||||
int wplen = map.Waypoints.Length;
|
||||
for (int i = 0; i < wplen; ++i) {
|
||||
flag |= wps[i].Flag;
|
||||
}
|
||||
List<String> specialKeys = new List<string>();
|
||||
if ((flag & WaypointFlag.Flare) != WaypointFlag.None)
|
||||
{
|
||||
specialKeys.Add("F");
|
||||
}
|
||||
if ((flag & WaypointFlag.Home) != WaypointFlag.None)
|
||||
{
|
||||
specialKeys.Add("H");
|
||||
}
|
||||
if ((flag & WaypointFlag.Reinforce) != WaypointFlag.None)
|
||||
{
|
||||
specialKeys.Add("R");
|
||||
}
|
||||
if ((flag & WaypointFlag.Special) != WaypointFlag.None)
|
||||
{
|
||||
specialKeys.Add("S");
|
||||
}
|
||||
|
||||
if (placementMode)
|
||||
{
|
||||
statusLbl.Text = "Left-Click to set cell waypoint, Right-Click to clear cell waypoint";
|
||||
statusLbl.Text = "Left-Click to set cell waypoint, Right-Click to clear cell waypoint, " + String.Join("/", specialKeys) + " to select a special waypoint";
|
||||
}
|
||||
else
|
||||
{
|
||||
statusLbl.Text = "Shift to enter placement mode, Left-Click or Right-Click to pick cell waypoint";
|
||||
statusLbl.Text = "Shift to enter placement mode, Left-Click or Right-Click to pick cell waypoint, Shift + " + String.Join("/", specialKeys) + " to select a special waypoint";
|
||||
}
|
||||
}
|
||||
|
||||
|
220
CnCTDRAMapEditor/Utility/Keyboard.cs
Normal file
220
CnCTDRAMapEditor/Utility/Keyboard.cs
Normal file
@ -0,0 +1,220 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MobiusEditor.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// List of scan codes for standard 104-key keyboard US English keyboard,
|
||||
/// from https://stackoverflow.com/questions/2569268/net-difference-between-right-shift-and-left-shift-keys
|
||||
/// and https://handmade.network/forums/articles/t/2823-keyboard_inputs_-_scancodes%252C_raw_input%252C_text_input%252C_key_names
|
||||
/// </summary>
|
||||
public enum OemScanCode
|
||||
{
|
||||
Escape = 1,
|
||||
/// <summary>1 !</summary>
|
||||
Number1 = 2,
|
||||
/// <summary>2 @</summary>
|
||||
Number2 = 3,
|
||||
/// <summary>3 #</summary>
|
||||
Number3 = 4,
|
||||
/// <summary>4 $</summary>
|
||||
Number4 = 5,
|
||||
/// <summary>5 %</summary>
|
||||
Number5 = 6,
|
||||
/// <summary>6 ^</summary>
|
||||
Number6 = 7,
|
||||
/// <summary>7 &</summary>
|
||||
Number7 = 8,
|
||||
/// <summary>8 *</summary>
|
||||
Number8 = 9,
|
||||
/// <summary>9 (</summary>
|
||||
Number9 = 0x0A,
|
||||
/// <summary>0 )</summary>
|
||||
Number0 = 0x0B,
|
||||
/// <summary>- _</summary>
|
||||
MinusDash = 0x0C,
|
||||
/// <summary>= +</summary>
|
||||
Equals = 0x0D,
|
||||
Backspace = 0x0E,
|
||||
Tab = 0x0F,
|
||||
Q = 0x10,
|
||||
W = 0x11,
|
||||
E = 0x12,
|
||||
R = 0x13,
|
||||
T = 0x14,
|
||||
Y = 0x15,
|
||||
U = 0x16,
|
||||
I = 0x17,
|
||||
O = 0x18,
|
||||
P = 0x19,
|
||||
/// <summary>[ {</summary>
|
||||
LeftBracket = 0x1A,
|
||||
/// <summary>] }</summary>
|
||||
RightBracket = 0x1B,
|
||||
Enter = 0x1C,
|
||||
LeftControl = 0x1D,
|
||||
A = 0x1E,
|
||||
S = 0x1F,
|
||||
D = 0x20,
|
||||
F = 0x21,
|
||||
G = 0x22,
|
||||
H = 0x23,
|
||||
J = 0x24,
|
||||
K = 0x25,
|
||||
L = 0x26,
|
||||
/// <summary>; :</summary>
|
||||
SemiColon = 0x27,
|
||||
/// <summary>' "</summary>
|
||||
Quotes = 0x28,
|
||||
/// <summary>` ~</summary>
|
||||
BacktickTilde = 0x29,
|
||||
LeftShift = 0x2A,
|
||||
/// <summary>| \</summary>
|
||||
Pipe = 0x2B,
|
||||
Z = 0x2C,
|
||||
X = 0x2D,
|
||||
C = 0x2E,
|
||||
V = 0x2F,
|
||||
B = 0x30,
|
||||
N = 0x31,
|
||||
M = 0x32,
|
||||
/// <summary>, <</summary>
|
||||
Comma = 0x33,
|
||||
/// <summary>. ></summary>
|
||||
Period = 0x34,
|
||||
/// <summary>/ ?</summary>
|
||||
Slash = 0x35,
|
||||
RightShift = 0x36,
|
||||
NumPadAsterisk = 0x37,
|
||||
LeftAlt = 0x38,
|
||||
SpaceBar = 0x39,
|
||||
CapsLock = 0x3A,
|
||||
F1 = 0x3B,
|
||||
F2 = 0x3C,
|
||||
F3 = 0x3D,
|
||||
F4 = 0x3E,
|
||||
F5 = 0x3F,
|
||||
F6 = 0x40,
|
||||
F7 = 0x41,
|
||||
F8 = 0x42,
|
||||
F9 = 0x43,
|
||||
F10 = 0x44,
|
||||
PauseBreak = 0x45,
|
||||
ScrollLock = 0x46,
|
||||
NumPad7 = 0x47,
|
||||
NumPad8 = 0x48,
|
||||
NumPad9 = 0x49,
|
||||
NumPadMinus = 0x4A,
|
||||
NumPad4 = 0x4B,
|
||||
NumPad5 = 0x4C,
|
||||
NumPad6 = 0x4D,
|
||||
NumPadPlus = 0x4E,
|
||||
NumPad1 = 0x4F,
|
||||
NumPad2 = 0x50,
|
||||
NumPad3 = 0x51,
|
||||
NumPad0 = 0x52,
|
||||
NumPadDecimal = 0x53,
|
||||
/// <summary> Alt + print screen. MapVirtualKeyEx( VK_SNAPSHOT, MAPVK_VK_TO_VSC_EX, 0 ) returns scancode 0x54.</summary>
|
||||
AltPrintScreen = 0x54,
|
||||
/// <summary>Key between the left shift and Z.</summary>
|
||||
BracketAngle = 0x56,
|
||||
F11 = 0x57,
|
||||
F12 = 0x58,
|
||||
|
||||
OEM1 = 0x5a, /* VK_OEM_WSCTRL */
|
||||
OEM2 = 0x5b, /* VK_OEM_FINISH */
|
||||
OEM3 = 0x5c, /* VK_OEM_JUMP */
|
||||
EraseEOF = 0x5d,
|
||||
OEM4 = 0x5e, /* VK_OEM_BACKTAB */
|
||||
OEM5 = 0x5f, /* VK_OEM_AUTO */
|
||||
Zoom = 0x62,
|
||||
Help = 0x63,
|
||||
F13 = 0x64,
|
||||
F14 = 0x65,
|
||||
F15 = 0x66,
|
||||
F16 = 0x67,
|
||||
F17 = 0x68,
|
||||
F18 = 0x69,
|
||||
F19 = 0x6a,
|
||||
F20 = 0x6b,
|
||||
F21 = 0x6c,
|
||||
F22 = 0x6d,
|
||||
F23 = 0x6e,
|
||||
OEM6 = 0x6f, /* VK_OEM_PA3 */
|
||||
Katakana = 0x70,
|
||||
OEM7 = 0x71, /* VK_OEM_RESET */
|
||||
//---
|
||||
F24 = 0x76,
|
||||
SBCSChar = 0x77,
|
||||
//---
|
||||
Convert = 0x79,
|
||||
//---
|
||||
Nonconvert = 0x7B, /* VK_OEM_PA1 */
|
||||
//---
|
||||
RControl = 0x11D,
|
||||
NumPadEnter = 0x11C,
|
||||
//---
|
||||
NumPadSlash = 0x135,
|
||||
//---
|
||||
PrintScreen = 0x137,
|
||||
RightAlt = 0x138,
|
||||
//---
|
||||
NumLock = 0x145,
|
||||
//---
|
||||
Home = 0x147,
|
||||
UpArrow = 0x148,
|
||||
PageUp = 0x149,
|
||||
//---
|
||||
LeftArrow = 0x14B,
|
||||
//---
|
||||
RightArrow = 0x14D,
|
||||
//---
|
||||
End = 0x14F,
|
||||
DownArrow = 0x150,
|
||||
PageDown = 0x151,
|
||||
Insert = 0x152,
|
||||
Delete = 0x153,
|
||||
//---
|
||||
LeftWindows = 0x15B,
|
||||
RightWindows = 0x15C,
|
||||
/// <summary>The menu key thingy</summary>
|
||||
Application = 0x15D,
|
||||
}
|
||||
|
||||
public class Keyboard
|
||||
{
|
||||
/// <summary>Shift key</summary>
|
||||
const int VK_SHIFT = 0x10;
|
||||
/// <summary>Control key</summary>
|
||||
const int VK_CONTROL = 0x11;
|
||||
/// <summary>Alt key</summary>
|
||||
const int VK_MENU = 0x12;
|
||||
|
||||
|
||||
public static OemScanCode GetScanCodeFromLParam(int lParam)
|
||||
{
|
||||
return (OemScanCode)((lParam >> 16) & 0x1FF);
|
||||
}
|
||||
|
||||
public static OemScanCode GetScanCode(Message msg)
|
||||
{
|
||||
return GetScanCodeFromLParam((int)msg.LParam);
|
||||
}
|
||||
|
||||
public static bool HasShift(Message msg)
|
||||
{
|
||||
return (int)msg.WParam == VK_SHIFT;
|
||||
}
|
||||
|
||||
public static bool HasControl(Message msg)
|
||||
{
|
||||
return (int)msg.WParam == VK_CONTROL;
|
||||
}
|
||||
|
||||
public static bool HasAlt(Message msg)
|
||||
{
|
||||
return (int)msg.WParam == VK_MENU;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -103,6 +103,8 @@ namespace MobiusEditor.Utility
|
||||
.ToDictionary(k => k.Name, v => v);
|
||||
}
|
||||
|
||||
public bool HasChanges => propertyValues.Count > 0;
|
||||
|
||||
public void Revert() => propertyValues.Clear();
|
||||
|
||||
public void Commit()
|
||||
@ -168,6 +170,25 @@ namespace MobiusEditor.Utility
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TrySetMember(string memberName, object value)
|
||||
{
|
||||
if (!trackableProperties.TryGetValue(memberName, out PropertyInfo property))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Equals(property.GetValue(Object), value))
|
||||
{
|
||||
propertyValues.Remove(memberName);
|
||||
}
|
||||
else
|
||||
{
|
||||
propertyValues[memberName] = value;
|
||||
NotifyPropertyChanged(memberName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void NotifyPropertyChanged(String name)
|
||||
{
|
||||
if (this.PropertyChanged != null)
|
||||
|
13
README.md
13
README.md
@ -332,6 +332,19 @@ These options are all enabled by default, but can be disabled if you wish. Use t
|
||||
* Fixed a crash in the smudge restore system when you delete a smudge or building that is too close to the map edge.
|
||||
* Reduced maximum multiplayer start positions in the editor to 8, since the games apparently can't show more.
|
||||
|
||||
#### v1.4.3.3: [WIP]
|
||||
|
||||
* When your mouse cursor is inside the map bounds and you press [Ctrl] in Map mode to enable bounds editing mode, your cursor will now immediately change to the Move cursor, without requiring any mouse movement.
|
||||
* The status bar at the bottom will now explicitly mention the sub-position of the infantry under the mouse cursor.
|
||||
* When loading a map, if a map's file name identifies it as classic single player mission, this will no longer mark the mission as "modified" by the loading process. This will make it simpler to open classic maps for reference without getting a save prompt on close. Do note that lots of classic maps contain errors in triggers being linked to wrong objects, and the automatic fixes for that **will** still mark the map as modified.
|
||||
* Fixed issues with the editor window getting focused simply by moving the mouse over it. The main window can steal focus from the tool window, but not the other way around.
|
||||
* In Waypoints and Cell Triggers editing mode, the Up, Down, PageUp, PageDown, Home and End keys will now let you go through the dropdown items list. PageUp and PageDown will skip 10 items.
|
||||
* In Waypoints editing mode, pressing [Shift] and a key will select special waypoints: [F]lare, [H]ome, [R]einforce, [S]pecial.
|
||||
* The shortcut keys to select the different editing modes (normally Q, W, E, R, T, Y, A, S, D, F, G) now work on keyboard position, meaning thy will also work in the logical way on on AZERTY keyboards.
|
||||
* Fixed bug where the checked states of the Houses in the Map Settings would reset when changing the "Single-Player" checkbox.
|
||||
* The [Aftermath] section is no longer ignored in the map settings' Rules editor, so Aftermath detail settings can be added. The actual "NewUnitsEnabled" setting in this is ignored, though; toggling the expansion units can only be done in the Basic settings.
|
||||
* Undo/Redo tracking will now also undo the map's modified-status.
|
||||
|
||||
### Possible future features
|
||||
|
||||
Some ideas that might get implemented in the future:
|
||||
|
Loading…
x
Reference in New Issue
Block a user