|
@@ -24,6 +24,12 @@ internal class Scene : OpenGlControlBase
|
|
|
|
|
|
public static readonly StyledProperty<VecI> ContentPositionProperty = AvaloniaProperty.Register<Scene, VecI>(
|
|
|
nameof(ContentPosition));
|
|
|
+
|
|
|
+ public static readonly StyledProperty<VecD> CenterProperty = AvaloniaProperty.Register<Scene, VecD>(
|
|
|
+ nameof(Center));
|
|
|
+
|
|
|
+ public static readonly StyledProperty<VecD> DimensionsProperty = AvaloniaProperty.Register<Scene, VecD>(
|
|
|
+ nameof(Dimensions));
|
|
|
|
|
|
public static readonly StyledProperty<DocumentViewModel> DocumentProperty = AvaloniaProperty.Register<Scene, DocumentViewModel>(
|
|
|
nameof(Document));
|
|
@@ -48,6 +54,18 @@ internal class Scene : OpenGlControlBase
|
|
|
get => GetValue(ContentPositionProperty);
|
|
|
set => SetValue(ContentPositionProperty, value);
|
|
|
}
|
|
|
+
|
|
|
+ public VecD Center
|
|
|
+ {
|
|
|
+ get => GetValue(CenterProperty);
|
|
|
+ set => SetValue(CenterProperty, value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public VecD Dimensions
|
|
|
+ {
|
|
|
+ get => GetValue(DimensionsProperty);
|
|
|
+ set => SetValue(DimensionsProperty, value);
|
|
|
+ }
|
|
|
|
|
|
public double Scale
|
|
|
{
|
|
@@ -61,7 +79,7 @@ internal class Scene : OpenGlControlBase
|
|
|
set => SetValue(SurfaceProperty, value);
|
|
|
}
|
|
|
|
|
|
- public Rect FinalBounds => new Rect(100, 100, Bounds.Width - 200, Bounds.Height - 200);
|
|
|
+ public Rect FinalBounds => new Rect((Bounds.Width - Bounds.Width/2 )/2, (Bounds.Height - Bounds.Height/2 )/2, Bounds.Width/2, Bounds.Height/2);
|
|
|
|
|
|
private SKSurface _outputSurface;
|
|
|
private SKPaint _paint = new SKPaint();
|
|
@@ -93,6 +111,8 @@ internal class Scene : OpenGlControlBase
|
|
|
GRGlFramebufferInfo frameBuffer = new GRGlFramebufferInfo(0, SKColorType.Rgba8888.ToGlSizedFormat());
|
|
|
GRBackendRenderTarget desc = new GRBackendRenderTarget((int)Bounds.Width, (int)Bounds.Height, 4, 0, frameBuffer);
|
|
|
_outputSurface = SKSurface.Create(gr, desc, GRSurfaceOrigin.BottomLeft, SKImageInfo.PlatformColorType);
|
|
|
+
|
|
|
+ //FinalBounds = new(dime)
|
|
|
}
|
|
|
|
|
|
protected override void OnOpenGlRender(GlInterface gl, int fb)
|
|
@@ -106,44 +126,42 @@ internal class Scene : OpenGlControlBase
|
|
|
canvas.Clear(SKColors.Transparent);
|
|
|
|
|
|
var scale = CalculateFinalScale();
|
|
|
+ float radians = (float)(Angle * Math.PI / 180);
|
|
|
|
|
|
/*canvas.RotateDegrees((float)Angle, ContentPosition.X, ContentPosition.Y);
|
|
|
canvas.Scale(scale, scale, ContentPosition.X, ContentPosition.Y);
|
|
|
|
|
|
canvas.Translate(ContentPosition.X, ContentPosition.Y);*/
|
|
|
|
|
|
- float radians = (float)(Angle * Math.PI / 180);
|
|
|
- VecD topLeft = SurfaceToViewport(new VecI(0, 0), scale, radians);
|
|
|
- VecD bottomRight = SurfaceToViewport(Surface.Size, scale, radians);
|
|
|
- VecD topRight = SurfaceToViewport(new VecI(Surface.Size.X, 0), scale, radians);
|
|
|
- VecD bottomLeft = SurfaceToViewport(new VecI(0, Surface.Size.Y), scale, radians);
|
|
|
+
|
|
|
+ RectD viewport = new(FinalBounds.X, FinalBounds.Y, FinalBounds.Width, FinalBounds.Height);
|
|
|
|
|
|
- bool topLeftWithinBounds = IsWithinBounds(topLeft, FinalBounds);
|
|
|
- bool bottomRightWithinBounds = IsWithinBounds(bottomRight, FinalBounds);
|
|
|
- bool topRightWithinBounds = IsWithinBounds(topRight, FinalBounds);
|
|
|
- bool bottomLeftWithinBounds = IsWithinBounds(bottomLeft, FinalBounds);
|
|
|
-
|
|
|
- int withinBoundsCount = 0;
|
|
|
- if (topLeftWithinBounds) withinBoundsCount++;
|
|
|
- if (bottomRightWithinBounds) withinBoundsCount++;
|
|
|
- if (topRightWithinBounds) withinBoundsCount++;
|
|
|
- if (bottomLeftWithinBounds) withinBoundsCount++;
|
|
|
-
|
|
|
- RectD viewport = new RectD(FinalBounds.X, FinalBounds.Y, FinalBounds.Width, FinalBounds.Height);
|
|
|
- RectD canvasViewRectAabb = RectD.CreateAABB(topLeft, bottomRight, topRight, bottomLeft);
|
|
|
-
|
|
|
- bool isViewportContained = canvasViewRectAabb.IntersectsWithInclusive(viewport);
|
|
|
-
|
|
|
- _paint.Color = SKColors.Green;
|
|
|
- canvas.DrawCircle((float)topLeft.X, (float)topLeft.Y, 5, _paint);
|
|
|
- canvas.DrawCircle((float)bottomRight.X, (float)bottomRight.Y, 5, _paint);
|
|
|
- canvas.DrawCircle((float)topRight.X, (float)topRight.Y, 5, _paint);
|
|
|
- canvas.DrawCircle((float)bottomLeft.X, (float)bottomLeft.Y, 5, _paint);
|
|
|
|
|
|
_paint.Color = SKColors.Blue;
|
|
|
DrawDebugRect(canvas, viewport);
|
|
|
-
|
|
|
- if (withinBoundsCount == 0 && !isViewportContained)
|
|
|
+
|
|
|
+
|
|
|
+ ShapeCorners surfaceInViewportSpace = SurfaceToViewport(new RectI(VecI.Zero, Surface.Size), scale, radians);
|
|
|
+ RectI surfaceBoundsInViewportSpace = (RectI)surfaceInViewportSpace.AABBBounds.RoundOutwards();
|
|
|
+ RectI viewportBoundsInViewportSpace = (RectI)(new RectD(FinalBounds.X, FinalBounds.Y, FinalBounds.Width, FinalBounds.Height)).RoundOutwards();
|
|
|
+ RectI firstIntersectionInViewportSpace = surfaceBoundsInViewportSpace.Intersect(viewportBoundsInViewportSpace);
|
|
|
+ ShapeCorners firstIntersectionInSurfaceSpace = ViewportToSurface(firstIntersectionInViewportSpace, scale, radians);
|
|
|
+ RectI firstIntersectionBoundsInSurfaceSpace = (RectI)firstIntersectionInSurfaceSpace.AABBBounds.RoundOutwards();
|
|
|
+
|
|
|
+ ShapeCorners viewportInSurfaceSpace = new ShapeCorners(Center, Dimensions / 2).AsRotated(-radians, Center);
|
|
|
+ RectD viewportBoundsInSurfaceSpace = viewportInSurfaceSpace.AABBBounds;
|
|
|
+ RectD surfaceBoundsInSurfaceSpace = new(VecD.Zero, Surface.Size);
|
|
|
+ RectI secondIntersectionInSurfaceSpace = (RectI)viewportBoundsInSurfaceSpace.Intersect(surfaceBoundsInSurfaceSpace).RoundOutwards();
|
|
|
+ //ShapeCorners secondIntersectionInViewportSpace = SurfaceToViewport(secondIntersectionInSurfaceSpace, scale, radians);
|
|
|
+ //RectI secondIntersectionBoundsInViewportSpace = (RectI)secondIntersectionInViewportSpace.AABBBounds.RoundOutwards();
|
|
|
+ //
|
|
|
+ //RectI combinedIntersectionInViewportSpace = firstIntersectionInViewportSpace.Intersect(secondIntersectionBoundsInViewportSpace);
|
|
|
+ //ShapeCorners combinedIntersectionInSurfaceSpace = ViewportToSurface(combinedIntersectionInViewportSpace, scale, radians);
|
|
|
+ //RectI combinedIntersectionBoundsInSurfaceSpace = (RectI)combinedIntersectionInSurfaceSpace.AABBBounds.RoundOutwards();
|
|
|
+
|
|
|
+ RectI surfaceRectToRender = firstIntersectionBoundsInSurfaceSpace.Intersect(secondIntersectionInSurfaceSpace);
|
|
|
+
|
|
|
+ if (surfaceRectToRender.IsZeroOrNegativeArea)
|
|
|
{
|
|
|
canvas.Restore();
|
|
|
canvas.Flush();
|
|
@@ -151,20 +169,6 @@ internal class Scene : OpenGlControlBase
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- RectI surfaceRectToRender = new RectI(0, 0, Surface.Size.X, Surface.Size.Y);
|
|
|
-
|
|
|
- if(withinBoundsCount < 4)
|
|
|
- {
|
|
|
- var topLeftCorner = new CornerInViewport(topLeft, topLeftWithinBounds, VecI.Zero);
|
|
|
- var topRightCorner = new CornerInViewport(topRight, topRightWithinBounds, new VecI(Surface.Size.X, 0));
|
|
|
- var bottomRightCorner = new CornerInViewport(bottomRight, bottomRightWithinBounds, Surface.Size);
|
|
|
- var bottomLeftCorner = new CornerInViewport(bottomLeft, bottomLeftWithinBounds, new VecI(0, Surface.Size.Y));
|
|
|
-
|
|
|
- CornersInViewport cornersInViewport = new CornersInViewport(topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner);
|
|
|
-
|
|
|
- surfaceRectToRender = cornersInViewport.ShrinkToViewport(surfaceRectToRender, IsSurfaceWithinViewportBounds);
|
|
|
- }
|
|
|
-
|
|
|
canvas.RotateDegrees((float)Angle, ContentPosition.X, ContentPosition.Y);
|
|
|
canvas.Scale(scale, scale, ContentPosition.X, ContentPosition.Y);
|
|
|
|
|
@@ -173,8 +177,8 @@ internal class Scene : OpenGlControlBase
|
|
|
|
|
|
_paint.Color = SKColors.Red;
|
|
|
DrawDebugRect(canvas, (RectD)surfaceRectToRender);
|
|
|
- /*using Image snapshot = Surface.DrawingSurface.Snapshot(surfaceRectToRender);
|
|
|
- canvas.DrawImage((SKImage)snapshot.Native, surfaceRectToRender.X, surfaceRectToRender.Y, _paint);*/
|
|
|
+ using Image snapshot = Surface.DrawingSurface.Snapshot((RectI)surfaceRectToRender);
|
|
|
+ canvas.DrawImage((SKImage)snapshot.Native, (float)surfaceRectToRender.X, (float)surfaceRectToRender.Y, _paint);
|
|
|
|
|
|
canvas.Restore();
|
|
|
|
|
@@ -191,11 +195,26 @@ internal class Scene : OpenGlControlBase
|
|
|
canvas.DrawLine((float)rect.X, (float)rect.Bottom, (float)rect.X, (float)rect.Y, _paint);
|
|
|
}
|
|
|
|
|
|
- private RectI ViewportToSurface(RectD viewportRect, float scale, float angleRadians)
|
|
|
+ private ShapeCorners ViewportToSurface(RectI viewportRect, float scale, float angleRadians)
|
|
|
{
|
|
|
- VecI start = ViewportToSurface(viewportRect.TopLeft, scale, angleRadians);
|
|
|
- VecI end = ViewportToSurface(viewportRect.BottomRight, scale, angleRadians);
|
|
|
- return RectI.FromTwoPoints(start, end);
|
|
|
+ return new ShapeCorners()
|
|
|
+ {
|
|
|
+ TopLeft = ViewportToSurface(viewportRect.TopLeft, scale, angleRadians),
|
|
|
+ TopRight = ViewportToSurface(viewportRect.TopRight, scale, angleRadians),
|
|
|
+ BottomLeft = ViewportToSurface(viewportRect.BottomLeft, scale, angleRadians),
|
|
|
+ BottomRight = ViewportToSurface(viewportRect.BottomRight, scale, angleRadians),
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ private ShapeCorners SurfaceToViewport(RectI viewportRect, float scale, float angleRadians)
|
|
|
+ {
|
|
|
+ return new ShapeCorners()
|
|
|
+ {
|
|
|
+ TopLeft = SurfaceToViewport(viewportRect.TopLeft, scale, angleRadians),
|
|
|
+ TopRight = SurfaceToViewport(viewportRect.TopRight, scale, angleRadians),
|
|
|
+ BottomLeft = SurfaceToViewport(viewportRect.BottomLeft, scale, angleRadians),
|
|
|
+ BottomRight = SurfaceToViewport(viewportRect.BottomRight, scale, angleRadians),
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
private bool IsWithinBounds(VecD point, Rect bounds)
|