--- /dev/null
+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);
+ }
+}