Made a GUI tester for video capture
[kaka/cakelight.git] / src / kaka / cakelight / GuiTest.java
diff --git a/src/kaka/cakelight/GuiTest.java b/src/kaka/cakelight/GuiTest.java
new file mode 100644 (file)
index 0000000..8feac32
--- /dev/null
@@ -0,0 +1,158 @@
+package kaka.cakelight;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.canvas.Canvas;
+import javafx.scene.canvas.GraphicsContext;
+import javafx.scene.input.KeyCode;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Color;
+import javafx.scene.paint.Paint;
+import javafx.stage.Stage;
+import org.opencv.core.Core;
+import org.opencv.core.Mat;
+
+import static kaka.cakelight.Main.log;
+
+public class GuiTest extends Application {
+    private static final int BLOCK = 45;
+    private static final int GUTTER = 3 * BLOCK;
+    private Canvas canvas;
+    private Configuration config;
+    private CakeLight cakelight;
+    private boolean paused;
+
+    public static void main(String[] args) {
+        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
+        launch(args);
+    }
+
+    @Override
+    public void start(Stage stage) throws Exception {
+        config = Configuration.from("config.properties");
+        canvas = new Canvas(16 * BLOCK + 2 * GUTTER, 9 * BLOCK + 2 * GUTTER);
+
+        Pane root = new Pane();
+        root.getChildren().add(canvas);
+
+        Scene scene = new Scene(root);
+        scene.setOnKeyPressed(keyEvent -> {
+            if (keyEvent.getCode() == KeyCode.ESCAPE) {
+                stage.close();
+                cakelight.cleanup();
+            }
+            if (keyEvent.getCode() == KeyCode.SPACE) {
+                paused = !paused;
+            }
+        });
+
+        stage.setTitle("Cakelight");
+        stage.setScene(scene);
+        stage.setOnCloseRequest(windowEvent -> cakelight.cleanup());
+        stage.show();
+
+        setupCakeLight();
+    }
+
+    private void setupCakeLight() {
+        log("Running with config:\n" + config);
+        cakelight = new CakeLight(config);
+        VideoMode mode = new VideoMode();
+        cakelight.setMode(mode);
+        cakelight.startLoop();
+        mode.onFrame(frame -> drawFrame(canvas.getGraphicsContext2D(), frame));
+    }
+
+    private void drawFrame(GraphicsContext gc, Frame frame) {
+        if (paused) return;
+        System.out.println("Drawing a frame");
+        drawCols(gc, frame);
+        drawRows(gc, frame);
+//        drawVideo(gc, frame);
+        drawBorderAndGrid(gc);
+        drawLEDs(gc, frame);
+    }
+
+    private void drawLEDs(GraphicsContext gc, Frame frame) {
+        int ledLength = GUTTER;
+        float colSize = 16f * BLOCK / config.leds.cols;
+        float rowSize = 9f * BLOCK / config.leds.rows;
+//        DropShadow shadow = new DropShadow(BlurType.ONE_PASS_BOX, Color.RED, colSize * 2, colSize, 0, 0);
+        for (int x = 0; x < config.leds.cols; x++) {
+            gc.setFill(frame.getLedColor(ListPosition.TOP, x));
+            gc.fillRect(GUTTER + x * colSize, GUTTER - ledLength, colSize, ledLength);
+            gc.setFill(frame.getLedColor(ListPosition.BOTTOM, x));
+            gc.fillRect(GUTTER + x * colSize, GUTTER + 9 * BLOCK, colSize, ledLength);
+        }
+        for (int y = 0; y < config.leds.rows; y++) {
+            gc.setFill(frame.getLedColor(ListPosition.LEFT, y));
+            gc.fillRect(GUTTER - ledLength, GUTTER + y * rowSize, ledLength, rowSize);
+            gc.setFill(frame.getLedColor(ListPosition.RIGHT, y));
+            gc.fillRect(GUTTER + 16 * BLOCK, GUTTER + y * rowSize, ledLength, rowSize);
+        }
+    }
+
+    private void drawVideo(GraphicsContext gc, Frame frame) {
+        byte[] rgb = new byte[3];
+        Mat img = frame.getConvertedImage();
+        float colSize = 16 * BLOCK / (float)img.cols();
+        float rowSize = 9 * BLOCK / (float)img.rows();
+        for (int x = 0, cols = img.cols(); x < cols; x++) {
+            for (int y = 0, rows = img.rows(); y < rows; y++) {
+                img.get(y, x, rgb);
+                gc.setFill(Color.rgb(rgb[0] & 0xff, rgb[1] & 0xff, rgb[2] & 0xff, 0.5));
+                gc.fillRect(GUTTER + x * colSize, GUTTER + y * rowSize, colSize, rowSize);
+            }
+        }
+    }
+
+    private void drawCols(GraphicsContext gc, Frame frame) {
+        byte[] rgb = new byte[3];
+        for (int x = 0; x < config.leds.cols; x++) {
+            for (int y = 0; y < 9; y++) {
+                frame.getColImage().get(y, x, rgb);
+                drawColPixel(gc, x, y, rgb);
+            }
+        }
+    }
+
+    private void drawRows(GraphicsContext gc, Frame frame) {
+        byte[] rgb = new byte[3];
+        for (int y = 0; y < config.leds.rows; y++) {
+            for (int x = 0; x < 16; x++) {
+                frame.getRowImage().get(y, x, rgb);
+                drawRowPixel(gc, x, y, rgb);
+            }
+        }
+    }
+
+    private void drawColPixel(GraphicsContext gc, int x, int y, byte[] rgb) {
+        float ledSize = 16f * BLOCK / config.leds.cols;
+        gc.setFill(Color.rgb(rgb[0] & 0xff, rgb[1] & 0xff, rgb[2] & 0xff, 0.5));
+        gc.fillRect(GUTTER + x * ledSize, GUTTER + y * BLOCK, ledSize, BLOCK);
+    }
+
+    private void drawRowPixel(GraphicsContext gc, int x, int y, byte[] rgb) {
+        float ledSize = 9f * BLOCK / config.leds.rows;
+        gc.setFill(Color.rgb(rgb[0] & 0xff, rgb[1] & 0xff, rgb[2] & 0xff, 0.5));
+        gc.fillRect(GUTTER + x * BLOCK, GUTTER + y * ledSize, BLOCK, ledSize);
+    }
+
+    private void drawBorderAndGrid(GraphicsContext gc) {
+        gc.setStroke(Color.BLACK);
+        gc.setLineWidth(BLOCK * 0.1);
+        gc.strokeRect(GUTTER, GUTTER, 16 * BLOCK, 9 * BLOCK);
+        gc.setLineWidth(1);
+        for (int x = 1; x < 16; x++) {
+            gc.strokeLine(GUTTER + x * BLOCK, GUTTER, GUTTER + x * BLOCK, GUTTER + 9 * BLOCK);
+        }
+        for (int y = 1; y < 9; y++) {
+            gc.strokeLine(GUTTER, GUTTER + y * BLOCK, GUTTER + 16 * BLOCK, GUTTER + y * BLOCK);
+        }
+    }
+
+    private void drawPixel(GraphicsContext gc, int x, int y, Paint paint) {
+        gc.setFill(paint);
+        gc.fillRect(GUTTER + x * BLOCK, GUTTER + y * BLOCK, BLOCK, BLOCK);
+    }
+}