diff --git a/litfx-core/src/main/java/lit/litfx/core/components/Band.java b/litfx-core/src/main/java/lit/litfx/core/components/Band.java index c08cb78..fb30bac 100644 --- a/litfx-core/src/main/java/lit/litfx/core/components/Band.java +++ b/litfx-core/src/main/java/lit/litfx/core/components/Band.java @@ -10,9 +10,8 @@ import javafx.geometry.Point2D; import javafx.scene.Group; import javafx.scene.paint.Color; -import javafx.scene.paint.CycleMethod; -import javafx.scene.paint.RadialGradient; -import javafx.scene.paint.Stop; +import javafx.scene.paint.Paint; +import javafx.scene.shape.Circle; import javafx.scene.shape.MoveTo; import javafx.scene.shape.Path; import javafx.scene.shape.QuadCurveTo; @@ -24,29 +23,26 @@ */ public class Band extends Group { + Paint pointFill = Color.TRANSPARENT; Path path; ArrayList slopeVectors; double centerX; double centerY; + private double velocity; SimpleDoubleProperty magnitudeProperty = new SimpleDoubleProperty(1.0); Timeline animation; ChangeListener magCL; + ArrayList pointCircles; - public Band(double x, double y, double... doubles) { + + public Band(double x, double y, double velocity, double... doubles) { + this.centerX = x; + this.centerY = y; + this.velocity = velocity; path = new Path(); updateQuadPath(doubles); getChildren().add(path); - path.setStroke(Color.rgb(200, 200, 255)); - RadialGradient gradient1 = new RadialGradient(0, 0.1, 0.5, 0.5, - 0.55, true, CycleMethod.NO_CYCLE, - new Stop(0, Color.BLUE.deriveColor(1, 1, 1, 0.2)), - new Stop(0.6, Color.YELLOW.deriveColor(1, 1, 1, 0.8)), - new Stop(1, Color.RED.deriveColor(1, 1, 1, 0.8)) - ); - - path.setFill(gradient1); - this.centerX = x; - this.centerY = y; + path.setStroke(Color.ALICEBLUE); slopeVectors = calcSlopeVectors(doubles, magnitudeProperty.get()); magCL = new ChangeListener() { @Override @@ -77,24 +73,14 @@ public void changed(ObservableValue ov, Number t, Number t1) { animation = new Timeline( new KeyFrame(Duration.ZERO, new KeyValue(magnitudeProperty, 1.0)), new KeyFrame(Duration.seconds(1), new KeyValue(opacityProperty(), 1)), - new KeyFrame(Duration.seconds(3), new KeyValue(magnitudeProperty, 1.2)), + new KeyFrame(Duration.seconds(3), new KeyValue(magnitudeProperty, velocity)), new KeyFrame(Duration.seconds(3), new KeyValue(opacityProperty(), 0)) ); } - - private ArrayList calcSlopeVectors(double [] doubles, double magnitude) { - ArrayList pointSlopes = new ArrayList<>(doubles.length / 2); - for (int i = 0; i < doubles.length; i += 2) { - pointSlopes.add(new SlopeVector(doubles[i], doubles[i+1], magnitude)); - } - return pointSlopes; - } - private Point2D getMidpoint(double x1, double y1, double x2, double y2) { - return new Point2D(x1, y1).midpoint(x2, y2); - } - private void updateQuadPath(double[] points){ + //Remove any points from the group that might exist + getChildren().removeIf(t -> t instanceof Circle); //Go through the points, using points as a control points and midpoint // of line segments as points for quad curves double startX, startY, nextX, nextY; @@ -136,6 +122,9 @@ private void updateQuadPath(double[] points){ } //use the midpoint at the target point for the curve Point2D midPoint = getMidpoint(startX, startY, nextX, nextY); + //Add point to the group + Circle circle = new Circle(midPoint.getX(), midPoint.getY(), 3.0, pointFill); + getChildren().add(circle); //@DEBUG SMP visual starting point with unique circle //getChildren().add(new Circle(midPoint.getX(), midPoint.getY(), 3.0, // Color.DARKBLUE.deriveColor(1, 1, 1, 0.7))); @@ -145,4 +134,34 @@ private void updateQuadPath(double[] points){ path.getElements().add(qct); //add our curve to the path } } + private ArrayList calcSlopeVectors(double [] doubles, double magnitude) { + ArrayList pointSlopes = new ArrayList<>(doubles.length / 2); + for (int i = 0; i < doubles.length; i += 2) { + pointSlopes.add(new SlopeVector(doubles[i], doubles[i+1], magnitude)); + } + return pointSlopes; + } + + private Point2D getMidpoint(double x1, double y1, double x2, double y2) { + return new Point2D(x1, y1).midpoint(x2, y2); + } + + public void setPointFill(Color color) { + pointFill = color; + getChildren().stream().filter(n -> n instanceof Circle) + .forEach(t -> ((Circle)t).setFill(pointFill)); + } + /** + * @return the velocity + */ + public double getVelocity() { + return velocity; + } + + /** + * @param velocity the velocity to set + */ + public void setVelocity(double velocity) { + this.velocity = velocity; + } } diff --git a/litfx-core/src/main/java/lit/litfx/core/components/BandEmitter.java b/litfx-core/src/main/java/lit/litfx/core/components/BandEmitter.java index b5eed70..5172e13 100644 --- a/litfx-core/src/main/java/lit/litfx/core/components/BandEmitter.java +++ b/litfx-core/src/main/java/lit/litfx/core/components/BandEmitter.java @@ -6,6 +6,11 @@ import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Group; +import javafx.scene.paint.Color; +import javafx.scene.paint.CycleMethod; +import javafx.scene.paint.Paint; +import javafx.scene.paint.RadialGradient; +import javafx.scene.paint.Stop; import javafx.util.Duration; /** @@ -17,12 +22,19 @@ * createQuadBand method is called. Bands grow and fade out over 3 seconds */ public class BandEmitter extends Group { + private int polygonPoints; private double initialRadius; private double edgeVariation; private double generatorCenterX = 100.0; private double generatorCenterY = 100.0; private double velocity; + private double pathThickness; + private boolean showPoints; + public Paint fill; + public Paint stroke; + public static Paint DEFAULT_FILL = Color.ALICEBLUE.deriveColor(1, 1, 1, 0.05); + public static Paint DEFAULT_STROKE = Color.ALICEBLUE; private Timeline generate = new Timeline( new KeyFrame(Duration.seconds(0.5), new EventHandler() { @@ -33,12 +45,15 @@ public void handle(ActionEvent event) { }) ); + public BandEmitter(int points, double initialRadius, double edgeVariation) { this.polygonPoints = points; this.initialRadius = initialRadius; this.edgeVariation = edgeVariation; velocity = 0.0; generate.setCycleCount(Timeline.INDEFINITE); + fill = DEFAULT_FILL; + stroke = DEFAULT_STROKE; } public void createQuadBand() { @@ -70,7 +85,14 @@ public void createQuadBand() { // Color.ALICEBLUE.deriveColor(1, 1, 1, 0.7))); } - final Band band = new Band(getGeneratorCenterX(), getGeneratorCenterY(), doubles); + Band band = new Band(getGeneratorCenterX(), getGeneratorCenterY(), velocity, doubles); + band.path.setStrokeWidth(pathThickness); + band.path.setFill(fill); + band.path.setStroke(stroke); + if(showPoints) + band.setPointFill(Color.ALICEBLUE); + else + band.setPointFill(Color.TRANSPARENT); getChildren().add(band); band.animation.play(); @@ -86,6 +108,12 @@ public void handle(ActionEvent event) { remover.play(); } + public void setCustomFill(Paint fill) { + this.fill = fill; + } + public void setCustomStroke(Paint stroke) { + this.stroke = stroke; + } public void startGenerating() { generate.play(); } @@ -171,4 +199,25 @@ public double getVelocity() { public void setVelocity(double velocity) { this.velocity = velocity; } + + /** + * @return the pathThickness + */ + public double getPathThickness() { + return pathThickness; + } + + /** + * @param pathThickness the pathThickness to set + */ + public void setPathThickness(double pathThickness) { + this.pathThickness = pathThickness; + } + + /** + * @param showPoints the showPoints to set + */ + public void setShowPoints(boolean showPoints) { + this.showPoints = showPoints; + } } \ No newline at end of file diff --git a/litfx-demos/src/main/java/lit/litfx/demos/AnimatedWavesDemo.java b/litfx-demos/src/main/java/lit/litfx/demos/AnimatedWavesDemo.java index 2d1465b..961f9da 100644 --- a/litfx-demos/src/main/java/lit/litfx/demos/AnimatedWavesDemo.java +++ b/litfx-demos/src/main/java/lit/litfx/demos/AnimatedWavesDemo.java @@ -19,7 +19,7 @@ public class AnimatedWavesDemo extends Application { public void start(Stage primaryStage) throws IOException { FXMLLoader loader = new FXMLLoader(getClass().getResource("AnimatedWavesDemo.fxml")); Parent parent = loader.load(); - scene = new Scene(parent, 800, 800, Color.BLACK); + scene = new Scene(parent, Color.BLACK); String CSS = getClass().getResource("styles.css").toExternalForm(); scene.getStylesheets().add(CSS); diff --git a/litfx-demos/src/main/java/lit/litfx/demos/controllers/AnimatedWavesDemoController.java b/litfx-demos/src/main/java/lit/litfx/demos/controllers/AnimatedWavesDemoController.java index d91af03..e691e30 100644 --- a/litfx-demos/src/main/java/lit/litfx/demos/controllers/AnimatedWavesDemoController.java +++ b/litfx-demos/src/main/java/lit/litfx/demos/controllers/AnimatedWavesDemoController.java @@ -12,6 +12,7 @@ import javafx.scene.control.CheckBox; import javafx.scene.control.Slider; import javafx.scene.control.TabPane; +import javafx.scene.effect.BlurType; import javafx.scene.effect.DropShadow; import javafx.scene.effect.Effect; import javafx.scene.effect.Glow; @@ -19,6 +20,9 @@ import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; import javafx.scene.paint.Color; +import javafx.scene.paint.CycleMethod; +import javafx.scene.paint.RadialGradient; +import javafx.scene.paint.Stop; import javafx.scene.shape.Circle; import lit.litfx.core.components.BandEmitter; @@ -70,7 +74,14 @@ public class AnimatedWavesDemoController implements Initializable { SimpleLongProperty timeDelayProp = new SimpleLongProperty(500); ArrayList bandEmitters = new ArrayList<>(); - + + RadialGradient gradient1 = new RadialGradient(0, 0.1, 0.5, 0.5, + 0.55, true, CycleMethod.NO_CYCLE, + new Stop(0, Color.BLUE.deriveColor(1, 1, 1, 0.1)), + new Stop(0.7, Color.YELLOW.deriveColor(1, 1, 1, 0.2)), + new Stop(0.8, Color.YELLOW.deriveColor(1, 1, 1, 0.8)), + new Stop(1, Color.RED.deriveColor(1, 1, 1, 0.8)) + ); /** * Initializes the controller class. * @param url @@ -98,16 +109,7 @@ public void initialize(URL url, ResourceBundle rb) { // else if(event.getButton() == MouseButton.SECONDARY) // end = new Point2D(event.getX(), event.getY()); }); -// centerPane.widthProperty().addListener((obs, oV, nV)-> { -// start = new Point2D(centerPane.getWidth() / 2.0, centerPane.getHeight() / 2.0); -// }); -// centerPane.heightProperty().addListener((obs, oV, nV)-> { -// start = new Point2D(centerPane.getWidth() / 2.0, centerPane.getHeight() / 2.0); -// }); -// -// start = new Point2D(centerPane.getWidth() / 2.0, centerPane.getHeight() / 2.0); -// end = new Point2D(centerPane.getWidth()-10.0, centerPane.getHeight() / 2.0); - + timeDelayProp.bind(updateDelaySlider.valueProperty()); Task animationTask = new Task() { @@ -137,45 +139,31 @@ private BandEmitter createBandEmitter(double x, double y, int points, } public void updateBands() { Platform.runLater(()-> { -// centerPane.getChildren().clear(); bandEmitters.stream().forEach(be -> { be.setPolygonPoints(Double.valueOf(pointsSlider.getValue()).intValue()); be.setInitialRadius(radiusSlider.getValue()); be.setEdgeVariation(pointDivergenceSlider.getValue()); be.setVelocity(velocitySlider.getValue()); be.createQuadBand(); -// branch.setBoltThickness(boltThicknessSlider.getValue()); -// branch.setBranchThickness(pathThicknessSlider.getValue()); -// branch.setEffect(collectEffects(BranchLightning.Member.PRIMARYBOLT), -// BranchLightning.Member.PRIMARYBOLT); -// branch.setEffect(collectEffects(BranchLightning.Member.BRANCH), -// BranchLightning.Member.BRANCH); -// branch.setOpacity(boltOpacitySlider.getValue(), BranchLightning.Member.PRIMARYBOLT); -// branch.setOpacity(opacitySlider.getValue(), BranchLightning.Member.BRANCH); - + be.setPathThickness(pathThicknessSlider.getValue()); + be.setEffect(collectEffects()); + be.setOpacity(opacitySlider.getValue()); + be.setShowPoints(showControlPoints.isSelected()); + if(showPathLines.isSelected()) + be.setCustomStroke(BandEmitter.DEFAULT_STROKE); + else + be.setCustomStroke(Color.TRANSPARENT); + if(enableGradientFill.isSelected()) + be.setCustomFill(gradient1); + else + be.setCustomFill(BandEmitter.DEFAULT_FILL); }); - }); } -// private Effect collectEffects(BranchLightning.Member member) { -// if(member == BranchLightning.Member.PRIMARYBOLT) { -// SepiaTone st = new SepiaTone(boltSepiaSlider.getValue()); -// Bloom bloom = new Bloom(boltBloomSlider.getValue()); -// bloom.setInput(st); -// Glow glow = new Glow(boltGlowSlider.getValue()); -// glow.setInput(bloom); -// DropShadow shadow = new DropShadow(BlurType.GAUSSIAN, Color.AZURE, boltShadowSlider.getValue(), 0.5, 0, 0); -// shadow.setInput(glow); -// return shadow; -// } else { -// SepiaTone st = new SepiaTone(branchSepiaSlider.getValue()); -// Bloom bloom = new Bloom(branchBloomSlider.getValue()); -// bloom.setInput(st); -// Glow glow = new Glow(glowSlider.getValue()); -// glow.setInput(bloom); -// DropShadow shadow = new DropShadow(BlurType.GAUSSIAN, Color.AZURE, shadowSlider.getValue(), 0.5, 0, 0); -// shadow.setInput(glow); -// return shadow; -// } -// } + private Effect collectEffects() { + Glow glow = new Glow(glowSlider.getValue()); + DropShadow shadow = new DropShadow(BlurType.GAUSSIAN, Color.AZURE, shadowSlider.getValue(), 0.5, 0, 0); + shadow.setInput(glow); + return shadow; + } } diff --git a/litfx-demos/src/main/resources/lit/litfx/demos/AnimatedWavesDemo.fxml b/litfx-demos/src/main/resources/lit/litfx/demos/AnimatedWavesDemo.fxml index 616bc60..216a101 100644 --- a/litfx-demos/src/main/resources/lit/litfx/demos/AnimatedWavesDemo.fxml +++ b/litfx-demos/src/main/resources/lit/litfx/demos/AnimatedWavesDemo.fxml @@ -32,7 +32,7 @@