Browse Source

Fix some bugs

Equbuxu 2 years ago
parent
commit
eae4ce4e32

+ 10 - 4
src/ChunkyImageLib/Chunk.cs

@@ -61,15 +61,21 @@ public class Chunk : IDisposable
         surface.Canvas.DrawSurface(Surface.DrawingSurface, pos.X, pos.Y, paint);
     }
     
-    public unsafe RectI? FindPreciseBounds()
+    public unsafe RectI? FindPreciseBounds(RectI? passedSearchRegion = null)
     {
         RectI? bounds = null;
-        if(returned) return bounds;
+        if (returned) 
+            return bounds;
+
+        if (passedSearchRegion is not null && !new RectI(VecI.Zero, Surface.Size).ContainsInclusive(passedSearchRegion.Value))
+            throw new ArgumentException("Passed search region lies outside of the chunk's surface", nameof(passedSearchRegion));
+
+        RectI searchRegion = passedSearchRegion ?? new RectI(VecI.Zero, Surface.Size);
         
         ulong* ptr = (ulong*)Surface.PixelBuffer;
-        for (int y = 0; y < Surface.Size.Y; y++)
+        for (int y = searchRegion.Top; y < searchRegion.Bottom; y++)
         {
-            for (int x = 0; x < Surface.Size.X; x++)
+            for (int x = searchRegion.Left; x < searchRegion.Right; x++)
             {
                 int i = y * Surface.Size.X + x;
                 // ptr[i] actually contains 4 16-bit floats. We only care about the first one which is alpha.

+ 15 - 7
src/ChunkyImageLib/ChunkyImage.cs

@@ -159,22 +159,28 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable
         }
     }
 
+    /// <summary>
+    /// Finds the precise bounds in <paramref name="suggestedResolution"/>. If there are no chunks rendered for that resolution, full res chunks are used instead.
+    /// </summary>
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
-    public RectI? FindTightCommittedBounds(ChunkResolution requestedResolution = ChunkResolution.Full)
+    public RectI? FindTightCommittedBounds(ChunkResolution suggestedResolution = ChunkResolution.Full)
     {
         lock (lockObject)
         {
             ThrowIfDisposed();
 
-            var chunkSize = requestedResolution.PixelSize();
-            var multiplier = requestedResolution.Multiplier();
+            var chunkSize = suggestedResolution.PixelSize();
+            var multiplier = suggestedResolution.Multiplier();
+            RectI scaledCommittedSize = (RectI)(new RectD(VecI.Zero, CommittedSize * multiplier)).RoundOutwards();
 
             RectI? preciseBounds = null;
             foreach (var (chunkPos, fullResChunk) in committedChunks[ChunkResolution.Full])
             {
-                if (committedChunks[requestedResolution].TryGetValue(chunkPos, out Chunk? requestedResChunk))
+                if (committedChunks[suggestedResolution].TryGetValue(chunkPos, out Chunk? requestedResChunk))
                 {
-                    RectI? chunkPreciseBounds = requestedResChunk.FindPreciseBounds();
+                    RectI visibleArea = new RectI(chunkPos * chunkSize, new VecI(chunkSize)).Intersect(scaledCommittedSize).Translate(-chunkPos * chunkSize);
+
+                    RectI? chunkPreciseBounds = requestedResChunk.FindPreciseBounds(visibleArea);
                     if (chunkPreciseBounds is null)
                         continue;
                     RectI globalChunkBounds = chunkPreciseBounds.Value.Offset(chunkPos * chunkSize);
@@ -184,7 +190,9 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable
                 }
                 else
                 {
-                    RectI? chunkPreciseBounds = fullResChunk.FindPreciseBounds();
+                    RectI visibleArea = new RectI(chunkPos * FullChunkSize, new VecI(FullChunkSize)).Intersect(new RectI(VecI.Zero, CommittedSize)).Translate(-chunkPos * FullChunkSize);
+
+                    RectI? chunkPreciseBounds = fullResChunk.FindPreciseBounds(visibleArea);
                     if (chunkPreciseBounds is null)
                         continue;
                     RectI globalChunkBounds = (RectI)chunkPreciseBounds.Value.Scale(multiplier).Offset(chunkPos * chunkSize).RoundOutwards();
@@ -193,7 +201,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable
                     preciseBounds = preciseBounds.Value.Union(globalChunkBounds);
                 }
             }
-            preciseBounds = (RectI?)preciseBounds?.Scale(requestedResolution.InvertedMultiplier()).RoundOutwards();
+            preciseBounds = (RectI?)preciseBounds?.Scale(suggestedResolution.InvertedMultiplier()).RoundOutwards();
             preciseBounds = preciseBounds?.Intersect(new RectI(preciseBounds.Value.Pos, CommittedSize));
 
             return preciseBounds;

+ 7 - 3
src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs

@@ -53,8 +53,8 @@ internal class MemberPreviewUpdater
         if (!rerenderPreviews)
             return new List<IRenderInfo>();
 
-        Dictionary<Guid, (VecI previewSize, RectI tightBounds)?> changedMainPreviewBounds = null;
-        Dictionary<Guid, (VecI previewSize, RectI tightBounds)?> changedMaskPreviewBounds = null;
+        Dictionary<Guid, (VecI previewSize, RectI tightBounds)?>? changedMainPreviewBounds = null;
+        Dictionary<Guid, (VecI previewSize, RectI tightBounds)?>? changedMaskPreviewBounds = null;
         await Task.Run(() =>
         {
             changedMainPreviewBounds = FindChangedTightBounds(false);
@@ -62,7 +62,7 @@ internal class MemberPreviewUpdater
         }).ConfigureAwait(true);
 
         RecreatePreviewBitmaps(changedMainPreviewBounds!, changedMaskPreviewBounds!);
-        var renderInfos = await Task.Run(() => Render(changedMainPreviewBounds, changedMaskPreviewBounds)).ConfigureAwait(true);
+        var renderInfos = await Task.Run(() => Render(changedMainPreviewBounds!, changedMaskPreviewBounds)).ConfigureAwait(true);
 
         CleanupUnusedTightBounds();
 
@@ -70,12 +70,16 @@ internal class MemberPreviewUpdater
         {
             if (a.Value is not null)
                 lastMainPreviewTightBounds[a.Key] = a.Value.Value.tightBounds;
+            else
+                lastMainPreviewTightBounds.Remove(a.Key);
         }
 
         foreach (var a in changedMaskPreviewBounds)
         {
             if (a.Value is not null)
                 lastMaskPreviewTightBounds[a.Key] = a.Value.Value.tightBounds;
+            else
+                lastMaskPreviewTightBounds.Remove(a.Key);
         }
 
         return renderInfos;