11package edu .wpi .grip .preloader ;
22
33import java .io .IOException ;
4+ import java .util .Random ;
5+
6+ import javafx .animation .Animation ;
7+ import javafx .animation .FillTransition ;
8+ import javafx .application .Platform ;
49import javafx .application .Preloader ;
510import javafx .fxml .FXMLLoader ;
6- import javafx .scene .Parent ;
711import javafx .scene .Scene ;
8- import javafx .scene .control .ProgressBar ;
12+ import javafx .scene .layout .Pane ;
13+ import javafx .scene .layout .StackPane ;
14+ import javafx .scene .paint .Color ;
915import javafx .stage .Stage ;
1016import javafx .stage .StageStyle ;
17+ import javafx .util .Duration ;
1118
1219public final class GripPreloader extends Preloader {
1320
14- private ProgressBar progressBar ;
21+ private static final Color primaryColor = Color .gray (0.075 );
22+ private static final Color secondaryColor = Color .gray (0.1 );
23+
24+ // Animation timings
25+ private static final double minTime = 1 / 3.0 ;
26+ private static final double maxTime = 2 / 3.0 ;
27+
28+ private static final double HEXAGON_RADIUS = 12 ;
29+
1530 private Stage preloaderStage ;
1631
1732 public static void main (String [] args ) {
@@ -20,16 +35,41 @@ public static void main(String[] args) {
2035
2136 @ Override
2237 public void start (Stage preloaderStage ) throws IOException {
23- Parent root = FXMLLoader .load (GripPreloader .class .getResource ("Preloader.fxml" ));
24- Scene scene = new Scene (root );
38+ final StackPane root = FXMLLoader .load (GripPreloader .class .getResource ("Preloader.fxml" ));
39+
40+ // Animated hexagon grid background
41+ // wrap in runLater so we can get the size of the scene
42+ Platform .runLater (() -> {
43+ Random random = new Random (System .currentTimeMillis () ^ (System .currentTimeMillis () >> 16 ));
44+ HexagonGrid hexagonGrid = new HexagonGrid (
45+ (int ) (preloaderStage .getScene ().getWidth () / HEXAGON_RADIUS ),
46+ (int ) (preloaderStage .getScene ().getHeight () / HEXAGON_RADIUS ),
47+ HEXAGON_RADIUS ,
48+ 0 );
49+ // animate the hexagons
50+ hexagonGrid .hexagons ()
51+ .stream ()
52+ .map (h -> new FillTransition (
53+ Duration .seconds (
54+ clamp (random .nextGaussian () + 1 , 0 , 2 ) * (maxTime - minTime ) + minTime ),
55+ h , primaryColor , secondaryColor ))
56+ .peek (t -> t .setCycleCount (Animation .INDEFINITE ))
57+ .peek (t -> t .setAutoReverse (true ))
58+ .forEach (t -> t .playFrom (Duration .seconds (random .nextDouble () * maxTime * 16 )));
59+ Pane backgroundContainer = new Pane (hexagonGrid );
2560
26- progressBar = (ProgressBar ) root .getChildrenUnmodifiable ().filtered (
27- p -> p instanceof ProgressBar ).get (0 );
61+ // bring the hexagons to the top edge to avoid weird blank spots
62+ backgroundContainer .setTranslateY (-HEXAGON_RADIUS );
63+
64+ root .getChildren ().add (0 , backgroundContainer );
65+ });
66+
67+ Scene scene = new Scene (root );
2868
2969 System .setProperty ("prism.lcdtext" , "false" );
3070
3171 if (getParameters ().getRaw ().contains ("windowed" )) {
32- preloaderStage .initStyle (StageStyle .UTILITY );
72+ preloaderStage .initStyle (StageStyle .UNDECORATED );
3373 } else {
3474 preloaderStage .initStyle (StageStyle .TRANSPARENT );
3575 }
@@ -43,11 +83,14 @@ public void start(Stage preloaderStage) throws IOException {
4383
4484 @ Override
4585 public void handleApplicationNotification (PreloaderNotification pn ) {
46- if (pn instanceof ProgressNotification ) {
47- progressBar .setProgress (((ProgressNotification ) pn ).getProgress ());
48- } else if (pn instanceof StateChangeNotification
86+ if (pn instanceof StateChangeNotification
4987 && ((StateChangeNotification ) pn ).getType () == StateChangeNotification .Type .BEFORE_START ) {
5088 preloaderStage .hide ();
5189 }
5290 }
91+
92+ private static double clamp (double n , double min , double max ) {
93+ return (n < min ) ? min : ((n > max ) ? max : n );
94+ }
95+
5396}
0 commit comments