Move all modes to package kaka.cakelight.mode
[kaka/cakelight.git] / src / kaka / cakelight / GuiTest.java
1 package kaka.cakelight;
2
3 import javafx.application.Application;
4 import javafx.scene.Scene;
5 import javafx.scene.canvas.Canvas;
6 import javafx.scene.canvas.GraphicsContext;
7 import javafx.scene.input.KeyCode;
8 import javafx.scene.layout.Pane;
9 import javafx.scene.paint.Color;
10 import javafx.scene.paint.Paint;
11 import javafx.stage.Stage;
12 import kaka.cakelight.mode.AmbientMode;
13 import org.opencv.core.Core;
14 import org.opencv.core.Mat;
15
16 import static kaka.cakelight.Main.log;
17
18 public class GuiTest extends Application {
19     private static final int BLOCK = 45;
20     private static final int GUTTER = 3 * BLOCK;
21     private Canvas canvas;
22     private Configuration config;
23     private CakeLight cakelight;
24     private boolean paused;
25
26     public static void main(String[] args) {
27         System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
28         launch(args);
29     }
30
31     @Override
32     public void start(Stage stage) throws Exception {
33         config = Configuration.from("config.properties");
34         canvas = new Canvas(16 * BLOCK + 2 * GUTTER, 9 * BLOCK + 2 * GUTTER);
35
36         Pane root = new Pane();
37         root.getChildren().add(canvas);
38
39         Scene scene = new Scene(root);
40         scene.setOnKeyPressed(keyEvent -> {
41             if (keyEvent.getCode() == KeyCode.ESCAPE || keyEvent.getCode() == KeyCode.Q) {
42                 stage.close();
43                 cakelight.cleanup();
44             }
45             if (keyEvent.getCode() == KeyCode.SPACE) {
46                 paused = !paused;
47             }
48         });
49
50         stage.setTitle("Cakelight");
51         stage.setScene(scene);
52         stage.setOnCloseRequest(windowEvent -> cakelight.cleanup());
53         stage.show();
54
55         setupCakeLight();
56     }
57
58     private void setupCakeLight() {
59         log("Running with config:\n" + config);
60         cakelight = new CakeLight(config);
61         VideoMode mode = new VideoMode();
62         cakelight.setMode(mode);
63         cakelight.startLoop();
64         mode.onVideoFrame(frame -> drawFrame(canvas.getGraphicsContext2D(), frame));
65     }
66
67     private javafx.scene.paint.Color getLedColor(LedFrame frame, int led) {
68         kaka.cakelight.Color c = frame.getLedColor(led);
69         return javafx.scene.paint.Color.rgb(c.r(), c.g(), c.b());
70     }
71
72     private void drawFrame(GraphicsContext gc, VideoFrame frame) {
73         if (paused) return;
74         System.out.println("Drawing a frame");
75         drawCols(gc, frame);
76         drawRows(gc, frame);
77 //        drawVideo(gc, frame);
78         drawBorderAndGrid(gc);
79     }
80
81     private void drawLEDs(GraphicsContext gc, LedFrame frame) {
82         int ledLength = GUTTER;
83         float colSize = 16f * BLOCK / config.leds.cols;
84         float rowSize = 9f * BLOCK / config.leds.rows;
85 //        DropShadow shadow = new DropShadow(BlurType.ONE_PASS_BOX, Color.RED, colSize * 2, colSize, 0, 0);
86         for (int x = 0; x < config.leds.cols; x++) {
87             // Top
88             gc.setFill(getLedColor(frame, config.leds.cols * 2 + config.leds.rows - x - 1));
89             gc.fillRect(GUTTER + x * colSize, GUTTER - ledLength, colSize, ledLength);
90             // Bottom
91             gc.setFill(getLedColor(frame, x));
92             gc.fillRect(GUTTER + x * colSize, GUTTER + 9 * BLOCK, colSize, ledLength);
93         }
94         for (int y = 0; y < config.leds.rows; y++) {
95             // Left
96             gc.setFill(getLedColor(frame, config.leds.cols * 2 + config.leds.rows + y));
97             gc.fillRect(GUTTER - ledLength, GUTTER + y * rowSize, ledLength, rowSize);
98             // Right
99             gc.setFill(getLedColor(frame, config.leds.rows + config.leds.cols - y - 1));
100             gc.fillRect(GUTTER + 16 * BLOCK, GUTTER + y * rowSize, ledLength, rowSize);
101         }
102     }
103
104     private void drawVideo(GraphicsContext gc, VideoFrame frame) {
105         byte[] rgb = new byte[3];
106         Mat img = frame.getConvertedImage();
107         float colSize = 16 * BLOCK / (float)img.cols();
108         float rowSize = 9 * BLOCK / (float)img.rows();
109         for (int x = 0, cols = img.cols(); x < cols; x++) {
110             for (int y = 0, rows = img.rows(); y < rows; y++) {
111                 img.get(y, x, rgb);
112                 gc.setFill(Color.rgb(rgb[0] & 0xff, rgb[1] & 0xff, rgb[2] & 0xff, 0.5));
113                 gc.fillRect(GUTTER + x * colSize, GUTTER + y * rowSize, colSize, rowSize);
114             }
115         }
116     }
117
118     private void drawCols(GraphicsContext gc, VideoFrame frame) {
119         byte[] rgb = new byte[3];
120         for (int x = 0; x < config.leds.cols; x++) {
121             for (int y = 0; y < 9; y++) {
122                 frame.getColImage().get(y, x, rgb);
123                 drawColPixel(gc, x, y, rgb);
124             }
125         }
126     }
127
128     private void drawRows(GraphicsContext gc, VideoFrame frame) {
129         byte[] rgb = new byte[3];
130         for (int y = 0; y < config.leds.rows; y++) {
131             for (int x = 0; x < 16; x++) {
132                 frame.getRowImage().get(y, x, rgb);
133                 drawRowPixel(gc, x, y, rgb);
134             }
135         }
136     }
137
138     private void drawColPixel(GraphicsContext gc, int x, int y, byte[] rgb) {
139         float ledSize = 16f * BLOCK / config.leds.cols;
140         gc.setFill(Color.rgb(rgb[0] & 0xff, rgb[1] & 0xff, rgb[2] & 0xff, 0.5));
141         gc.fillRect(GUTTER + x * ledSize, GUTTER + y * BLOCK, ledSize, BLOCK);
142     }
143
144     private void drawRowPixel(GraphicsContext gc, int x, int y, byte[] rgb) {
145         float ledSize = 9f * BLOCK / config.leds.rows;
146         gc.setFill(Color.rgb(rgb[0] & 0xff, rgb[1] & 0xff, rgb[2] & 0xff, 0.5));
147         gc.fillRect(GUTTER + x * BLOCK, GUTTER + y * ledSize, BLOCK, ledSize);
148     }
149
150     private void drawBorderAndGrid(GraphicsContext gc) {
151         gc.setStroke(Color.BLACK);
152         gc.setLineWidth(BLOCK * 0.1);
153         gc.strokeRect(GUTTER, GUTTER, 16 * BLOCK, 9 * BLOCK);
154         gc.setLineWidth(1);
155         for (int x = 1; x < 16; x++) {
156             gc.strokeLine(GUTTER + x * BLOCK, GUTTER, GUTTER + x * BLOCK, GUTTER + 9 * BLOCK);
157         }
158         for (int y = 1; y < 9; y++) {
159             gc.strokeLine(GUTTER, GUTTER + y * BLOCK, GUTTER + 16 * BLOCK, GUTTER + y * BLOCK);
160         }
161     }
162
163     private void drawPixel(GraphicsContext gc, int x, int y, Paint paint) {
164         gc.setFill(paint);
165         gc.fillRect(GUTTER + x * BLOCK, GUTTER + y * BLOCK, BLOCK, BLOCK);
166     }
167 }