diff --git a/VGAPainter/App.config b/VGAPainter/App.config index 56efbc7..74ade9d 100644 --- a/VGAPainter/App.config +++ b/VGAPainter/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/VGAPainter/MainForm.Designer.cs b/VGAPainter/MainForm.Designer.cs index 2e9ce6a..639b46b 100644 --- a/VGAPainter/MainForm.Designer.cs +++ b/VGAPainter/MainForm.Designer.cs @@ -44,6 +44,9 @@ private void InitializeComponent() this.undoAction = new System.Windows.Forms.ToolStripMenuItem(); this.redoAction = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); + this.drawToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.fillToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.pixerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); this.showPalette = new System.Windows.Forms.ToolStripMenuItem(); this.loadPaletteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -68,9 +71,6 @@ private void InitializeComponent() this.canvasBox = new System.Windows.Forms.PictureBox(); this.openTgr = new System.Windows.Forms.OpenFileDialog(); this.openFileDialog2 = new System.Windows.Forms.OpenFileDialog(); - this.drawToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.fillToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.pixerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.panel1 = new System.Windows.Forms.Panel(); this.menuStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.canvasBox)).BeginInit(); @@ -186,7 +186,7 @@ private void InitializeComponent() // this.undoAction.Name = "undoAction"; this.undoAction.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z))); - this.undoAction.Size = new System.Drawing.Size(180, 22); + this.undoAction.Size = new System.Drawing.Size(148, 22); this.undoAction.Text = "&Undo"; this.undoAction.Click += new System.EventHandler(this.UndoAction_Click); // @@ -194,24 +194,53 @@ private void InitializeComponent() // this.redoAction.Name = "redoAction"; this.redoAction.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Y))); - this.redoAction.Size = new System.Drawing.Size(180, 22); + this.redoAction.Size = new System.Drawing.Size(148, 22); this.redoAction.Text = "&Redo"; this.redoAction.Click += new System.EventHandler(this.RedoAction_Click); // // toolStripSeparator8 // this.toolStripSeparator8.Name = "toolStripSeparator8"; - this.toolStripSeparator8.Size = new System.Drawing.Size(177, 6); + this.toolStripSeparator8.Size = new System.Drawing.Size(145, 6); + // + // drawToolStripMenuItem + // + this.drawToolStripMenuItem.Checked = true; + this.drawToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; + this.drawToolStripMenuItem.Name = "drawToolStripMenuItem"; + this.drawToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F5; + this.drawToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.drawToolStripMenuItem.Tag = VGAPainter.DrawMode.Pixel; + this.drawToolStripMenuItem.Text = "&Draw"; + this.drawToolStripMenuItem.Click += new System.EventHandler(this.DrawTool_Select); + // + // fillToolStripMenuItem + // + this.fillToolStripMenuItem.Name = "fillToolStripMenuItem"; + this.fillToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F6; + this.fillToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.fillToolStripMenuItem.Tag = VGAPainter.DrawMode.Fill; + this.fillToolStripMenuItem.Text = "&Fill"; + this.fillToolStripMenuItem.Click += new System.EventHandler(this.DrawTool_Select); + // + // pixerToolStripMenuItem + // + this.pixerToolStripMenuItem.Name = "pixerToolStripMenuItem"; + this.pixerToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F8; + this.pixerToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.pixerToolStripMenuItem.Tag = VGAPainter.DrawMode.Picker; + this.pixerToolStripMenuItem.Text = "&Picker"; + this.pixerToolStripMenuItem.Click += new System.EventHandler(this.DrawTool_Select); // // toolStripSeparator3 // this.toolStripSeparator3.Name = "toolStripSeparator3"; - this.toolStripSeparator3.Size = new System.Drawing.Size(177, 6); + this.toolStripSeparator3.Size = new System.Drawing.Size(145, 6); // // showPalette // this.showPalette.Name = "showPalette"; - this.showPalette.Size = new System.Drawing.Size(180, 22); + this.showPalette.Size = new System.Drawing.Size(148, 22); this.showPalette.Text = "&Show Palette"; this.showPalette.Click += new System.EventHandler(this.ShowPalette_Click); // @@ -219,7 +248,7 @@ private void InitializeComponent() // this.loadPaletteToolStripMenuItem.Enabled = false; this.loadPaletteToolStripMenuItem.Name = "loadPaletteToolStripMenuItem"; - this.loadPaletteToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.loadPaletteToolStripMenuItem.Size = new System.Drawing.Size(148, 22); this.loadPaletteToolStripMenuItem.Text = "&Load Palette..."; // // menuView @@ -391,35 +420,6 @@ private void InitializeComponent() // this.openFileDialog2.FileName = "openFileDialog2"; // - // drawToolStripMenuItem - // - this.drawToolStripMenuItem.Checked = true; - this.drawToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; - this.drawToolStripMenuItem.Name = "drawToolStripMenuItem"; - this.drawToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F5; - this.drawToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.drawToolStripMenuItem.Tag = VGAPainter.DrawMode.Pixel; - this.drawToolStripMenuItem.Text = "&Draw"; - this.drawToolStripMenuItem.Click += new System.EventHandler(this.DrawTool_Select); - // - // fillToolStripMenuItem - // - this.fillToolStripMenuItem.Name = "fillToolStripMenuItem"; - this.fillToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F6; - this.fillToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.fillToolStripMenuItem.Tag = VGAPainter.DrawMode.Fill; - this.fillToolStripMenuItem.Text = "&Fill"; - this.fillToolStripMenuItem.Click += new System.EventHandler(this.DrawTool_Select); - // - // pixerToolStripMenuItem - // - this.pixerToolStripMenuItem.Name = "pixerToolStripMenuItem"; - this.pixerToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F8; - this.pixerToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.pixerToolStripMenuItem.Tag = VGAPainter.DrawMode.Picker; - this.pixerToolStripMenuItem.Text = "&Picker"; - this.pixerToolStripMenuItem.Click += new System.EventHandler(this.DrawTool_Select); - // // panel1 // this.panel1.AutoScroll = true; @@ -443,6 +443,7 @@ private void InitializeComponent() this.MainMenuStrip = this.menuStrip1; this.Name = "MainForm"; this.Text = "Raresh\'s VGA Painter"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); this.menuStrip1.ResumeLayout(false); this.menuStrip1.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.canvasBox)).EndInit(); diff --git a/VGAPainter/MainForm.cs b/VGAPainter/MainForm.cs index c7a2998..1396438 100644 --- a/VGAPainter/MainForm.cs +++ b/VGAPainter/MainForm.cs @@ -27,11 +27,10 @@ public partial class MainForm : Form private int bmWidth = 16, bmHeight = 16; private byte[] bmData = new byte[256]; - // canvas properties + // canvas + private Bitmap canvas; private int zoom = 5; - private int offsetX = 0; - private int offsetY = 0; - + // mouse actions private bool mouseDraw = false; private DrawMode drawMode; @@ -65,7 +64,7 @@ public MainForm() } // a few UI things - Redraw(); + FullRedraw(); UpdateStackButtons(); } @@ -209,7 +208,7 @@ private void ShowPalette_Click(object sender, EventArgs e) undoStack.Clear(); redoStack.Clear(); - Redraw(); + FullRedraw(); } #endregion @@ -251,17 +250,28 @@ private Bitmap RenderBitmap(int scale, bool grid) return bm; } + /// + /// Redraws the canvas from scratch + /// + private void FullRedraw() + { + canvas = RenderBitmap(zoom, showGrid.Checked); + Redraw(); + } + /// /// Redraws the canvas /// private void Redraw() - { - canvasBox.Image = RenderBitmap(zoom, showGrid.Checked); + { + canvasBox.Image = canvas; + canvasBox.Refresh(); + canvasBox.Update(); } private void RedrawUITrigger(object sender, EventArgs e) { - Redraw(); + FullRedraw(); } #endregion @@ -276,19 +286,19 @@ private void ViewToolStripMenuItem_Click(object sender, EventArgs e) private void ZoomIn_Click(object sender, EventArgs e) { zoom++; - Redraw(); + FullRedraw(); } private void ZoomOut_Click(object sender, EventArgs e) { if (zoom > 1) zoom--; - Redraw(); + FullRedraw(); } private void ZoomReset_Click(object sender, EventArgs e) { zoom = Int32.Parse((sender as ToolStripItem).Tag as string); - Redraw(); + FullRedraw(); } #endregion @@ -333,6 +343,10 @@ private void SaveImage_Click(object sender, EventArgs e) { // get the filename var result = saveTgr.ShowDialog(this); + if (result == DialogResult.Cancel && e is FormClosingEventArgs) + { + (e as FormClosingEventArgs).Cancel = true; + } if (result != DialogResult.OK) return; // save the image @@ -378,17 +392,18 @@ private void DoMouse(int mouseX, int mouseY) // don't do anything out of scope if (mouseX >= bmWidth || mouseY >= bmHeight) return; - // pre-calc image offset + // precalc offset and boundary check int offset = mouseY * bmWidth + mouseX; if (offset < 0 || offset >= bmData.Length) return; + // pixel changes to commit to history + var changes = new HashSet(); + switch (drawMode) { case DrawMode.Pixel: - var oldColor = bmData[offset]; - if (color == oldColor) break; // do nothing if the color is the same - bmData[offset] = color; - undoStack.Push(new HistoryEvent(new PixelChange(offset, oldColor, color))); + var change = DrawPixel(mouseX, mouseY, color); + if (change != null) changes.Add(change); redoStack.Clear(); break; case DrawMode.Picker: @@ -398,8 +413,13 @@ private void DoMouse(int mouseX, int mouseY) throw new NotImplementedException("Draw mode " + drawMode.ToString() + " not implemented."); } - Redraw(); + // undo/redo stack things + if (changes.Count > 0) + undoStack.Push(new HistoryEvent(changes)); UpdateStackButtons(); + + // trigger canvasBox redraw + Redraw(); } private void NewToolStripMenuItem_Click(object sender, EventArgs e) @@ -412,7 +432,7 @@ private void NewToolStripMenuItem_Click(object sender, EventArgs e) bmHeight = (int)newDialog.bmHeight.Value; bmData = new byte[bmWidth * bmHeight]; - Redraw(); + FullRedraw(); } private void CanvasBox_MouseDown(object sender, MouseEventArgs e) @@ -440,6 +460,29 @@ private void CanvasBox_MouseLeave(object sender, EventArgs e) #endregion + private PixelChange DrawPixel(int x, int y, byte color) + { + // precalc offset and check boundary + int offset = y * bmWidth + x; + if (offset < 0 || offset >= bmData.Length) return null; + + // don't do anything if the pixel is the same + if (bmData[offset] == color) return null; + + // change the pixel and note the change + var change = new PixelChange(offset, bmData[offset], color); + bmData[offset] = color; + + // update the bitmap + var gfx = Graphics.FromImage(canvas); + gfx.FillRectangle(new SolidBrush(vgaPalette[color]), + x * zoom, y * zoom, + zoom - (showGrid.Checked ? 1 : 0), + zoom - (showGrid.Checked ? 1 : 0)); + + return change; + } + private void AboutToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show(this, "VGAPainter by thegreatrazz\n" + @@ -466,7 +509,9 @@ private void UndoAction_Click(object sender, EventArgs e) // undo it foreach (var change in action.changes) { - bmData[change.Offset] = change.OldColor; + int x = change.Offset % bmWidth; + int y = change.Offset / bmWidth; + DrawPixel(x, y, change.OldColor); } // put it on the redo stack @@ -484,7 +529,9 @@ private void RedoAction_Click(object sender, EventArgs e) // undo it foreach (var change in action.changes) { - bmData[change.Offset] = change.NewColor; + int x = change.Offset % bmWidth; + int y = change.Offset / bmWidth; + DrawPixel(x, y, change.NewColor); } // put it on the redo stack @@ -494,6 +541,19 @@ private void RedoAction_Click(object sender, EventArgs e) UpdateStackButtons(); } + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + if (undoStack.Count > 0) + { + var result = MessageBox.Show("Would you like to save your work before quitting?", "Save and Quit", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning); + if (result == DialogResult.Cancel) e.Cancel = true; + if (result == DialogResult.Yes) + { + SaveImage_Click(sender, e); + } + } + } + private void DrawTool_Select(object sender, EventArgs e) { foreach (var el in menuEdit.DropDownItems) diff --git a/VGAPainter/Properties/AssemblyInfo.cs b/VGAPainter/Properties/AssemblyInfo.cs index 2603970..bf317e8 100644 --- a/VGAPainter/Properties/AssemblyInfo.cs +++ b/VGAPainter/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.0.2.0")] -[assembly: AssemblyFileVersion("0.0.2.0")] +[assembly: AssemblyVersion("0.0.3.0")] +[assembly: AssemblyFileVersion("0.0.3.0")] diff --git a/VGAPainter/Properties/Resources.Designer.cs b/VGAPainter/Properties/Resources.Designer.cs index a5fc5a4..1f23e14 100644 --- a/VGAPainter/Properties/Resources.Designer.cs +++ b/VGAPainter/Properties/Resources.Designer.cs @@ -8,10 +8,10 @@ // //------------------------------------------------------------------------------ -namespace VGAPainter.Properties -{ - - +namespace VGAPainter.Properties { + using System; + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -19,51 +19,43 @@ namespace VGAPainter.Properties // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources - { - + internal class Resources { + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() - { + internal Resources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager - { - get - { - if ((resourceMan == null)) - { + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VGAPainter.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture - { - get - { + internal static global::System.Globalization.CultureInfo Culture { + get { return resourceCulture; } - set - { + set { resourceCulture = value; } } diff --git a/VGAPainter/Properties/Settings.Designer.cs b/VGAPainter/Properties/Settings.Designer.cs index e78a05a..343ff85 100644 --- a/VGAPainter/Properties/Settings.Designer.cs +++ b/VGAPainter/Properties/Settings.Designer.cs @@ -8,21 +8,17 @@ // //------------------------------------------------------------------------------ -namespace VGAPainter.Properties -{ - - +namespace VGAPainter.Properties { + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.2.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { + + public static Settings Default { + get { return defaultInstance; } } diff --git a/VGAPainter/VGAPainter.csproj b/VGAPainter/VGAPainter.csproj index c0db77f..1103d91 100644 --- a/VGAPainter/VGAPainter.csproj +++ b/VGAPainter/VGAPainter.csproj @@ -8,10 +8,11 @@ WinExe VGAPainter VGAPainter - v4.7.2 + v4.0 512 true true + AnyCPU @@ -44,7 +45,6 @@ - @@ -78,6 +78,7 @@ True Resources.resx + True SettingsSingleFileGenerator