ShiftLayer_UpdateableChange.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System.Runtime.InteropServices;
  2. using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
  3. using PixiEditor.DrawingApi.Core.Numerics;
  4. using PixiEditor.Numerics;
  5. namespace PixiEditor.ChangeableDocument.Changes.Drawing;
  6. internal class ShiftLayer_UpdateableChange : UpdateableChange
  7. {
  8. private List<Guid> layerGuids;
  9. private bool keepOriginal;
  10. private VecI delta;
  11. private Dictionary<Guid, CommittedChunkStorage?> originalLayerChunks = new();
  12. private List<IChangeInfo> _tempChanges = new();
  13. private int frame;
  14. [GenerateUpdateableChangeActions]
  15. public ShiftLayer_UpdateableChange(List<Guid> layerGuids, VecI delta, bool keepOriginal, int frame)
  16. {
  17. this.delta = delta;
  18. this.layerGuids = layerGuids;
  19. this.keepOriginal = keepOriginal;
  20. this.frame = frame;
  21. }
  22. public override bool InitializeAndValidate(Document target)
  23. {
  24. if (layerGuids.Count == 0)
  25. {
  26. return false;
  27. }
  28. layerGuids = target.ExtractLayers(layerGuids);
  29. foreach (var layer in layerGuids)
  30. {
  31. if (!target.HasMember(layer)) return false;
  32. }
  33. return true;
  34. }
  35. [UpdateChangeMethod]
  36. public void Update(VecI delta, bool keepOriginal)
  37. {
  38. this.delta = delta;
  39. this.keepOriginal = keepOriginal;
  40. }
  41. public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply,
  42. out bool ignoreInUndo)
  43. {
  44. originalLayerChunks = new Dictionary<Guid, CommittedChunkStorage?>();
  45. List<IChangeInfo> changes = new List<IChangeInfo>();
  46. foreach (var layerGuid in layerGuids)
  47. {
  48. var layer = target.FindMemberOrThrow<LayerNode>(layerGuid);
  49. // TODO: This now does't crash, but ignores other layer types. Think how to handle this.
  50. if (layer is not ImageLayerNode)
  51. {
  52. continue;
  53. }
  54. var area = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta, frame);
  55. var image = target.FindMemberOrThrow<ImageLayerNode>(layerGuid).GetLayerImageAtFrame(frame);
  56. changes.Add(new LayerImageArea_ChangeInfo(layerGuid, area));
  57. originalLayerChunks[layerGuid] = new(image, image.FindAffectedArea().Chunks);
  58. image.CommitChanges();
  59. }
  60. ignoreInUndo = delta.TaxicabLength == 0;
  61. return changes;
  62. }
  63. public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
  64. {
  65. _tempChanges.Clear();
  66. foreach (var layerGuid in layerGuids)
  67. {
  68. var layer = target.FindMemberOrThrow<LayerNode>(layerGuid);
  69. if (layer is not ImageLayerNode)
  70. {
  71. continue;
  72. }
  73. var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta, frame);
  74. _tempChanges.Add(new LayerImageArea_ChangeInfo(layerGuid, chunks));
  75. }
  76. return _tempChanges;
  77. }
  78. public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
  79. {
  80. List<IChangeInfo> changes = new List<IChangeInfo>();
  81. foreach (var layerGuid in layerGuids)
  82. {
  83. var layer = target.FindMemberOrThrow<LayerNode>(layerGuid);
  84. if (layer is not ImageLayerNode)
  85. {
  86. continue;
  87. }
  88. var image = target.FindMemberOrThrow<ImageLayerNode>(layerGuid).GetLayerImageAtFrame(frame);
  89. CommittedChunkStorage? originalChunks = originalLayerChunks[layerGuid];
  90. var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(image, ref originalChunks);
  91. changes.Add(new LayerImageArea_ChangeInfo(layerGuid, affected));
  92. }
  93. return changes;
  94. }
  95. public override void Dispose()
  96. {
  97. foreach (var (_, value) in originalLayerChunks)
  98. {
  99. value?.Dispose();
  100. }
  101. }
  102. }