From d9001bc10658baa913aa7a3c2c407d93d38716f3 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 24 Aug 2017 17:38:51 +0300 Subject: [PATCH] More abstractions --- .../main/java/com/annimon/hotarufx/Main.java | 18 +++++----- .../KeyFrameDuplicationException.java | 10 ++++++ .../annimon/hotarufx/visual/Composition.java | 34 +++++++++++-------- .../com/annimon/hotarufx/visual/KeyFrame.java | 18 ++++++++++ .../com/annimon/hotarufx/visual/TimeLine.java | 24 +++++++++++++ .../annimon/hotarufx/visual/VirtualScene.java | 20 +++++++++++ .../hotarufx/visual/objects/CircleNode.java | 7 ++-- .../hotarufx/visual/objects/ObjectNode.java | 4 +-- .../hotarufx/visual/CompositionTest.java | 6 ++-- .../annimon/hotarufx/visual/TimeLineTest.java | 24 +++++++++++++ 10 files changed, 131 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/com/annimon/hotarufx/exceptions/KeyFrameDuplicationException.java create mode 100644 app/src/main/java/com/annimon/hotarufx/visual/KeyFrame.java create mode 100644 app/src/main/java/com/annimon/hotarufx/visual/TimeLine.java create mode 100644 app/src/main/java/com/annimon/hotarufx/visual/VirtualScene.java create mode 100644 app/src/test/java/com/annimon/hotarufx/visual/TimeLineTest.java diff --git a/app/src/main/java/com/annimon/hotarufx/Main.java b/app/src/main/java/com/annimon/hotarufx/Main.java index 66a2dd6..54f7342 100644 --- a/app/src/main/java/com/annimon/hotarufx/Main.java +++ b/app/src/main/java/com/annimon/hotarufx/Main.java @@ -1,24 +1,26 @@ package com.annimon.hotarufx; import com.annimon.hotarufx.visual.Composition; +import com.annimon.hotarufx.visual.KeyFrame; import com.annimon.hotarufx.visual.objects.CircleNode; import javafx.application.Application; -import javafx.scene.Group; import javafx.scene.paint.Color; import javafx.scene.paint.Paint; import javafx.stage.Stage; +import lombok.Data; +import lombok.AllArgsConstructor; import lombok.val; public class Main extends Application { @Override public void start(Stage primaryStage) { - val group = new Group(); - val composition = new Composition(1280, 720, Color.WHITE, group); + val composition = new Composition(1280, 720, 30); + val scene = composition.newScene(KeyFrame.of(0)); val colors = new Paint[] {Color.GREEN, Color.RED}; - val halfWidth = composition.getVirtualWidth() / 2; - val halfHeight = composition.getVirtualHeight() / 2; + val halfWidth = scene.getVirtualWidth() / 2; + val halfHeight = scene.getVirtualHeight() / 2; for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { val circle = new CircleNode(); @@ -26,13 +28,9 @@ public class Main extends Application { circle.getCircle().setCenterX(x * halfWidth); circle.getCircle().setCenterY(y * halfHeight); circle.getCircle().setRadius(50); - circle.render(composition); + circle.render(scene); } } - - primaryStage.setTitle("HotaruFX"); - primaryStage.setScene(composition.getScene()); - primaryStage.show(); } public static void main(String[] args) { diff --git a/app/src/main/java/com/annimon/hotarufx/exceptions/KeyFrameDuplicationException.java b/app/src/main/java/com/annimon/hotarufx/exceptions/KeyFrameDuplicationException.java new file mode 100644 index 0000000..90f5fdd --- /dev/null +++ b/app/src/main/java/com/annimon/hotarufx/exceptions/KeyFrameDuplicationException.java @@ -0,0 +1,10 @@ +package com.annimon.hotarufx.exceptions; + +import com.annimon.hotarufx.visual.KeyFrame; + +public class KeyFrameDuplicationException extends RuntimeException { + + public KeyFrameDuplicationException(KeyFrame keyFrame) { + super("Key frame " + keyFrame.getFrame() + " already exists in timeline"); + } +} diff --git a/app/src/main/java/com/annimon/hotarufx/visual/Composition.java b/app/src/main/java/com/annimon/hotarufx/visual/Composition.java index b916e86..a13ea0c 100644 --- a/app/src/main/java/com/annimon/hotarufx/visual/Composition.java +++ b/app/src/main/java/com/annimon/hotarufx/visual/Composition.java @@ -1,19 +1,13 @@ package com.annimon.hotarufx.visual; import javafx.scene.Group; -import javafx.scene.Node; import javafx.scene.Scene; -import javafx.scene.paint.Paint; +import javafx.scene.paint.Color; import lombok.Getter; +import lombok.val; public class Composition { - @Getter - private final Group group; - - @Getter - private final Scene scene; - @Getter private final int virtualWidth, virtualHeight, @@ -21,22 +15,34 @@ public class Composition { @Getter private final double factor; - public Composition(int sceneWidth, int sceneHeight, Paint background, Group group) { + @Getter + private final double frameRate; + + @Getter + private final TimeLine timeLine; + + public Composition(int sceneWidth, int sceneHeight, double frameRate) { this.sceneWidth = sceneWidth; this.sceneHeight = sceneHeight; + this.frameRate = frameRate; virtualHeight = 1080; factor = virtualHeight / (double) sceneHeight; virtualWidth = (int) (sceneWidth * factor); + timeLine = new TimeLine(); + } + + public VirtualScene newScene(KeyFrame keyFrame) { + val group = new Group(); group.setScaleX(1d / factor); group.setScaleY(1d / factor); group.setTranslateX(sceneWidth / 2); group.setTranslateY(sceneHeight / 2); - this.group = group; - this.scene = new Scene(group, sceneWidth, sceneHeight, background); + val scene = new VirtualScene(group, virtualWidth, virtualHeight); + timeLine.add(keyFrame, scene); + return scene; } - public void add(Node node) { - group.getChildren().add(node); + public Scene produceAnimationScene(VirtualScene scene) { + return new Scene(scene.getGroup(), sceneWidth, sceneHeight, Color.WHITE); } - } diff --git a/app/src/main/java/com/annimon/hotarufx/visual/KeyFrame.java b/app/src/main/java/com/annimon/hotarufx/visual/KeyFrame.java new file mode 100644 index 0000000..2583ed3 --- /dev/null +++ b/app/src/main/java/com/annimon/hotarufx/visual/KeyFrame.java @@ -0,0 +1,18 @@ +package com.annimon.hotarufx.visual; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor(staticName="of") +@EqualsAndHashCode +public class KeyFrame implements Comparable { + + @Getter + private final int frame; + + @Override + public int compareTo(KeyFrame o) { + return Integer.compare(frame, o.frame); + } +} diff --git a/app/src/main/java/com/annimon/hotarufx/visual/TimeLine.java b/app/src/main/java/com/annimon/hotarufx/visual/TimeLine.java new file mode 100644 index 0000000..faf1e15 --- /dev/null +++ b/app/src/main/java/com/annimon/hotarufx/visual/TimeLine.java @@ -0,0 +1,24 @@ +package com.annimon.hotarufx.visual; + +import com.annimon.hotarufx.exceptions.KeyFrameDuplicationException; +import java.util.Map; +import java.util.TreeMap; +import lombok.Getter; +import lombok.val; + +public class TimeLine { + + @Getter + private final Map keyFrames; + + public TimeLine() { + keyFrames = new TreeMap<>(); + } + + public void add(KeyFrame keyFrame, VirtualScene scene) { + val previous = keyFrames.put(keyFrame, scene); + if (previous != null) { + throw new KeyFrameDuplicationException(keyFrame); + } + } +} diff --git a/app/src/main/java/com/annimon/hotarufx/visual/VirtualScene.java b/app/src/main/java/com/annimon/hotarufx/visual/VirtualScene.java new file mode 100644 index 0000000..911cbff --- /dev/null +++ b/app/src/main/java/com/annimon/hotarufx/visual/VirtualScene.java @@ -0,0 +1,20 @@ +package com.annimon.hotarufx.visual; + +import javafx.scene.Group; +import javafx.scene.Node; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class VirtualScene { + + @Getter + private final Group group; + + @Getter + private final int virtualWidth, virtualHeight; + + public void add(Node node) { + group.getChildren().add(node); + } +} diff --git a/app/src/main/java/com/annimon/hotarufx/visual/objects/CircleNode.java b/app/src/main/java/com/annimon/hotarufx/visual/objects/CircleNode.java index c782ff2..091e1e9 100644 --- a/app/src/main/java/com/annimon/hotarufx/visual/objects/CircleNode.java +++ b/app/src/main/java/com/annimon/hotarufx/visual/objects/CircleNode.java @@ -1,9 +1,8 @@ package com.annimon.hotarufx.visual.objects; -import com.annimon.hotarufx.visual.Composition; +import com.annimon.hotarufx.visual.VirtualScene; import javafx.scene.shape.Circle; import lombok.Getter; -import lombok.val; public class CircleNode implements ObjectNode { @@ -15,7 +14,7 @@ public class CircleNode implements ObjectNode { } @Override - public void render(Composition composition) { - composition.add(circle); + public void render(VirtualScene scene) { + scene.add(circle); } } diff --git a/app/src/main/java/com/annimon/hotarufx/visual/objects/ObjectNode.java b/app/src/main/java/com/annimon/hotarufx/visual/objects/ObjectNode.java index 6e0f6d2..c82bbfd 100644 --- a/app/src/main/java/com/annimon/hotarufx/visual/objects/ObjectNode.java +++ b/app/src/main/java/com/annimon/hotarufx/visual/objects/ObjectNode.java @@ -1,8 +1,8 @@ package com.annimon.hotarufx.visual.objects; -import com.annimon.hotarufx.visual.Composition; +import com.annimon.hotarufx.visual.VirtualScene; public interface ObjectNode { - void render(Composition composition); + void render(VirtualScene scene); } diff --git a/app/src/test/java/com/annimon/hotarufx/visual/CompositionTest.java b/app/src/test/java/com/annimon/hotarufx/visual/CompositionTest.java index 0e267b0..c9b88e5 100644 --- a/app/src/test/java/com/annimon/hotarufx/visual/CompositionTest.java +++ b/app/src/test/java/com/annimon/hotarufx/visual/CompositionTest.java @@ -1,7 +1,5 @@ package com.annimon.hotarufx.visual; -import javafx.scene.Group; -import javafx.scene.paint.Color; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -12,10 +10,10 @@ class CompositionTest { @Test void testVirtualSize() { Composition composition; - composition = new Composition(1280, 720, Color.WHITE, new Group()); + composition = new Composition(1280, 720, 30); assertThat(composition.getVirtualWidth(), is(1920)); - composition = new Composition(1280, 1280, Color.WHITE, new Group()); + composition = new Composition(1280, 1280, 30); assertThat(composition.getVirtualWidth(), is(1080)); } } \ No newline at end of file diff --git a/app/src/test/java/com/annimon/hotarufx/visual/TimeLineTest.java b/app/src/test/java/com/annimon/hotarufx/visual/TimeLineTest.java new file mode 100644 index 0000000..104fa8d --- /dev/null +++ b/app/src/test/java/com/annimon/hotarufx/visual/TimeLineTest.java @@ -0,0 +1,24 @@ +package com.annimon.hotarufx.visual; + +import lombok.val; +import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.junit.jupiter.api.Assertions.*; + +class TimeLineTest { + + @Test + void add() { + val timeline = new TimeLine(); + timeline.add(KeyFrame.of(20), null); + timeline.add(KeyFrame.of(10), null); + timeline.add(KeyFrame.of(0), null); + timeline.add(KeyFrame.of(1), null); + + assertThat(timeline.getKeyFrames().keySet(), contains( + KeyFrame.of(0), KeyFrame.of(1), + KeyFrame.of(10), KeyFrame.of(20) + )); + } +} \ No newline at end of file