CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

TeamTypesDialog.cs (19496B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // The Command & Conquer Map Editor and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // The Command & Conquer Map Editor and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 using MobiusEditor.Interface;
     16 using MobiusEditor.Model;
     17 using MobiusEditor.Utility;
     18 using System;
     19 using System.Collections.Generic;
     20 using System.Data;
     21 using System.Linq;
     22 using System.Windows.Forms;
     23 
     24 namespace MobiusEditor.Dialogs
     25 {
     26     public partial class TeamTypesDialog : Form
     27     {
     28         private readonly IGamePlugin plugin;
     29         private readonly int maxTeams;
     30         private readonly IEnumerable<ITechnoType> technoTypes;
     31 
     32         private readonly List<TeamType> teamTypes;
     33         public IEnumerable<TeamType> TeamTypes => teamTypes;
     34 
     35         private ListViewItem SelectedItem => (teamTypesListView.SelectedItems.Count > 0) ? teamTypesListView.SelectedItems[0] : null;
     36 
     37         private TeamType SelectedTeamType => SelectedItem?.Tag as TeamType;
     38 
     39         private TeamTypeClass mockClass;
     40         private TeamTypeMission mockMission;
     41         private int classEditRow = -1;
     42         private int missionEditRow = -1;
     43 
     44         public TeamTypesDialog(IGamePlugin plugin, int maxTeams)
     45         {
     46             this.plugin = plugin;
     47             this.maxTeams = maxTeams;
     48             technoTypes = plugin.Map.InfantryTypes.Cast<ITechnoType>().Concat(plugin.Map.UnitTypes.Cast<ITechnoType>());
     49 
     50             InitializeComponent();
     51 
     52             switch (plugin.GameType)
     53             {
     54                 case GameType.TiberianDawn:
     55                     triggerLabel.Visible = triggerComboBox.Visible = false;
     56                     waypointLabel.Visible = waypointComboBox.Visible = false;
     57                     break;
     58                 case GameType.RedAlert:
     59                     learningCheckBox.Visible = false;
     60                     mercernaryCheckBox.Visible = false;
     61                     break;
     62             }
     63 
     64             teamTypes = new List<TeamType>(plugin.Map.TeamTypes.Select(t => t.Clone()));
     65 
     66             teamTypesListView.BeginUpdate();
     67             {
     68                 foreach (var teamType in this.teamTypes)
     69                 {
     70                     var item = new ListViewItem(teamType.Name)
     71                     {
     72                         Tag = teamType
     73                     };
     74                     teamTypesListView.Items.Add(item).ToolTipText = teamType.Name;
     75                 }
     76             }
     77             teamTypesListView.EndUpdate();
     78 
     79             houseComboBox.DataSource = plugin.Map.Houses.Select(t => new TypeItem<HouseType>(t.Type.Name, t.Type)).ToArray();
     80             waypointComboBox.DataSource = "(none)".Yield().Concat(plugin.Map.Waypoints.Select(w => w.Name)).ToArray();
     81             triggerComboBox.DataSource = Trigger.None.Yield().Concat(plugin.Map.Triggers.Select(t => t.Name)).ToArray();
     82 
     83             teamsTypeColumn.DisplayMember = "Name";
     84             teamsTypeColumn.ValueMember = "Type";
     85             teamsTypeColumn.DataSource = technoTypes.Select(t => new TypeItem<ITechnoType>(t.Name, t)).ToArray();
     86 
     87             missionsMissionColumn.DataSource = plugin.Map.TeamMissionTypes;
     88 
     89             teamTypeTableLayoutPanel.Visible = false;
     90         }
     91 
     92         private void teamTypesListView_SelectedIndexChanged(object sender, EventArgs e)
     93         {
     94             houseComboBox.DataBindings.Clear();
     95             roundaboutCheckBox.DataBindings.Clear();
     96             learningCheckBox.DataBindings.Clear();
     97             suicideCheckBox.DataBindings.Clear();
     98             autocreateCheckBox.DataBindings.Clear();
     99             mercernaryCheckBox.DataBindings.Clear();
    100             reinforcableCheckBox.DataBindings.Clear();
    101             prebuiltCheckBox.DataBindings.Clear();
    102             recruitPriorityNud.DataBindings.Clear();
    103             initNumNud.DataBindings.Clear();
    104             maxAllowedNud.DataBindings.Clear();
    105             fearNud.DataBindings.Clear();
    106             waypointComboBox.DataBindings.Clear();
    107             triggerComboBox.DataBindings.Clear();
    108 
    109             if (SelectedTeamType != null)
    110             {
    111                 houseComboBox.DataBindings.Add("SelectedValue", SelectedTeamType, "House");
    112                 roundaboutCheckBox.DataBindings.Add("Checked", SelectedTeamType, "IsRoundAbout");
    113                 learningCheckBox.DataBindings.Add("Checked", SelectedTeamType, "IsLearning");
    114                 suicideCheckBox.DataBindings.Add("Checked", SelectedTeamType, "IsSuicide");
    115                 autocreateCheckBox.DataBindings.Add("Checked", SelectedTeamType, "IsAutocreate");
    116                 mercernaryCheckBox.DataBindings.Add("Checked", SelectedTeamType, "IsMercenary");
    117                 reinforcableCheckBox.DataBindings.Add("Checked", SelectedTeamType, "IsReinforcable");
    118                 prebuiltCheckBox.DataBindings.Add("Checked", SelectedTeamType, "IsPrebuilt");
    119                 recruitPriorityNud.DataBindings.Add("Value", SelectedTeamType, "RecruitPriority");
    120                 initNumNud.DataBindings.Add("Value", SelectedTeamType, "InitNum");
    121                 maxAllowedNud.DataBindings.Add("Value", SelectedTeamType, "MaxAllowed");
    122                 fearNud.DataBindings.Add("Value", SelectedTeamType, "Fear");
    123                 waypointComboBox.DataBindings.Add("SelectedIndex", SelectedTeamType, "Origin");
    124                 triggerComboBox.DataBindings.Add("SelectedItem", SelectedTeamType, "Trigger");
    125 
    126                 mockClass = null;
    127                 mockMission = null;
    128                 classEditRow = -1;
    129                 missionEditRow = -1;
    130 
    131                 teamsDataGridView.Rows.Clear();
    132                 missionsDataGridView.Rows.Clear();
    133 
    134                 teamsDataGridView.RowCount = SelectedTeamType.Classes.Count + 1;
    135                 missionsDataGridView.RowCount = SelectedTeamType.Missions.Count + 1;
    136 
    137                 updateDataGridViewAddRows(teamsDataGridView, Globals.MaxTeamClasses);
    138                 updateDataGridViewAddRows(missionsDataGridView, Globals.MaxTeamMissions);
    139 
    140                 teamTypeTableLayoutPanel.Visible = true;
    141             }
    142             else
    143             {
    144                 teamTypeTableLayoutPanel.Visible = false;
    145             }
    146         }
    147 
    148         private void teamTypesListView_MouseDown(object sender, MouseEventArgs e)
    149         {
    150             if (e.Button == MouseButtons.Right)
    151             {
    152                 var hitTest = teamTypesListView.HitTest(e.Location);
    153 
    154                 bool canAdd = (hitTest.Item == null) && (teamTypesListView.Items.Count < maxTeams);
    155                 bool canRemove = hitTest.Item != null;
    156                 addTeamTypeToolStripMenuItem.Visible = canAdd;
    157                 removeTeamTypeToolStripMenuItem.Visible = canRemove;
    158 
    159                 if (canAdd || canRemove)
    160                 {
    161                     teamTypesContextMenuStrip.Show(Cursor.Position);
    162                 }
    163             }
    164         }
    165 
    166         private void teamTypesListView_KeyDown(object sender, KeyEventArgs e)
    167         {
    168             if ((e.KeyData == Keys.F2) && (teamTypesListView.SelectedItems.Count > 0))
    169             {
    170                 teamTypesListView.SelectedItems[0].BeginEdit();
    171             }
    172         }
    173 
    174         private void addTeamTypeToolStripMenuItem_Click(object sender, EventArgs e)
    175         {
    176             var nameChars = Enumerable.Range(97, 26).Concat(Enumerable.Range(48, 10));
    177 
    178             string name = string.Empty;
    179             foreach (var nameChar in nameChars)
    180             {
    181                 name = new string((char)nameChar, 4);
    182                 if (!teamTypes.Where(t => t.Equals(name)).Any())
    183                 {
    184                     break;
    185                 }
    186             }
    187 
    188             var teamType = new TeamType { Name = name, House = plugin.Map.HouseTypes.First() };
    189             var item = new ListViewItem(teamType.Name)
    190             {
    191                 Tag = teamType
    192             };
    193             teamTypes.Add(teamType);
    194             teamTypesListView.Items.Add(item).ToolTipText = teamType.Name;
    195 
    196             item.Selected = true;
    197             item.BeginEdit();
    198         }
    199 
    200         private void removeTeamTypeToolStripMenuItem_Click(object sender, EventArgs e)
    201         {
    202             if (SelectedItem != null)
    203             {
    204                 teamTypes.Remove(SelectedTeamType);
    205                 teamTypesListView.Items.Remove(SelectedItem);
    206             }
    207         }
    208 
    209         private void teamTypesListView_AfterLabelEdit(object sender, LabelEditEventArgs e)
    210         {
    211             int maxLength = int.MaxValue;
    212             switch (plugin.GameType)
    213             {
    214                 case GameType.TiberianDawn:
    215                     maxLength = 8;
    216                     break;
    217                 case GameType.RedAlert:
    218                     maxLength = 23;
    219                     break;
    220             }
    221 
    222             if (string.IsNullOrEmpty(e.Label))
    223             {
    224                 e.CancelEdit = true;
    225             }
    226             else if (e.Label.Length > maxLength)
    227             {
    228                 e.CancelEdit = true;
    229                 MessageBox.Show(string.Format("Team name is longer than {0} characters.", maxLength), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    230             }
    231             else if (teamTypes.Where(t => (t != SelectedTeamType) && t.Equals(e.Label)).Any())
    232             {
    233                 e.CancelEdit = true;
    234                 MessageBox.Show(string.Format("Team with name '{0]' already exists", e.Label), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    235             }
    236             else
    237             {
    238                 SelectedTeamType.Name = e.Label;
    239                 teamTypesListView.Items[e.Item].ToolTipText = SelectedTeamType.Name;
    240             }
    241         }
    242 
    243         private void teamsDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
    244         {
    245             if (SelectedTeamType == null)
    246             {
    247                 return;
    248             }
    249 
    250             TeamTypeClass teamTypeClass = null;
    251             if (e.RowIndex == classEditRow)
    252             {
    253                 teamTypeClass = mockClass;
    254             }
    255             else if (e.RowIndex < SelectedTeamType.Classes.Count)
    256             {
    257                 teamTypeClass = SelectedTeamType.Classes[e.RowIndex];
    258             }
    259 
    260             if (teamTypeClass == null)
    261             {
    262                 return;
    263             }
    264 
    265             switch (e.ColumnIndex)
    266             {
    267                 case 0:
    268                     e.Value = teamTypeClass.Type;
    269                     break;
    270                 case 1:
    271                     e.Value = teamTypeClass.Count;
    272                     break;
    273             }
    274         }
    275 
    276         private void teamsDataGridView_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)
    277         {
    278             if (SelectedTeamType == null)
    279             {
    280                 return;
    281             }
    282 
    283             if (mockClass == null)
    284             {
    285                 mockClass = (e.RowIndex < SelectedTeamType.Classes.Count) ?
    286                     new TeamTypeClass { Type = SelectedTeamType.Classes[e.RowIndex].Type, Count = SelectedTeamType.Classes[e.RowIndex].Count } :
    287                     new TeamTypeClass { Type = technoTypes.First(), Count = 0 };
    288             }
    289             classEditRow = e.RowIndex;
    290 
    291             switch (e.ColumnIndex)
    292             {
    293                 case 0:
    294                     mockClass.Type = e.Value as ITechnoType;
    295                     break;
    296                 case 1:
    297                     mockClass.Count = int.TryParse(e.Value as string, out int value) ? (byte)Math.Max(0, Math.Min(255, value)) : (byte)0;
    298                     break;
    299             }
    300         }
    301 
    302         private void teamsDataGridView_NewRowNeeded(object sender, DataGridViewRowEventArgs e)
    303         {
    304             mockClass = new TeamTypeClass { Type = technoTypes.First(), Count = 0 };
    305             classEditRow = teamsDataGridView.RowCount - 1;
    306         }
    307 
    308         private void teamsDataGridView_RowValidated(object sender, DataGridViewCellEventArgs e)
    309         {
    310             if ((mockClass != null) && (e.RowIndex >= SelectedTeamType.Classes.Count) && ((teamsDataGridView.Rows.Count > 1) || (e.RowIndex < (teamsDataGridView.Rows.Count - 1))))
    311             {
    312                 SelectedTeamType.Classes.Add(mockClass);
    313                 mockClass = null;
    314                 classEditRow = -1;
    315             }
    316             else if ((mockClass != null) && (e.RowIndex < SelectedTeamType.Classes.Count))
    317             {
    318                 SelectedTeamType.Classes[e.RowIndex] = mockClass;
    319                 mockClass = null;
    320                 classEditRow = -1;
    321             }
    322             else if (teamsDataGridView.ContainsFocus)
    323             {
    324                 mockClass = null;
    325                 classEditRow = -1;
    326             }
    327         }
    328 
    329         private void teamsDataGridView_RowDirtyStateNeeded(object sender, QuestionEventArgs e)
    330         {
    331             e.Response = teamsDataGridView.IsCurrentCellDirty;
    332         }
    333 
    334         private void teamsDataGridView_CancelRowEdit(object sender, QuestionEventArgs e)
    335         {
    336             if ((classEditRow == (teamsDataGridView.Rows.Count - 2)) && (classEditRow == SelectedTeamType.Classes.Count))
    337             {
    338                 mockClass = new TeamTypeClass { Type = technoTypes.First(), Count = 0 };
    339             }
    340             else
    341             {
    342                 mockClass = null;
    343                 classEditRow = -1;
    344             }
    345         }
    346 
    347         private void teamsDataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
    348         {
    349             if (e.Row.Index < SelectedTeamType.Classes.Count)
    350             {
    351                 SelectedTeamType.Classes.RemoveAt(e.Row.Index);
    352             }
    353 
    354             if (e.Row.Index == classEditRow)
    355             {
    356                 mockClass = null;
    357                 classEditRow = -1;
    358             }
    359         }
    360 
    361         private void teamsDataGridView_UserAddedRow(object sender, DataGridViewRowEventArgs e)
    362         {
    363             updateDataGridViewAddRows(teamsDataGridView, Globals.MaxTeamClasses);
    364         }
    365 
    366         private void teamsDataGridView_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
    367         {
    368             updateDataGridViewAddRows(teamsDataGridView, Globals.MaxTeamClasses);
    369         }
    370 
    371         private void missionsDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
    372         {
    373             if (SelectedTeamType == null)
    374             {
    375                 return;
    376             }
    377 
    378             TeamTypeMission teamMissionType = null;
    379             if (e.RowIndex == missionEditRow)
    380             {
    381                 teamMissionType = mockMission;
    382             }
    383             else if (e.RowIndex < SelectedTeamType.Missions.Count)
    384             {
    385                 teamMissionType = SelectedTeamType.Missions[e.RowIndex];
    386             }
    387 
    388             if (teamMissionType == null)
    389             {
    390                 return;
    391             }
    392 
    393             switch (e.ColumnIndex)
    394             {
    395                 case 0:
    396                     e.Value = teamMissionType.Mission;
    397                     break;
    398                 case 1:
    399                     e.Value = teamMissionType.Argument;
    400                     break;
    401             }
    402         }
    403 
    404         private void missionsDataGridView_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)
    405         {
    406             if (SelectedTeamType == null)
    407             {
    408                 return;
    409             }
    410 
    411             if (mockMission == null)
    412             {
    413                 mockMission = (e.RowIndex < SelectedTeamType.Missions.Count) ?
    414                     new TeamTypeMission { Mission = SelectedTeamType.Missions[e.RowIndex].Mission, Argument = SelectedTeamType.Missions[e.RowIndex].Argument } :
    415                     new TeamTypeMission { Mission = plugin.Map.TeamMissionTypes.First(), Argument = 0 };
    416             }
    417             missionEditRow = e.RowIndex;
    418 
    419             switch (e.ColumnIndex)
    420             {
    421                 case 0:
    422                     mockMission.Mission = e.Value as string;
    423                     break;
    424                 case 1:
    425                     mockMission.Argument = int.TryParse(e.Value as string, out int value) ? value : 0;
    426                     break;
    427             }
    428         }
    429 
    430         private void missionsDataGridView_NewRowNeeded(object sender, DataGridViewRowEventArgs e)
    431         {
    432             mockMission = new TeamTypeMission { Mission = plugin.Map.TeamMissionTypes.First(), Argument = 0 };
    433             missionEditRow = missionsDataGridView.RowCount - 1;
    434         }
    435 
    436         private void missionsDataGridView_RowValidated(object sender, DataGridViewCellEventArgs e)
    437         {
    438             if ((mockMission != null) && (e.RowIndex >= SelectedTeamType.Missions.Count) && ((missionsDataGridView.Rows.Count > 1) || (e.RowIndex < (missionsDataGridView.Rows.Count - 1))))
    439             {
    440                 SelectedTeamType.Missions.Add(mockMission);
    441                 mockMission = null;
    442                 missionEditRow = -1;
    443             }
    444             else if ((mockMission != null) && (e.RowIndex < SelectedTeamType.Missions.Count))
    445             {
    446                 SelectedTeamType.Missions[e.RowIndex] = mockMission;
    447                 mockMission = null;
    448                 missionEditRow = -1;
    449             }
    450             else if (missionsDataGridView.ContainsFocus)
    451             {
    452                 mockMission = null;
    453                 missionEditRow = -1;
    454             }
    455         }
    456 
    457         private void missionsDataGridView_RowDirtyStateNeeded(object sender, QuestionEventArgs e)
    458         {
    459             e.Response = missionsDataGridView.IsCurrentCellDirty;
    460         }
    461 
    462         private void missionsDataGridView_CancelRowEdit(object sender, QuestionEventArgs e)
    463         {
    464             if ((missionEditRow == (missionsDataGridView.Rows.Count - 2)) && (missionEditRow == SelectedTeamType.Missions.Count))
    465             {
    466                 mockMission = new TeamTypeMission { Mission = plugin.Map.TeamMissionTypes.First(), Argument = 0 };
    467             }
    468             else
    469             {
    470                 mockMission = null;
    471                 missionEditRow = -1;
    472             }
    473         }
    474 
    475         private void missionsDataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
    476         {
    477             if (e.Row.Index < SelectedTeamType.Missions.Count)
    478             {
    479                 SelectedTeamType.Missions.RemoveAt(e.Row.Index);
    480             }
    481 
    482             if (e.Row.Index == missionEditRow)
    483             {
    484                 mockMission = null;
    485                 missionEditRow = -1;
    486             }
    487         }
    488 
    489         private void missionsDataGridView_UserAddedRow(object sender, DataGridViewRowEventArgs e)
    490         {
    491             updateDataGridViewAddRows(missionsDataGridView, Globals.MaxTeamMissions);
    492         }
    493 
    494         private void missionsDataGridView_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
    495         {
    496             updateDataGridViewAddRows(missionsDataGridView, Globals.MaxTeamMissions);
    497         }
    498 
    499         private void updateDataGridViewAddRows(DataGridView dataGridView, int maxItems)
    500         {
    501             dataGridView.AllowUserToAddRows = dataGridView.Rows.Count <= maxItems;
    502         }
    503     }
    504 }