CnC_Remastered_Collection

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

SmudgeTool.cs (11061B)


      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.Controls;
     16 using MobiusEditor.Event;
     17 using MobiusEditor.Interface;
     18 using MobiusEditor.Model;
     19 using MobiusEditor.Utility;
     20 using MobiusEditor.Widgets;
     21 using System;
     22 using System.Drawing;
     23 using System.Linq;
     24 using System.Windows.Forms;
     25 
     26 namespace MobiusEditor.Tools
     27 {
     28     public class SmudgeTool : ViewTool
     29     {
     30         private readonly TypeComboBox smudgeTypeComboBox;
     31         private readonly MapPanel smudgeTypeMapPanel;
     32 
     33         private Map previewMap;
     34         protected override Map RenderMap => previewMap;
     35 
     36         private bool placementMode;
     37 
     38         private SmudgeType selectedSmudgeType;
     39         private SmudgeType SelectedSmudgeType
     40         {
     41             get => selectedSmudgeType;
     42             set
     43             {
     44                 if (selectedSmudgeType != value)
     45                 {
     46                     if (placementMode && (selectedSmudgeType != null))
     47                     {
     48                         mapPanel.Invalidate(map, navigationWidget.MouseCell);
     49                     }
     50 
     51                     selectedSmudgeType = value;
     52                     smudgeTypeComboBox.SelectedValue = selectedSmudgeType;
     53 
     54                     if (placementMode && (selectedSmudgeType != null))
     55                     {
     56                         mapPanel.Invalidate(map, navigationWidget.MouseCell);
     57                     }
     58 
     59                     RefreshMapPanel();
     60                 }
     61             }
     62         }
     63 
     64         public SmudgeTool(MapPanel mapPanel, MapLayerFlag layers, ToolStripStatusLabel statusLbl, TypeComboBox smudgeTypeComboBox, MapPanel smudgeTypeMapPanel, IGamePlugin plugin, UndoRedoList<UndoRedoEventArgs> url)
     65             : base(mapPanel, layers, statusLbl, plugin, url)
     66         {
     67             previewMap = map;
     68 
     69             this.mapPanel.MouseDown += MapPanel_MouseDown;
     70             this.mapPanel.MouseMove += MapPanel_MouseMove;
     71             (this.mapPanel as Control).KeyDown += SmudgeTool_KeyDown;
     72             (this.mapPanel as Control).KeyUp += SmudgeTool_KeyUp;
     73 
     74             this.smudgeTypeComboBox = smudgeTypeComboBox;
     75             this.smudgeTypeComboBox.SelectedIndexChanged += SmudgeTypeComboBox_SelectedIndexChanged;
     76 
     77             this.smudgeTypeMapPanel = smudgeTypeMapPanel;
     78             this.smudgeTypeMapPanel.BackColor = Color.White;
     79             this.smudgeTypeMapPanel.MaxZoom = 1;
     80 
     81             navigationWidget.MouseCellChanged += MouseoverWidget_MouseCellChanged;
     82 
     83             SelectedSmudgeType = smudgeTypeComboBox.Types.First() as SmudgeType;
     84 
     85             UpdateStatus();
     86         }
     87 
     88         private void SmudgeTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)
     89         {
     90             SelectedSmudgeType = smudgeTypeComboBox.SelectedValue as SmudgeType;
     91         }
     92 
     93         private void SmudgeTool_KeyDown(object sender, KeyEventArgs e)
     94         {
     95             if (e.KeyCode == Keys.ShiftKey)
     96             {
     97                 EnterPlacementMode();
     98             }
     99         }
    100 
    101         private void SmudgeTool_KeyUp(object sender, KeyEventArgs e)
    102         {
    103             if (e.KeyCode == Keys.ShiftKey)
    104             {
    105                 ExitPlacementMode();
    106             }
    107         }
    108 
    109         private void MapPanel_MouseDown(object sender, MouseEventArgs e)
    110         {
    111             if (placementMode)
    112             {
    113                 if (e.Button == MouseButtons.Left)
    114                 {
    115                     AddSmudge(navigationWidget.MouseCell);
    116                 }
    117                 else if (e.Button == MouseButtons.Right)
    118                 {
    119                     RemoveSmudge(navigationWidget.MouseCell);
    120                 }
    121             }
    122             else if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Right))
    123             {
    124                 PickSmudge(navigationWidget.MouseCell);
    125             }
    126         }
    127 
    128         private void MapPanel_MouseMove(object sender, MouseEventArgs e)
    129         {
    130             if (!placementMode && (Control.ModifierKeys == Keys.Shift))
    131             {
    132                 EnterPlacementMode();
    133             }
    134             else if (placementMode && (Control.ModifierKeys == Keys.None))
    135             {
    136                 ExitPlacementMode();
    137             }
    138         }
    139 
    140         private void MouseoverWidget_MouseCellChanged(object sender, MouseCellChangedEventArgs e)
    141         {
    142             if (placementMode)
    143             {
    144                 if (SelectedSmudgeType != null)
    145                 {
    146                     mapPanel.Invalidate(map, e.OldCell);
    147                     mapPanel.Invalidate(map, e.NewCell);
    148                 }
    149             }
    150         }
    151 
    152         private void AddSmudge(Point location)
    153         {
    154             if (map.Smudge[location] == null)
    155             {
    156                 if (SelectedSmudgeType != null)
    157                 {
    158                     var smudge = new Smudge
    159                     {
    160                         Type = SelectedSmudgeType,
    161                         Icon = 0,
    162                         Data = 0
    163                     };
    164                     map.Smudge[location] = smudge;
    165                     mapPanel.Invalidate(map, location);
    166 
    167                     void undoAction(UndoRedoEventArgs e)
    168                     {
    169                         e.MapPanel.Invalidate(e.Map, location);
    170                         e.Map.Smudge[location] = null;
    171                     }
    172 
    173                     void redoAction(UndoRedoEventArgs e)
    174                     {
    175                         e.Map.Smudge[location] = smudge;
    176                         e.MapPanel.Invalidate(e.Map, location);
    177                     }
    178 
    179                     url.Track(undoAction, redoAction);
    180 
    181                     plugin.Dirty = true;
    182                 }
    183             }
    184         }
    185 
    186         private void RemoveSmudge(Point location)
    187         {
    188             if ((map.Smudge[location] is Smudge smudge) && ((smudge.Type.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None))
    189             {
    190                 map.Smudge[location] = null;
    191                 mapPanel.Invalidate(map, location);
    192 
    193                 void undoAction(UndoRedoEventArgs e)
    194                 {
    195                     e.Map.Smudge[location] = smudge;
    196                     e.MapPanel.Invalidate(e.Map, location);
    197                 }
    198 
    199                 void redoAction(UndoRedoEventArgs e)
    200                 {
    201                     e.MapPanel.Invalidate(e.Map, location);
    202                     e.Map.Smudge[location] = null;
    203                 }
    204 
    205                 url.Track(undoAction, redoAction);
    206 
    207                 plugin.Dirty = true;
    208             }
    209         }
    210 
    211         private void EnterPlacementMode()
    212         {
    213             if (placementMode)
    214             {
    215                 return;
    216             }
    217 
    218             placementMode = true;
    219 
    220             navigationWidget.MouseoverSize = Size.Empty;
    221 
    222             if (SelectedSmudgeType != null)
    223             {
    224                 mapPanel.Invalidate(map, navigationWidget.MouseCell);
    225             }
    226 
    227             UpdateStatus();
    228         }
    229 
    230         private void ExitPlacementMode()
    231         {
    232             if (!placementMode)
    233             {
    234                 return;
    235             }
    236 
    237             placementMode = false;
    238 
    239             navigationWidget.MouseoverSize = new Size(1, 1);
    240 
    241             if (SelectedSmudgeType != null)
    242             {
    243                 mapPanel.Invalidate(map, navigationWidget.MouseCell);
    244             }
    245 
    246             UpdateStatus();
    247         }
    248 
    249         private void PickSmudge(Point location)
    250         {
    251             if (map.Metrics.GetCell(location, out int cell))
    252             {
    253                 var smudge = map.Smudge[cell];
    254                 if (smudge != null)
    255                 {
    256                     SelectedSmudgeType = smudge.Type;
    257                 }
    258             }
    259         }
    260 
    261         private void RefreshMapPanel()
    262         {
    263             smudgeTypeMapPanel.MapImage = SelectedSmudgeType?.Thumbnail;
    264         }
    265 
    266         private void UpdateStatus()
    267         {
    268             if (placementMode)
    269             {
    270                 statusLbl.Text = "Left-Click to place smudge, Right-Click to remove smudge";
    271             }
    272             else
    273             {
    274                 statusLbl.Text = "Shift to enter placement mode, Left-Click or Right-Click to pick smudge";
    275             }
    276         }
    277 
    278         protected override void PreRenderMap()
    279         {
    280             base.PreRenderMap();
    281 
    282             previewMap = map.Clone();
    283             if (placementMode)
    284             {
    285                 var location = navigationWidget.MouseCell;
    286                 if (SelectedSmudgeType != null)
    287                 {
    288                     if (previewMap.Metrics.GetCell(location, out int cell))
    289                     {
    290                         if (previewMap.Smudge[cell] == null)
    291                         {
    292                             previewMap.Smudge[cell] = new Smudge { Type = SelectedSmudgeType, Data = 0, Tint = Color.FromArgb(128, Color.White) };
    293                         }
    294                     }
    295                 }
    296             }
    297         }
    298 
    299         protected override void PostRenderMap(Graphics graphics)
    300         {
    301             base.PostRenderMap(graphics);
    302 
    303             var smudgePen = new Pen(Color.Green, 4.0f);
    304             foreach (var (cell, smudge) in previewMap.Smudge.Where(x => (x.Value.Type.Flag & SmudgeTypeFlag.Bib) == SmudgeTypeFlag.None))
    305             {
    306                 previewMap.Metrics.GetLocation(cell, out Point topLeft);
    307                 var bounds = new Rectangle(new Point(topLeft.X * Globals.TileWidth, topLeft.Y * Globals.TileHeight), Globals.TileSize);
    308                 graphics.DrawRectangle(smudgePen, bounds);
    309             }
    310         }
    311 
    312         #region IDisposable Support
    313         private bool disposedValue = false;
    314 
    315         protected override void Dispose(bool disposing)
    316         {
    317             if (!disposedValue)
    318             {
    319                 if (disposing)
    320                 {
    321                     smudgeTypeComboBox.SelectedIndexChanged -= SmudgeTypeComboBox_SelectedIndexChanged;
    322 
    323                     mapPanel.MouseDown -= MapPanel_MouseDown;
    324                     mapPanel.MouseMove -= MapPanel_MouseMove;
    325                     (mapPanel as Control).KeyDown -= SmudgeTool_KeyDown;
    326                     (mapPanel as Control).KeyUp -= SmudgeTool_KeyUp;
    327 
    328                     navigationWidget.MouseCellChanged -= MouseoverWidget_MouseCellChanged;
    329                 }
    330                 disposedValue = true;
    331             }
    332 
    333             base.Dispose(disposing);
    334         }
    335         #endregion
    336     }
    337 }