Skip to content

Commit

Permalink
Connected controls that manipulate control points, path stroke and fi…
Browse files Browse the repository at this point in the history
…ll colors.
  • Loading branch information
Birdasaur committed Aug 28, 2020
1 parent fde5693 commit 49c34bd
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 82 deletions.
75 changes: 47 additions & 28 deletions litfx-core/src/main/java/lit/litfx/core/components/Band.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -24,29 +23,26 @@
*/
public class Band extends Group {

Paint pointFill = Color.TRANSPARENT;
Path path;
ArrayList<SlopeVector> slopeVectors;
double centerX;
double centerY;
private double velocity;
SimpleDoubleProperty magnitudeProperty = new SimpleDoubleProperty(1.0);
Timeline animation;
ChangeListener<Number> magCL;
ArrayList<Circle> 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<Number>() {
@Override
Expand Down Expand Up @@ -77,24 +73,14 @@ public void changed(ObservableValue<? extends Number> 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<SlopeVector> calcSlopeVectors(double [] doubles, double magnitude) {
ArrayList<SlopeVector> 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;
Expand Down Expand Up @@ -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)));
Expand All @@ -145,4 +134,34 @@ private void updateQuadPath(double[] points){
path.getElements().add(qct); //add our curve to the path
}
}
private ArrayList<SlopeVector> calcSlopeVectors(double [] doubles, double magnitude) {
ArrayList<SlopeVector> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -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<ActionEvent>() {
Expand All @@ -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() {
Expand Down Expand Up @@ -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();

Expand All @@ -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();
}
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
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;
import javafx.scene.input.MouseButton;
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;

Expand Down Expand Up @@ -70,7 +74,14 @@ public class AnimatedWavesDemoController implements Initializable {
SimpleLongProperty timeDelayProp = new SimpleLongProperty(500);

ArrayList<BandEmitter> 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
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<Label text="Initial Radius" />
<Slider fx:id="radiusSlider" majorTickUnit="10.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="50.0" />
<Label layoutX="10.0" layoutY="10.0" text="Velocity" />
<Slider fx:id="velocitySlider" blockIncrement="1.0" layoutX="10.0" layoutY="10.0" majorTickUnit="1.0" max="5.0" minorTickCount="4" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="1.0" />
<Slider fx:id="velocitySlider" blockIncrement="1.0" layoutX="10.0" layoutY="10.0" majorTickUnit="0.5" max="5.0" minorTickCount="4" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="1.0" />
<Label layoutX="10.0" layoutY="175.0" text="Update Delay" />
<Slider fx:id="updateDelaySlider" blockIncrement="100.0" layoutX="10.0" layoutY="192.0" majorTickUnit="100.0" max="1000.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="100.0" />
</children>
Expand All @@ -55,19 +55,19 @@
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="20.0">
<children>
<CheckBox mnemonicParsing="false" text="Show Path Lines" />
<CheckBox mnemonicParsing="false" text="Show Control Points" />
<CheckBox mnemonicParsing="false" text="Enable Gradient Fill" />
<CheckBox fx:id="showPathLines" mnemonicParsing="false" text="Show Path Lines" />
<CheckBox fx:id="showControlPoints" mnemonicParsing="false" text="Show Control Points" />
<CheckBox fx:id="enableGradientFill" mnemonicParsing="false" text="Enable Gradient Fill" />
</children>
</HBox>
<Label text="Path Thickness" />
<Slider fx:id="branchThicknessSlider" blockIncrement="5.0" majorTickUnit="10.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" value="3.0" />
<Slider fx:id="pathThicknessSlider" blockIncrement="2.0" majorTickUnit="1.0" max="10.0" minorTickCount="9" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="2.0" />
<Label text="glow" />
<Slider fx:id="branchGlowSlider" blockIncrement="0.1" majorTickUnit="0.1" max="1.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" value="0.75" />
<Slider fx:id="glowSlider" blockIncrement="0.1" majorTickUnit="0.1" max="1.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" />
<Label text="Shadow" />
<Slider fx:id="branchShadowSlider" majorTickUnit="10.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" value="60.0" />
<Slider fx:id="shadowSlider" majorTickUnit="10.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" />
<Label text="opacity" />
<Slider fx:id="branchOpacitySlider" blockIncrement="0.1" majorTickUnit="0.1" max="1.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" value="0.5" />
<Slider fx:id="opacitySlider" blockIncrement="0.1" majorTickUnit="0.1" max="1.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" value="0.5" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
Expand All @@ -92,7 +92,7 @@
</image>
</ImageView>
<Circle fx:id="circle1" fill="#1f93ff21" layoutX="193.0" layoutY="235.0" radius="50.0" stroke="#07aaf523" strokeType="INSIDE" />
<Circle fx:id="circle2" fill="#1f93ff21" layoutX="365.0" layoutY="189.0" radius="50.0" stroke="#07b2f560" strokeType="INSIDE" />
<Circle fx:id="circle2" fill="#1f93ff21" layoutX="361.0" layoutY="189.0" radius="50.0" stroke="#07b5f585" strokeType="INSIDE" />
</children></Pane>
</center>
</BorderPane>

0 comments on commit 49c34bd

Please sign in to comment.