12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // The Command & Conquer Map Editor and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // The Command & Conquer Map Editor and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- using MobiusEditor.Dialogs;
- using MobiusEditor.Event;
- using MobiusEditor.Interface;
- using MobiusEditor.Model;
- using MobiusEditor.Tools;
- using MobiusEditor.Tools.Dialogs;
- using MobiusEditor.Utility;
- using Steamworks;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Diagnostics;
- using System.Drawing;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- namespace MobiusEditor
- {
- public partial class MainForm : Form
- {
- [Flags]
- private 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
- }
- private static readonly ToolType[] toolTypes;
- private ToolType availableToolTypes = ToolType.None;
- private ToolType activeToolType = ToolType.None;
- private ToolType ActiveToolType
- {
- get => activeToolType;
- set
- {
- var firstAvailableTool = value;
- if ((availableToolTypes & firstAvailableTool) == ToolType.None)
- {
- var otherAvailableToolTypes = toolTypes.Where(t => (availableToolTypes & t) != ToolType.None);
- firstAvailableTool = otherAvailableToolTypes.Any() ? otherAvailableToolTypes.First() : ToolType.None;
- }
- if (activeToolType != firstAvailableTool)
- {
- activeToolType = firstAvailableTool;
- RefreshActiveTool();
- }
- }
- }
- private MapLayerFlag activeLayers;
- public MapLayerFlag ActiveLayers
- {
- get => activeLayers;
- set
- {
- if (activeLayers != value)
- {
- activeLayers = value;
- if (activeTool != null)
- {
- activeTool.Layers = ActiveLayers;
- }
- }
- }
- }
- private ITool activeTool;
- private Form activeToolForm;
- private IGamePlugin plugin;
- private string filename;
- private readonly MRU mru;
- private readonly UndoRedoList<UndoRedoEventArgs> url = new UndoRedoList<UndoRedoEventArgs>();
- private readonly Timer steamUpdateTimer = new Timer();
- static MainForm()
- {
- toolTypes = ((IEnumerable<ToolType>)Enum.GetValues(typeof(ToolType))).Where(t => t != ToolType.None).ToArray();
- }
- public MainForm()
- {
- InitializeComponent();
- mru = new MRU("Software\\Petroglyph\\CnCRemasteredEditor", 10, fileRecentFilesMenuItem);
- mru.FileSelected += Mru_FileSelected;
- foreach (ToolStripButton toolStripButton in mainToolStrip.Items)
- {
- toolStripButton.MouseMove += mainToolStrip_MouseMove;
- }
- #if !DEVELOPER
- fileExportMenuItem.Visible = false;
- developerToolStripMenuItem.Visible = false;
- #endif
- url.Tracked += UndoRedo_Updated;
- url.Undone += UndoRedo_Updated;
- url.Redone += UndoRedo_Updated;
- UpdateUndoRedo();
- steamUpdateTimer.Interval = 500;
- steamUpdateTimer.Tick += SteamUpdateTimer_Tick;
- }
- private void SteamUpdateTimer_Tick(object sender, EventArgs e)
- {
- if (SteamworksUGC.IsInit)
- {
- SteamworksUGC.Service();
- }
- }
- protected override void OnLoad(EventArgs e)
- {
- base.OnLoad(e);
- RefreshAvailableTools();
- UpdateVisibleLayers();
- filePublishMenuItem.Visible = SteamworksUGC.IsInit;
- steamUpdateTimer.Start();
- }
- protected override void OnClosed(EventArgs e)
- {
- base.OnClosed(e);
- steamUpdateTimer.Stop();
- steamUpdateTimer.Dispose();
- }
- protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
- {
- if (keyData == Keys.Q)
- {
- 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;
- }
- else if (keyData == (Keys.Control | Keys.Z))
- {
- if (editUndoMenuItem.Enabled)
- {
- editUndoMenuItem_Click(this, new EventArgs());
- }
- return true;
- }
- else if (keyData == (Keys.Control | Keys.Y))
- {
- if (editRedoMenuItem.Enabled)
- {
- editRedoMenuItem_Click(this, new EventArgs());
- }
- return true;
- }
- return base.ProcessCmdKey(ref msg, keyData);
- }
- private void UpdateUndoRedo()
- {
- editUndoMenuItem.Enabled = url.CanUndo;
- editRedoMenuItem.Enabled = url.CanRedo;
- }
- private void UndoRedo_Updated(object sender, EventArgs e)
- {
- UpdateUndoRedo();
- }
- private void fileNewMenuItem_Click(object sender, EventArgs e)
- {
- if (!PromptSaveMap())
- {
- return;
- }
- NewMapDialog nmd = new NewMapDialog();
- if (nmd.ShowDialog() == DialogResult.OK)
- {
- if (plugin != null)
- {
- plugin.Map.Triggers.CollectionChanged -= Triggers_CollectionChanged;
- plugin.Dispose();
- }
- plugin = null;
- Globals.TheTilesetManager.Reset();
- Globals.TheTextureManager.Reset();
- if (nmd.GameType == GameType.TiberianDawn)
- {
- Globals.TheTeamColorManager.Reset();
- Globals.TheTeamColorManager.Load(@"DATA\XML\CNCTDTEAMCOLORS.XML");
- plugin = new TiberianDawn.GamePlugin();
- plugin.New(nmd.TheaterName);
- }
- else if (nmd.GameType == GameType.RedAlert)
- {
- Globals.TheTeamColorManager.Reset();
- Globals.TheTeamColorManager.Load(@"DATA\XML\CNCRATEAMCOLORS.XML");
- plugin = new RedAlert.GamePlugin();
- plugin.New(nmd.TheaterName);
- }
- if (SteamworksUGC.IsInit)
- {
- plugin.Map.BasicSection.Author = SteamFriends.GetPersonaName();
- }
- plugin.Map.Triggers.CollectionChanged += Triggers_CollectionChanged;
- mapPanel.MapImage = plugin.MapImage;
- filename = null;
- Text = "CnC TDRA Map Editor";
- url.Clear();
- ClearActiveTool();
- RefreshAvailableTools();
- RefreshActiveTool();
- }
- }
- private void fileOpenMenuItem_Click(object sender, EventArgs e)
- {
- if (!PromptSaveMap())
- {
- return;
- }
- var pgmFilter =
- #if DEVELOPER
- "|PGM files (*.pgm)|*.pgm"
- #else
- string.Empty
- #endif
- ;
- OpenFileDialog ofd = new OpenFileDialog
- {
- AutoUpgradeEnabled = false,
- RestoreDirectory = true
- };
- ofd.Filter = "Tiberian Dawn files (*.ini;*.bin)|*.ini;*.bin|Red Alert files (*.mpr)|*.mpr" + pgmFilter + "|All files (*.*)|*.*";
- if (plugin != null)
- {
- switch (plugin.GameType)
- {
- case GameType.TiberianDawn:
- ofd.InitialDirectory = TiberianDawn.Constants.SaveDirectory;
- ofd.FilterIndex = 1;
- break;
- case GameType.RedAlert:
- ofd.InitialDirectory = RedAlert.Constants.SaveDirectory;
- ofd.FilterIndex = 2;
- break;
- }
- }
- else
- {
- ofd.InitialDirectory = Globals.RootSaveDirectory;
- }
- if (ofd.ShowDialog() == DialogResult.OK)
- {
- var fileInfo = new FileInfo(ofd.FileName);
- if (LoadFile(fileInfo.FullName))
- {
- mru.Add(fileInfo);
- }
- else
- {
- mru.Remove(fileInfo);
- MessageBox.Show(string.Format("Error loading {0}.", ofd.FileName), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- }
- }
- private void fileSaveMenuItem_Click(object sender, EventArgs e)
- {
- if (plugin == null)
- {
- return;
- }
- if (string.IsNullOrEmpty(filename))
- {
- fileSaveAsMenuItem.PerformClick();
- }
- else
- {
- var fileInfo = new FileInfo(filename);
- if (SaveFile(fileInfo.FullName))
- {
- mru.Add(fileInfo);
- }
- else
- {
- mru.Remove(fileInfo);
- }
- }
- }
- private void fileSaveAsMenuItem_Click(object sender, EventArgs e)
- {
- if (plugin == null)
- {
- return;
- }
- SaveFileDialog sfd = new SaveFileDialog
- {
- AutoUpgradeEnabled = false,
- RestoreDirectory = true
- };
- var filters = new List<string>();
- switch (plugin.GameType)
- {
- case GameType.TiberianDawn:
- filters.Add("Tiberian Dawn files (*.ini;*.bin)|*.ini;*.bin");
- sfd.InitialDirectory = TiberianDawn.Constants.SaveDirectory;
- break;
- case GameType.RedAlert:
- filters.Add("Red Alert files (*.mpr)|*.mpr");
- sfd.InitialDirectory = RedAlert.Constants.SaveDirectory;
- break;
- }
- filters.Add("All files (*.*)|*.*");
- sfd.Filter = string.Join("|", filters);
- if (!string.IsNullOrEmpty(filename))
- {
- sfd.InitialDirectory = Path.GetDirectoryName(filename);
- sfd.FileName = Path.GetFileName(filename);
- }
- if (sfd.ShowDialog() == DialogResult.OK)
- {
- var fileInfo = new FileInfo(sfd.FileName);
- if (SaveFile(fileInfo.FullName))
- {
- mru.Add(fileInfo);
- }
- else
- {
- mru.Remove(fileInfo);
- }
- }
- }
- private void fileExportMenuItem_Click(object sender, EventArgs e)
- {
- if (plugin == null)
- {
- return;
- }
- SaveFileDialog sfd = new SaveFileDialog
- {
- AutoUpgradeEnabled = false,
- RestoreDirectory = true
- };
- sfd.Filter = "MEG files (*.meg)|*.meg";
- if (sfd.ShowDialog() == DialogResult.OK)
- {
- plugin.Save(sfd.FileName, FileType.MEG);
- }
- }
- private void fileExitMenuItem_Click(object sender, EventArgs e)
- {
- Close();
- }
- private void editUndoMenuItem_Click(object sender, EventArgs e)
- {
- if (url.CanUndo)
- {
- url.Undo(new UndoRedoEventArgs(mapPanel, plugin.Map));
- }
- }
- private void editRedoMenuItem_Click(object sender, EventArgs e)
- {
- if (url.CanRedo)
- {
- url.Redo(new UndoRedoEventArgs(mapPanel, plugin.Map));
- }
- }
- private void settingsMapSettingsMenuItem_Click(object sender, EventArgs e)
- {
- if (plugin == null)
- {
- return;
- }
- var basicSettings = new PropertyTracker<BasicSection>(plugin.Map.BasicSection);
- var briefingSettings = new PropertyTracker<BriefingSection>(plugin.Map.BriefingSection);
- var houseSettingsTrackers = plugin.Map.Houses.ToDictionary(h => h, h => new PropertyTracker<House>(h));
- MapSettingsDialog msd = new MapSettingsDialog(plugin, basicSettings, briefingSettings, houseSettingsTrackers);
- if (msd.ShowDialog() == DialogResult.OK)
- {
- basicSettings.Commit();
- briefingSettings.Commit();
- foreach (var houseSettingsTracker in houseSettingsTrackers.Values)
- {
- houseSettingsTracker.Commit();
- }
- plugin.Dirty = true;
- }
- }
- private void settingsTeamTypesMenuItem_Click(object sender, EventArgs e)
- {
- if (plugin == null)
- {
- return;
- }
- int maxTeams = 0;
- switch (plugin.GameType)
- {
- case GameType.TiberianDawn:
- {
- maxTeams = TiberianDawn.Constants.MaxTeams;
- }
- break;
- case GameType.RedAlert:
- {
- maxTeams = RedAlert.Constants.MaxTeams;
- }
- break;
- }
- TeamTypesDialog ttd = new TeamTypesDialog(plugin, maxTeams);
- if (ttd.ShowDialog() == DialogResult.OK)
- {
- plugin.Map.TeamTypes.Clear();
- plugin.Map.TeamTypes.AddRange(ttd.TeamTypes.Select(t => t.Clone()));
- plugin.Dirty = true;
- }
- }
- private void settingsTriggersMenuItem_Click(object sender, EventArgs e)
- {
- if (plugin == null)
- {
- return;
- }
- int maxTriggers = 0;
- switch (plugin.GameType)
- {
- case GameType.TiberianDawn:
- {
- maxTriggers = TiberianDawn.Constants.MaxTriggers;
- }
- break;
- case GameType.RedAlert:
- {
- maxTriggers = RedAlert.Constants.MaxTriggers;
- }
- break;
- }
- TriggersDialog td = new TriggersDialog(plugin, maxTriggers);
- if (td.ShowDialog() == DialogResult.OK)
- {
- var oldTriggers =
- from leftTrigger in plugin.Map.Triggers
- join rightTrigger in td.Triggers
- on leftTrigger.Name equals rightTrigger.Name into result
- where result.Count() == 0
- select leftTrigger;
- var newTriggers =
- from leftTrigger in td.Triggers
- join rightTrigger in plugin.Map.Triggers
- on leftTrigger.Name equals rightTrigger.Name into result
- where result.Count() == 0
- select leftTrigger;
- var sameTriggers =
- from leftTrigger in plugin.Map.Triggers
- join rightTrigger in td.Triggers
- on leftTrigger.Name equals rightTrigger.Name
- select new
- {
- OldTrigger = leftTrigger,
- NewTrigger = rightTrigger
- };
- foreach (var oldTrigger in oldTriggers.ToArray())
- {
- plugin.Map.Triggers.Remove(oldTrigger);
- }
- foreach (var newTrigger in newTriggers.ToArray())
- {
- plugin.Map.Triggers.Add(newTrigger.Clone());
- }
- foreach (var item in sameTriggers.ToArray())
- {
- plugin.Map.Triggers.Add(item.NewTrigger.Clone());
- plugin.Map.Triggers.Remove(item.OldTrigger);
- }
- plugin.Dirty = true;
- }
- }
- private void Mru_FileSelected(object sender, FileInfo e)
- {
- if (!PromptSaveMap())
- {
- return;
- }
- if (LoadFile(e.FullName))
- {
- mru.Add(e);
- }
- else
- {
- mru.Remove(e);
- MessageBox.Show(string.Format("Error loading {0}.", e.FullName), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- }
- private void mapPanel_MouseMove(object sender, MouseEventArgs e)
- {
- if (plugin != null)
- {
- var mapPoint = mapPanel.ClientToMap(e.Location);
- var location = new Point((int)Math.Floor((double)mapPoint.X / Globals.TileWidth), (int)Math.Floor((double)mapPoint.Y / Globals.TileHeight));
- if (plugin.Map.Metrics.GetCell(location, out int cell))
- {
- var sb = new StringBuilder();
- sb.AppendFormat("X = {0}, Y = {1}, Cell = {2}", location.X, location.Y, cell);
- var template = plugin.Map.Templates[cell];
- var templateType = template?.Type;
- if (templateType != null)
- {
- sb.AppendFormat(", Template = {0} ({1})", templateType.DisplayName, template.Icon);
- }
- var smudge = plugin.Map.Smudge[cell];
- var smudgeType = smudge?.Type;
- if (smudgeType != null)
- {
- sb.AppendFormat(", Smudge = {0}", smudgeType.DisplayName);
- }
- var overlay = plugin.Map.Overlay[cell];
- var overlayType = overlay?.Type;
- if (overlayType != null)
- {
- sb.AppendFormat(", Overlay = {0}", overlayType.DisplayName);
- }
- var terrain = plugin.Map.Technos[location] as Terrain;
- var terrainType = terrain?.Type;
- if (terrainType != null)
- {
- sb.AppendFormat(", Terrain = {0}", terrainType.DisplayName);
- }
- if (plugin.Map.Technos[location] is InfantryGroup infantryGroup)
- {
- var subPixel = new Point(
- (mapPoint.X * Globals.PixelWidth / Globals.TileWidth) % Globals.PixelWidth,
- (mapPoint.Y * Globals.PixelHeight / Globals.TileHeight) % Globals.PixelHeight
- );
- var i = InfantryGroup.ClosestStoppingTypes(subPixel).Cast<int>().First();
- if (infantryGroup.Infantry[i] != null)
- {
- sb.AppendFormat(", Infantry = {0}", infantryGroup.Infantry[i].Type.DisplayName);
- }
- }
- var unit = plugin.Map.Technos[location] as Unit;
- var unitType = unit?.Type;
- if (unitType != null)
- {
- sb.AppendFormat(", Unit = {0}", unitType.DisplayName);
- }
- var building = plugin.Map.Technos[location] as Building;
- var buildingType = building?.Type;
- if (buildingType != null)
- {
- sb.AppendFormat(", Building = {0}", buildingType.DisplayName);
- }
- cellStatusLabel.Text = sb.ToString();
- }
- else
- {
- cellStatusLabel.Text = string.Empty;
- }
- }
- }
- private bool LoadFile(string loadFilename)
- {
- FileType fileType = FileType.None;
- switch (Path.GetExtension(loadFilename).ToLower())
- {
- case ".ini":
- case ".mpr":
- fileType = FileType.INI;
- break;
- case ".bin":
- fileType = FileType.BIN;
- break;
- #if DEVELOPER
- case ".pgm":
- fileType = FileType.PGM;
- break;
- #endif
- }
- if (fileType == FileType.None)
- {
- return false;
- }
- GameType gameType = GameType.None;
- switch (fileType)
- {
- case FileType.INI:
- {
- var ini = new INI();
- try
- {
- using (var reader = new StreamReader(loadFilename))
- {
- ini.Parse(reader);
- }
- }
- catch (FileNotFoundException)
- {
- return false;
- }
- gameType = File.Exists(Path.ChangeExtension(loadFilename, ".bin")) ? GameType.TiberianDawn : GameType.RedAlert;
- }
- break;
- case FileType.BIN:
- gameType = GameType.TiberianDawn;
- break;
- #if DEVELOPER
- case FileType.PGM:
- {
- try
- {
- using (var megafile = new Megafile(loadFilename))
- {
- if (megafile.Any(f => Path.GetExtension(f).ToLower() == ".mpr"))
- {
- gameType = GameType.RedAlert;
- }
- else
- {
- gameType = GameType.TiberianDawn;
- }
- }
- }
- catch (FileNotFoundException)
- {
- return false;
- }
- }
- break;
- #endif
- }
- if (gameType == GameType.None)
- {
- return false;
- }
- if (plugin != null)
- {
- plugin.Map.Triggers.CollectionChanged -= Triggers_CollectionChanged;
- plugin.Dispose();
- }
- plugin = null;
- Globals.TheTilesetManager.Reset();
- Globals.TheTextureManager.Reset();
- switch (gameType)
- {
- case GameType.TiberianDawn:
- {
- Globals.TheTeamColorManager.Reset();
- Globals.TheTeamColorManager.Load(@"DATA\XML\CNCTDTEAMCOLORS.XML");
- plugin = new TiberianDawn.GamePlugin();
- }
- break;
- case GameType.RedAlert:
- {
- Globals.TheTeamColorManager.Reset();
- Globals.TheTeamColorManager.Load(@"DATA\XML\CNCRATEAMCOLORS.XML");
- plugin = new RedAlert.GamePlugin();
- }
- break;
- }
- try
- {
- var errors = plugin.Load(loadFilename, fileType).ToArray();
- if (errors.Length > 0)
- {
- ErrorMessageBox errorMessageBox = new ErrorMessageBox { Errors = errors };
- errorMessageBox.ShowDialog();
- }
- }
- catch (Exception)
- {
- #if DEVELOPER
- throw;
- #else
- return false;
- #endif
- }
- plugin.Map.Triggers.CollectionChanged += Triggers_CollectionChanged;
- mapPanel.MapImage = plugin.MapImage;
- plugin.Dirty = false;
- filename = loadFilename;
- Text = string.Format("CnC TDRA Map Editor - {0}", filename);
- url.Clear();
- ClearActiveTool();
- RefreshAvailableTools();
- RefreshActiveTool();
- return true;
- }
- private bool SaveFile(string saveFilename)
- {
- FileType fileType = FileType.None;
- switch (Path.GetExtension(saveFilename).ToLower())
- {
- case ".ini":
- case ".mpr":
- fileType = FileType.INI;
- break;
- case ".bin":
- fileType = FileType.BIN;
- break;
- }
- if (fileType == FileType.None)
- {
- return false;
- }
- if (string.IsNullOrEmpty(plugin.Map.SteamSection.Title))
- {
- plugin.Map.SteamSection.Title = plugin.Map.BasicSection.Name;
- }
- if (!plugin.Save(saveFilename, fileType))
- {
- return false;
- }
- if (new FileInfo(saveFilename).Length > Globals.MaxMapSize)
- {
- MessageBox.Show(string.Format("Map file exceeds the maximum size of {0} bytes.", Globals.MaxMapSize), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- plugin.Dirty = false;
- filename = saveFilename;
- Text = string.Format("CnC TDRA Map Editor - {0}", filename);
- return true;
- }
- private void RefreshAvailableTools()
- {
- availableToolTypes = ToolType.None;
- if (plugin != null)
- {
- availableToolTypes |= ToolType.Waypoint;
- if (plugin.Map.TemplateTypes.Any()) availableToolTypes |= ToolType.Map;
- if (plugin.Map.SmudgeTypes.Any()) availableToolTypes |= ToolType.Smudge;
- if (plugin.Map.OverlayTypes.Any(t => t.IsPlaceable && ((t.Theaters == null) || t.Theaters.Contains(plugin.Map.Theater)))) availableToolTypes |= ToolType.Overlay;
- if (plugin.Map.TerrainTypes.Any(t => t.Theaters.Contains(plugin.Map.Theater))) availableToolTypes |= ToolType.Terrain;
- if (plugin.Map.InfantryTypes.Any()) availableToolTypes |= ToolType.Infantry;
- if (plugin.Map.UnitTypes.Any()) availableToolTypes |= ToolType.Unit;
- if (plugin.Map.BuildingTypes.Any()) availableToolTypes |= ToolType.Building;
- if (plugin.Map.OverlayTypes.Any(t => t.IsResource)) availableToolTypes |= ToolType.Resources;
- if (plugin.Map.OverlayTypes.Any(t => t.IsWall)) availableToolTypes |= ToolType.Wall;
- if (plugin.Map.Triggers.Any()) availableToolTypes |= ToolType.CellTrigger;
- }
- mapToolStripButton.Enabled = (availableToolTypes & ToolType.Map) != ToolType.None;
- smudgeToolStripButton.Enabled = (availableToolTypes & ToolType.Smudge) != ToolType.None;
- overlayToolStripButton.Enabled = (availableToolTypes & ToolType.Overlay) != ToolType.None;
- terrainToolStripButton.Enabled = (availableToolTypes & ToolType.Terrain) != ToolType.None;
- infantryToolStripButton.Enabled = (availableToolTypes & ToolType.Infantry) != ToolType.None;
- unitToolStripButton.Enabled = (availableToolTypes & ToolType.Unit) != ToolType.None;
- buildingToolStripButton.Enabled = (availableToolTypes & ToolType.Building) != ToolType.None;
- resourcesToolStripButton.Enabled = (availableToolTypes & ToolType.Resources) != ToolType.None;
- wallsToolStripButton.Enabled = (availableToolTypes & ToolType.Wall) != ToolType.None;
- waypointsToolStripButton.Enabled = (availableToolTypes & ToolType.Waypoint) != ToolType.None;
- cellTriggersToolStripButton.Enabled = (availableToolTypes & ToolType.CellTrigger) != ToolType.None;
- ActiveToolType = activeToolType;
- }
- private void ClearActiveTool()
- {
- activeTool?.Dispose();
- activeTool = null;
- if (activeToolForm != null)
- {
- activeToolForm.ResizeEnd -= ActiveToolForm_ResizeEnd;
- activeToolForm.Close();
- activeToolForm = null;
- }
- toolStatusLabel.Text = string.Empty;
- }
- private void RefreshActiveTool()
- {
- if (plugin == null)
- {
- return;
- }
- if (activeTool == null)
- {
- activeLayers = MapLayerFlag.None;
- }
- ClearActiveTool();
- switch (ActiveToolType)
- {
- case ToolType.Map:
- {
- TemplateToolDialog toolDialog = new TemplateToolDialog();
- activeTool = new TemplateTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.TemplateTypeListView, toolDialog.TemplateTypeMapPanel, mouseToolTip, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- } break;
- case ToolType.Smudge:
- {
- GenericToolDialog toolDialog = new GenericToolDialog
- {
- Text = "Smudge"
- };
- toolDialog.GenericTypeComboBox.Types = plugin.Map.SmudgeTypes.Where(t => (t.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None).OrderBy(t => t.Name);
- activeTool = new SmudgeTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.GenericTypeComboBox, toolDialog.GenericTypeMapPanel, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- case ToolType.Overlay:
- {
- GenericToolDialog toolDialog = new GenericToolDialog
- {
- Text = "Overlay"
- };
- toolDialog.GenericTypeComboBox.Types = plugin.Map.OverlayTypes.Where(t => t.IsPlaceable && ((t.Theaters == null) || t.Theaters.Contains(plugin.Map.Theater))).OrderBy(t => t.Name);
- activeTool = new OverlaysTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.GenericTypeComboBox, toolDialog.GenericTypeMapPanel, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- case ToolType.Resources:
- {
- ResourcesToolDialog toolDialog = new ResourcesToolDialog();
- activeTool = new ResourcesTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.TotalResourcesLbl, toolDialog.ResourceBrushSizeNud, toolDialog.GemsCheckBox, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- case ToolType.Terrain:
- {
- TerrainToolDialog toolDialog = new TerrainToolDialog(plugin);
- toolDialog.TerrainTypeComboBox.Types = plugin.Map.TerrainTypes.Where(t => t.Theaters.Contains(plugin.Map.Theater)).OrderBy(t => t.Name);
- activeTool = new TerrainTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.TerrainTypeComboBox, toolDialog.TerrainTypeMapPanel, toolDialog.TerrainProperties, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- case ToolType.Infantry:
- {
- ObjectToolDialog toolDialog = new ObjectToolDialog(plugin)
- {
- Text = "Infantry"
- };
- toolDialog.ObjectTypeComboBox.Types = plugin.Map.InfantryTypes.OrderBy(t => t.Name);
- activeTool = new InfantryTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.ObjectTypeComboBox, toolDialog.ObjectTypeMapPanel, toolDialog.ObjectProperties, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- case ToolType.Unit:
- {
- ObjectToolDialog toolDialog = new ObjectToolDialog(plugin)
- {
- Text = "Units"
- };
- toolDialog.ObjectTypeComboBox.Types = plugin.Map.UnitTypes
- .Where(t => !t.IsFixedWing)
- .OrderBy(t => t.Name);
- activeTool = new UnitTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.ObjectTypeComboBox, toolDialog.ObjectTypeMapPanel, toolDialog.ObjectProperties, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- case ToolType.Building:
- {
- ObjectToolDialog toolDialog = new ObjectToolDialog(plugin)
- {
- Text = "Structures"
- };
- toolDialog.ObjectTypeComboBox.Types = plugin.Map.BuildingTypes
- .Where(t => (t.Theaters == null) || t.Theaters.Contains(plugin.Map.Theater))
- .OrderBy(t => t.IsFake)
- .ThenBy(t => t.Name);
- activeTool = new BuildingTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.ObjectTypeComboBox, toolDialog.ObjectTypeMapPanel, toolDialog.ObjectProperties, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- case ToolType.Wall:
- {
- GenericToolDialog toolDialog = new GenericToolDialog
- {
- Text = "Walls"
- };
- toolDialog.GenericTypeComboBox.Types = plugin.Map.OverlayTypes.Where(t => t.IsWall).OrderBy(t => t.Name);
- activeTool = new WallsTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.GenericTypeComboBox, toolDialog.GenericTypeMapPanel, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- case ToolType.Waypoint:
- {
- WaypointsToolDialog toolDialog = new WaypointsToolDialog();
- toolDialog.WaypointCombo.DataSource = plugin.Map.Waypoints.Select(w => w.Name).ToArray();
- activeTool = new WaypointsTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.WaypointCombo, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- case ToolType.CellTrigger:
- {
- CellTriggersToolDialog toolDialog = new CellTriggersToolDialog();
- toolDialog.TriggerCombo.DataSource = plugin.Map.Triggers.Select(t => t.Name).ToArray();
- activeTool = new CellTriggersTool(mapPanel, ActiveLayers, toolStatusLabel, toolDialog.TriggerCombo, plugin, url);
- activeToolForm = toolDialog;
- activeToolForm.Show(this);
- }
- break;
- }
- if (activeToolForm != null)
- {
- activeToolForm.ResizeEnd += ActiveToolForm_ResizeEnd;
- clampActiveToolForm();
- }
- switch (plugin.GameType)
- {
- case GameType.TiberianDawn:
- mapPanel.MaxZoom = 8;
- mapPanel.ZoomStep = 1;
- break;
- case GameType.RedAlert:
- mapPanel.MaxZoom = 16;
- mapPanel.ZoomStep = 2;
- break;
- }
- mapToolStripButton.Checked = ActiveToolType == ToolType.Map;
- smudgeToolStripButton.Checked = ActiveToolType == ToolType.Smudge;
- overlayToolStripButton.Checked = ActiveToolType == ToolType.Overlay;
- terrainToolStripButton.Checked = ActiveToolType == ToolType.Terrain;
- infantryToolStripButton.Checked = ActiveToolType == ToolType.Infantry;
- unitToolStripButton.Checked = ActiveToolType == ToolType.Unit;
- buildingToolStripButton.Checked = ActiveToolType == ToolType.Building;
- resourcesToolStripButton.Checked = ActiveToolType == ToolType.Resources;
- wallsToolStripButton.Checked = ActiveToolType == ToolType.Wall;
- waypointsToolStripButton.Checked = ActiveToolType == ToolType.Waypoint;
- cellTriggersToolStripButton.Checked = ActiveToolType == ToolType.CellTrigger;
- Focus();
- UpdateVisibleLayers();
- mapPanel.Invalidate();
- }
- private void clampActiveToolForm()
- {
- if (activeToolForm == null)
- {
- return;
- }
- Rectangle bounds = activeToolForm.DesktopBounds;
- Rectangle workingArea = Screen.FromControl(this).WorkingArea;
- if (bounds.Right > workingArea.Right)
- {
- bounds.X = workingArea.Right - bounds.Width;
- }
- if (bounds.X < workingArea.Left)
- {
- bounds.X = workingArea.Left;
- }
- if (bounds.Bottom > workingArea.Bottom)
- {
- bounds.Y = workingArea.Bottom - bounds.Height;
- }
- if (bounds.Y < workingArea.Top)
- {
- bounds.Y = workingArea.Top;
- }
- activeToolForm.DesktopBounds = bounds;
- }
- private void ActiveToolForm_ResizeEnd(object sender, EventArgs e)
- {
- clampActiveToolForm();
- }
- private void Triggers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
- {
- RefreshAvailableTools();
- }
- private void mainToolStripButton_Click(object sender, EventArgs e)
- {
- if (plugin == null)
- {
- return;
- }
- if (sender == mapToolStripButton)
- {
- ActiveToolType = ToolType.Map;
- }
- else if (sender == smudgeToolStripButton)
- {
- ActiveToolType = ToolType.Smudge;
- }
- else if (sender == overlayToolStripButton)
- {
- ActiveToolType = ToolType.Overlay;
- }
- else if (sender == terrainToolStripButton)
- {
- ActiveToolType = ToolType.Terrain;
- }
- else if (sender == infantryToolStripButton)
- {
- ActiveToolType = ToolType.Infantry;
- }
- else if (sender == unitToolStripButton)
- {
- ActiveToolType = ToolType.Unit;
- }
- else if (sender == buildingToolStripButton)
- {
- ActiveToolType = ToolType.Building;
- }
- else if (sender == resourcesToolStripButton)
- {
- ActiveToolType = ToolType.Resources;
- }
- else if (sender == wallsToolStripButton)
- {
- ActiveToolType = ToolType.Wall;
- }
- else if (sender == waypointsToolStripButton)
- {
- ActiveToolType = ToolType.Waypoint;
- }
- else if (sender == cellTriggersToolStripButton)
- {
- ActiveToolType = ToolType.CellTrigger;
- }
- }
- private void UpdateVisibleLayers()
- {
- MapLayerFlag layers = MapLayerFlag.All;
- if (!viewLayersBoundariesMenuItem.Checked)
- {
- layers &= ~MapLayerFlag.Boundaries;
- }
- if (!viewLayersOverlayMenuItem.Checked)
- {
- layers &= ~MapLayerFlag.OverlayAll;
- }
- if (!viewLayersTerrainMenuItem.Checked)
- {
- layers &= ~MapLayerFlag.Terrain;
- }
- if (!viewLayersWaypointsMenuItem.Checked)
- {
- layers &= ~MapLayerFlag.Waypoints;
- }
- if (!viewLayersCellTriggersMenuItem.Checked)
- {
- layers &= ~MapLayerFlag.CellTriggers;
- }
- if (!viewLayersObjectTriggersMenuItem.Checked)
- {
- layers &= ~MapLayerFlag.TechnoTriggers;
- }
- ActiveLayers = layers;
- }
- private void viewLayersMenuItem_CheckedChanged(object sender, EventArgs e)
- {
- UpdateVisibleLayers();
- }
- private void toolTabControl_Selected(object sender, TabControlEventArgs e)
- {
- if (plugin == null)
- {
- return;
- }
- }
- private void developerGenerateMapPreviewMenuItem_Click(object sender, EventArgs e)
- {
- #if DEVELOPER
- if ((plugin == null) || string.IsNullOrEmpty(filename))
- {
- return;
- }
- plugin.Map.GenerateMapPreview().Save(Path.ChangeExtension(filename, ".tga"));
- #endif
- }
- private void developerGoToINIMenuItem_Click(object sender, EventArgs e)
- {
- #if DEVELOPER
- if ((plugin == null) || string.IsNullOrEmpty(filename))
- {
- return;
- }
- var path = Path.ChangeExtension(filename, ".mpr");
- if (!File.Exists(path))
- {
- path = Path.ChangeExtension(filename, ".ini");
- }
- try
- {
- Process.Start(path);
- }
- catch (Win32Exception)
- {
- Process.Start("notepad.exe", path);
- }
- catch (Exception) { }
- #endif
- }
- private void developerGenerateMapPreviewDirectoryMenuItem_Click(object sender, EventArgs e)
- {
- #if DEVELOPER
- FolderBrowserDialog fbd = new FolderBrowserDialog
- {
- ShowNewFolderButton = false
- };
- if (fbd.ShowDialog() == DialogResult.OK)
- {
- var extensions = new string[] { ".ini", ".mpr" };
- foreach (var file in Directory.EnumerateFiles(fbd.SelectedPath).Where(file => extensions.Contains(Path.GetExtension(file).ToLower())))
- {
- GameType gameType = GameType.None;
- var ini = new INI();
- using (var reader = new StreamReader(file))
- {
- ini.Parse(reader);
- }
- gameType = ini.Sections.Contains("MapPack") ? GameType.RedAlert : GameType.TiberianDawn;
- if (gameType == GameType.None)
- {
- continue;
- }
- IGamePlugin plugin = null;
- switch (gameType)
- {
- case GameType.TiberianDawn:
- {
- plugin = new TiberianDawn.GamePlugin(false);
- }
- break;
- case GameType.RedAlert:
- {
- plugin = new RedAlert.GamePlugin(false);
- }
- break;
- }
- plugin.Load(file, FileType.INI);
- plugin.Map.GenerateMapPreview().Save(Path.ChangeExtension(file, ".tga"));
- plugin.Dispose();
- }
- }
- #endif
- }
- private void developerDebugShowOverlapCellsMenuItem_CheckedChanged(object sender, EventArgs e)
- {
- #if DEVELOPER
- Globals.Developer.ShowOverlapCells = developerDebugShowOverlapCellsMenuItem.Checked;
- #endif
- }
- private void filePublishMenuItem_Click(object sender, EventArgs e)
- {
- if (plugin == null)
- {
- return;
- }
- if (!PromptSaveMap())
- {
- return;
- }
- if (plugin.Dirty)
- {
- MessageBox.Show("Map must be saved before publishing.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
- return;
- }
- if (new FileInfo(filename).Length > Globals.MaxMapSize)
- {
- return;
- }
- using (var sd = new SteamDialog(plugin))
- {
- sd.ShowDialog();
- }
- fileSaveMenuItem.PerformClick();
- }
- private void mainToolStrip_MouseMove(object sender, MouseEventArgs e)
- {
- mainToolStrip.Focus();
- }
- private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
- {
- e.Cancel = !PromptSaveMap();
- }
- private bool PromptSaveMap()
- {
- bool cancel = false;
- if (plugin?.Dirty ?? false)
- {
- var message = string.IsNullOrEmpty(filename) ? "Save new map?" : string.Format("Save map '{0}'?", filename);
- var result = MessageBox.Show(message, "Save", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
- switch (result)
- {
- case DialogResult.Yes:
- {
- if (string.IsNullOrEmpty(filename))
- {
- fileSaveAsMenuItem.PerformClick();
- }
- else
- {
- fileSaveMenuItem.PerformClick();
- }
- }
- break;
- case DialogResult.No:
- break;
- case DialogResult.Cancel:
- cancel = true;
- break;
- }
- }
- return !cancel;
- }
- }
- }
|