BitmapOperationsUtility.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. using PixiEditor.Helpers;
  2. using PixiEditor.Models.Controllers;
  3. using PixiEditor.Models.Enums;
  4. using PixiEditor.Models.Layers;
  5. using PixiEditor.Models.Position;
  6. using PixiEditor.Models.Tools;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Collections.ObjectModel;
  10. using System.Diagnostics;
  11. using System.Linq;
  12. using System.Windows.Input;
  13. using System.Windows.Media;
  14. using System.Windows.Media.Imaging;
  15. namespace PixiEditor.Models.Controllers
  16. {
  17. public class BitmapOperationsUtility : NotifyableObject
  18. {
  19. public MouseMovementController MouseController { get; set; }
  20. public Tool SelectedTool { get; set; }
  21. private ObservableCollection<Layer> _layers = new ObservableCollection<Layer>();
  22. public ObservableCollection<Layer> Layers
  23. {
  24. get => _layers;
  25. set { if (_layers != value) { _layers = value; } }
  26. }
  27. private int _activeLayerIndex;
  28. public int ActiveLayerIndex
  29. {
  30. get => _activeLayerIndex;
  31. set
  32. {
  33. _activeLayerIndex = value;
  34. RaisePropertyChanged("ActiveLayerIndex");
  35. RaisePropertyChanged("ActiveLayer");
  36. }
  37. }
  38. private Layer _previewLayer;
  39. public Layer PreviewLayer
  40. {
  41. get { return _previewLayer; }
  42. set
  43. {
  44. _previewLayer = value;
  45. RaisePropertyChanged("PreviewLayer");
  46. }
  47. }
  48. public Layer ActiveLayer => Layers.Count > 0 ? Layers[ActiveLayerIndex] : null;
  49. public Color PrimaryColor { get; set; }
  50. public int ToolSize { get; set; }
  51. public event EventHandler<BitmapChangedEventArgs> BitmapChanged;
  52. public event EventHandler<LayersChangedEventArgs> LayersChanged;
  53. private Coordinates _lastMousePos;
  54. private BitmapPixelChanges _lastChangedPixels;
  55. public BitmapOperationsUtility()
  56. {
  57. MouseController = new MouseMovementController();
  58. MouseController.MousePositionChanged += Controller_MousePositionChanged;
  59. MouseController.StoppedRecordingChanges += MouseController_StoppedRecordingChanges;
  60. }
  61. private void MouseController_StoppedRecordingChanges(object sender, EventArgs e)
  62. {
  63. if(SelectedTool.RequiresPreviewLayer)
  64. {
  65. BitmapPixelChanges oldValues = GetOldPixelsValues(_lastChangedPixels.ChangedPixels.Keys.ToArray());
  66. Layers[ActiveLayerIndex].ApplyPixels(_lastChangedPixels);
  67. BitmapChanged?.Invoke(this, new BitmapChangedEventArgs(_lastChangedPixels, oldValues, ActiveLayerIndex));
  68. _previewLayer.Clear();
  69. }
  70. }
  71. private void Controller_MousePositionChanged(object sender, MouseMovementEventArgs e)
  72. {
  73. if(SelectedTool != null && Mouse.LeftButton == MouseButtonState.Pressed)
  74. {
  75. var mouseMove = MouseController.LastMouseMoveCoordinates.ToList();
  76. mouseMove.Reverse();
  77. if (!SelectedTool.RequiresPreviewLayer)
  78. {
  79. BitmapPixelChanges changedPixels = SelectedTool.Use(Layers[ActiveLayerIndex], mouseMove.ToArray(), PrimaryColor, ToolSize);
  80. BitmapPixelChanges oldPixelsValues = GetOldPixelsValues(changedPixels.ChangedPixels.Keys.ToArray());
  81. ActiveLayer.ApplyPixels(changedPixels);
  82. BitmapChanged?.Invoke(this, new BitmapChangedEventArgs(changedPixels, oldPixelsValues, ActiveLayerIndex));
  83. }
  84. else
  85. {
  86. UseToolOnPreviewLayer(mouseMove);
  87. }
  88. _lastMousePos = e.NewPosition;
  89. }
  90. }
  91. private BitmapPixelChanges GetOldPixelsValues(Coordinates[] coordinates)
  92. {
  93. Dictionary<Coordinates, Color> values = new Dictionary<Coordinates, Color>();
  94. Layers[ActiveLayerIndex].LayerBitmap.Lock();
  95. for (int i = 0; i < coordinates.Length; i++)
  96. {
  97. values.Add(coordinates[i], Layers[ActiveLayerIndex].LayerBitmap.GetPixel(coordinates[i].X, coordinates[i].Y));
  98. }
  99. Layers[ActiveLayerIndex].LayerBitmap.Unlock();
  100. return new BitmapPixelChanges(values);
  101. }
  102. private void UseToolOnPreviewLayer(List<Coordinates> mouseMove)
  103. {
  104. BitmapPixelChanges changedPixels;
  105. if (mouseMove[0] != _lastMousePos)
  106. {
  107. GeneratePreviewLayer();
  108. PreviewLayer.Clear();
  109. changedPixels = SelectedTool.Use(Layers[ActiveLayerIndex], mouseMove.ToArray(), PrimaryColor, ToolSize);
  110. PreviewLayer.ApplyPixels(changedPixels);
  111. _lastChangedPixels = changedPixels;
  112. }
  113. }
  114. private void GeneratePreviewLayer()
  115. {
  116. if (PreviewLayer == null)
  117. {
  118. PreviewLayer = new Layer("_previewLayer", Layers[0].Width, Layers[0].Height);
  119. }
  120. }
  121. public void AddNewLayer(string name, int height, int width, bool setAsActive = true)
  122. {
  123. Layers.Add(new Layer(name, width, height));
  124. if (setAsActive)
  125. {
  126. ActiveLayerIndex = Layers.Count - 1;
  127. }
  128. LayersChanged?.Invoke(this, new LayersChangedEventArgs(0, LayerAction.Add));
  129. }
  130. public void SetActiveLayer(int index)
  131. {
  132. ActiveLayerIndex = index;
  133. LayersChanged?.Invoke(this, new LayersChangedEventArgs(index, LayerAction.SetActive));
  134. }
  135. }
  136. }
  137. public class BitmapChangedEventArgs : EventArgs
  138. {
  139. public BitmapPixelChanges PixelsChanged { get; set; }
  140. public BitmapPixelChanges OldPixelsValues { get; set; }
  141. public int ChangedLayerIndex { get; set; }
  142. public BitmapChangedEventArgs(BitmapPixelChanges pixelsChanged, BitmapPixelChanges oldPixelsValues, int changedLayerIndex)
  143. {
  144. PixelsChanged = pixelsChanged;
  145. OldPixelsValues = oldPixelsValues;
  146. ChangedLayerIndex = changedLayerIndex;
  147. }
  148. }
  149. public class LayersChangedEventArgs : EventArgs
  150. {
  151. public int LayerAffected { get; set; }
  152. public LayerAction LayerChangeType { get; set; }
  153. public LayersChangedEventArgs(int layerAffected, LayerAction layerChangeType)
  154. {
  155. LayerAffected = layerAffected;
  156. LayerChangeType = layerChangeType;
  157. }
  158. }