From d3e477f3a1637fc2a1739556245baf7d91dbd31b Mon Sep 17 00:00:00 2001 From: Connor Slade Date: Mon, 13 Mar 2023 17:25:57 -0400 Subject: [PATCH] Improve auto-centering and fix blue color chanel clamp --- .../animation/ColorAnimation.java | 7 +++- .../java/paintingcanvas/canvas/Canvas.java | 37 ++++++++++-------- .../paintingcanvas/canvas/CanvasPanel.java | 4 ++ .../canvas/RenderLifecycle.java | 39 ++++++++++--------- .../paintingcanvas/drawable/Drawable.java | 2 +- src/main/java/paintingcanvas/misc/Misc.java | 6 ++- 6 files changed, 57 insertions(+), 38 deletions(-) diff --git a/src/main/java/paintingcanvas/animation/ColorAnimation.java b/src/main/java/paintingcanvas/animation/ColorAnimation.java index b2c2faa..54da9c5 100644 --- a/src/main/java/paintingcanvas/animation/ColorAnimation.java +++ b/src/main/java/paintingcanvas/animation/ColorAnimation.java @@ -48,6 +48,11 @@ Color lerpColor(Color _a, Color _b, double delta) { var b = _a.getBlue() + (_b.getBlue() - _a.getBlue()) * delta; var a = _a.getAlpha() + (_b.getAlpha() - _a.getAlpha()) * delta; - return new Color(Misc.clamp(0, (int) r, 255), Misc.clamp(0, (int) g, 255), Misc.clamp(255, (int) b, 255), Misc.clamp(0, (int) a, 255)); + return new Color( + Misc.clamp(0, (int) r, 255), + Misc.clamp(0, (int) g, 255), + Misc.clamp(0, (int) b, 255), + Misc.clamp(0, (int) a, 255) + ); } } diff --git a/src/main/java/paintingcanvas/canvas/Canvas.java b/src/main/java/paintingcanvas/canvas/Canvas.java index d9357cf..a16a0ee 100644 --- a/src/main/java/paintingcanvas/canvas/Canvas.java +++ b/src/main/java/paintingcanvas/canvas/Canvas.java @@ -4,8 +4,8 @@ import paintingcanvas.drawable.Drawable; import java.awt.*; +import java.awt.geom.Point2D; import java.util.List; -import java.util.Locale; import java.util.Vector; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -22,7 +22,8 @@ public class Canvas { /** * the initial size of the Canvas */ - public final Point startSize; + public final Dimension startSize; + public final Point2D.Float translation; /** * the elements that are currently on the canvas */ @@ -74,18 +75,20 @@ public Canvas() { */ public Canvas(int width, int height, String title) { super(); - this.startSize = new Point(width, height); + this.startSize = new Dimension(width, height); + this.translation = new Point2D.Float(0, 0); this.panel = new CanvasPanel(this, width, height, title); + if (globalInstance != null) + throw new RuntimeException("There can only be one Canvas instance"); + Canvas.globalInstance = this; + this.renderLifecycles.add(new RenderLifecycle.AntiAliasingLifecycle()); - if (enabledProp("paintingcanvas.autoCenter")) + if (getProp("paintingcanvas.autoCenter", true)) this.renderLifecycles.add(new RenderLifecycle.CenteringLifecycle()); - if (enabledProp("paintingcanvas.autoAdd")) + if (getProp("paintingcanvas.autoAdd", true)) this.autoAdd = true; - if (globalInstance != null) - throw new RuntimeException("There can only be one Canvas instance"); - Canvas.globalInstance = this; render(); } @@ -100,8 +103,10 @@ static public Canvas getGlobalInstance() { return globalInstance; } - private boolean enabledProp(String prop) { - return !System.getProperties().getOrDefault(prop, "").toString().toLowerCase(Locale.ROOT).equals("false"); + private boolean getProp(String prop, boolean _default) { + var val = System.getProperties().getProperty(prop); + if (val == null) return _default; + return Boolean.parseBoolean(val); } /** @@ -119,8 +124,9 @@ public void setBackgroundColor(Color color) { * @return The width of the canvas */ public int getWidth() { + if (panel == null) return startSize.width; var width = panel.getWidth(); - return width == 0 ? startSize.x : width; + return width == 0 ? startSize.width : width; } /** @@ -129,8 +135,9 @@ public int getWidth() { * @return The height of the canvas */ public int getHeight() { + if (panel == null) return startSize.height; var height = panel.getHeight(); - return height == 0 ? startSize.y : height; + return height == 0 ? startSize.height : height; } /** @@ -198,10 +205,8 @@ public void sleep(double seconds) { public void render() { // TODO: Account for the time it takes to run the render function - // (Implement the run with a loop and thread::sleep) + // (Implement the run with a loop and thread::sleep) or dont -- im sure you will get a warning for busy waiting ScheduledThreadPoolExecutor poolExecutor = new ScheduledThreadPoolExecutor(1); - poolExecutor.scheduleAtFixedRate(() -> { - panel.repaint(); - }, 0, 1000000 / fps, TimeUnit.MICROSECONDS); + poolExecutor.scheduleAtFixedRate(panel::repaint, 0, 1000000 / fps, TimeUnit.MICROSECONDS); } } diff --git a/src/main/java/paintingcanvas/canvas/CanvasPanel.java b/src/main/java/paintingcanvas/canvas/CanvasPanel.java index e7b0eca..023fe58 100644 --- a/src/main/java/paintingcanvas/canvas/CanvasPanel.java +++ b/src/main/java/paintingcanvas/canvas/CanvasPanel.java @@ -51,6 +51,10 @@ public void paintComponent(Graphics g) { canvas.frame++; if (canvas.frame < 0) return; + synchronized (canvas.translation) { + g.translate((int)canvas.translation.x, (int)canvas.translation.y); + } + synchronized (canvas.animations) { // Update animations for (int i = 0; i < canvas.animations.size(); i++) { diff --git a/src/main/java/paintingcanvas/canvas/RenderLifecycle.java b/src/main/java/paintingcanvas/canvas/RenderLifecycle.java index d6a78f2..a04433f 100644 --- a/src/main/java/paintingcanvas/canvas/RenderLifecycle.java +++ b/src/main/java/paintingcanvas/canvas/RenderLifecycle.java @@ -1,10 +1,11 @@ package paintingcanvas.canvas; -import paintingcanvas.animation.MovementAnimation; +import paintingcanvas.misc.Misc; import java.awt.*; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; +import java.awt.geom.Point2D; public interface RenderLifecycle { default void renderStart(Graphics g) { @@ -45,36 +46,36 @@ public void renderStart(Graphics g) { } class CenteringLifecycle implements RenderLifecycle { - private static Dimension lastSize; + final int error = 50; + private Point2D.Double lastSize; + private boolean active = false; @Override public void onResize(CanvasPanel canvasComponent, ComponentEvent e) { - if (lastSize == null) { - lastSize = e.getComponent().getSize(); + if (e.getComponent() == null) return; + var canvas = Canvas.getGlobalInstance(); + if (lastSize == null || !this.active) { + var size = e.getComponent().getSize(); + lastSize = new Point2D.Double(size.width, size.height); + if (Misc.equality(lastSize.x, canvas.startSize.width, error) && + Misc.equality(lastSize.y, canvas.startSize.height, error)) + active = true; return; } - var canvas = Canvas.getGlobalInstance(); - var newSize = canvasComponent.jframe.getSize(); + var _newSize = canvasComponent.jframe.getSize(); + var newSize = new Point2D.Double(_newSize.width, _newSize.height); if (lastSize.equals(newSize)) return; - var widthDiff = (newSize.width - lastSize.width) / 2f; - var heightDiff = (newSize.height - lastSize.height) / 2f; + var widthDiff = (newSize.x - lastSize.x) / 2f; + var heightDiff = (newSize.y - lastSize.y) / 2f; lastSize = newSize; - synchronized (canvas.elements) { - canvas.elements.forEach(s -> { - s.x += widthDiff; - s.y += heightDiff; - }); + synchronized (canvas.translation) { + var old = canvas.translation; + canvas.translation.setLocation(old.x + widthDiff, old.y + heightDiff); } - canvas.animations.stream().filter(a -> a instanceof MovementAnimation).forEach(s -> { - var anim = (MovementAnimation) s; - anim.start = new Point(anim.start.x + (int) widthDiff, anim.start.y + (int) heightDiff); - anim.end = new Point(anim.end.x + (int) widthDiff, anim.end.y + (int) heightDiff); - }); - canvas.panel.jframe.repaint(); } } diff --git a/src/main/java/paintingcanvas/drawable/Drawable.java b/src/main/java/paintingcanvas/drawable/Drawable.java index 742efc9..334794a 100644 --- a/src/main/java/paintingcanvas/drawable/Drawable.java +++ b/src/main/java/paintingcanvas/drawable/Drawable.java @@ -137,7 +137,7 @@ public void render(Graphics g) { var gc = (Graphics2D) g; var transform = gc.getTransform(); var center = this.center(g); - transform.setToRotation(this.rotation, center.x, center.y); + transform.rotate(this.rotation, center.x, center.y); gc.setTransform(transform); // if filled, draw filled then outline diff --git a/src/main/java/paintingcanvas/misc/Misc.java b/src/main/java/paintingcanvas/misc/Misc.java index 4e7e201..88ab1df 100644 --- a/src/main/java/paintingcanvas/misc/Misc.java +++ b/src/main/java/paintingcanvas/misc/Misc.java @@ -6,4 +6,8 @@ public static N clamp(N min, N val, N max) { if (val.doubleValue() < min.doubleValue()) return min; return val; } -} + + public static boolean equality(N a, N b, N error) { + return Math.max(a.doubleValue(), b.doubleValue()) - error.doubleValue() <= Math.min(a.doubleValue(), b.doubleValue()) + error.doubleValue(); + } +} \ No newline at end of file