From 9948bd1c72586de06c38f1a4659876bb3987315b Mon Sep 17 00:00:00 2001
From: Jan Grewe <jan@faked.org>
Date: Mon, 5 Jun 2023 22:57:22 +0200
Subject: [PATCH] add color

---
 data_src/index.html | 11 ++++++--
 data_src/main.js    | 61 ++++++++++++++++++++++++++++++++++-----------
 src/display.cpp     | 13 ++++++++--
 src/display.h       |  4 +++
 src/main.cpp        |  4 ++-
 src/network.cpp     |  8 ++++++
 src/settings.cpp    |  7 ++++++
 src/settings.h      |  3 +++
 8 files changed, 92 insertions(+), 19 deletions(-)

diff --git a/data_src/index.html b/data_src/index.html
index d449844..55930d2 100644
--- a/data_src/index.html
+++ b/data_src/index.html
@@ -24,6 +24,9 @@
         </h5>
         <div class="card-body text-center">
 
+          <div class="row mb-3 px-3">
+            <div id="colorpicker" class="d-flex justify-content-center"></div>
+          </div>
           <div class="row mb-3 px-3">
             <label for="rangeBrightness" class="col-form-label">Brightness</label>
             <input type="range" class="form-range rangeSetting" id="rangeBrightness" data-name="brightness" min="1"
@@ -44,8 +47,10 @@
         <div class="card-footer text-body-secondary py-3">
           <div class="row">
             <div class="col-6">
-              <button type="button" class="btn btn-sm btn-success btnAction me-1" data-action="loadSettings" disabled>Load</button>
-              <button type="button" class="btn btn-sm btn-success btnAction" data-action="saveSettings" disabled>Save</button>
+              <button type="button" class="btn btn-sm btn-success btnAction me-1" data-action="loadSettings"
+                disabled>Load</button>
+              <button type="button" class="btn btn-sm btn-success btnAction" data-action="saveSettings"
+                disabled>Save</button>
             </div>
             <div class="col-6 text-end">
               <button type="button" class="btn btn-sm btn-outline-secondary me-1" data-bs-toggle="collapse"
@@ -92,6 +97,8 @@
   <script
     src="https://cdn.jsdelivr.net/gh/jbloemendal/jquery-simple-websocket@master/dist/jquery.simple.websocket.min.js"
     crossorigin="anonymous"></script>
+  <script src="https://cdn.jsdelivr.net/npm/@jaames/iro@5.5.2/dist/iro.min.js"
+    integrity="sha256-XQju26ya9yEvX99+M2rrLah6xHsjZIGK1LvX/L3RjQ0=" crossorigin="anonymous"></script>
   <script src="main.js"></script>
 
 </body>
diff --git a/data_src/main.js b/data_src/main.js
index fe3f97b..58eaac2 100644
--- a/data_src/main.js
+++ b/data_src/main.js
@@ -3,11 +3,21 @@ var wsUrl = 'ws://' + document.location.host + '/ws';
 var settings = {
     brightness: 0,
     interval: 0,
+    color: {
+        r: 255,
+        g: 255,
+        b: 255,
+    }
 };
 
-$(document).ready(function () {
-    uiEnabled(false);
-    $("#wsMessages, #prompt").val("");
+var uiEnabled = false;
+
+$(document).ready(function() {
+    enabledUI(false);
+    $("#wsMessages, #prompt").val("");    
+});
+
+$(window).on('load', function () {
     startSocket();
 });
 
@@ -23,10 +33,20 @@ $(document).on('change', '.rangeSetting', function () {
             break;
     }
     settings[setting] = value;
-    var payload = {
-        'settings': settings
-    };
-    wsSend(payload);
+    sendSettings();
+});
+
+var colorPicker = new iro.ColorPicker('#colorpicker', {
+    layout: [
+        {
+            component: iro.ui.Wheel,
+        }
+    ]
+});    
+
+colorPicker.on('input:end', function (color) {
+    settings.color = color.rgb;
+    sendSettings();
 });
 
 $('.btnAction').on('click', function () {
@@ -42,15 +62,17 @@ $("#prompt").on('keydown', function (e) {
     }
 });
 
-function uiEnabled(enabled) {
-    if (enabled) {
+function enabledUI(enable) {
+    if (enable) {
         $('#spinner').addClass('invisible');
         $('.btnAction').prop('disabled', false);
         $('.rangeSetting').prop('disabled', false);
+        uiEnabled = true;
     } else {
         $('#spinner').removeClass('invisible');
         $('.btnAction').prop('disabled', true);
         $('.rangeSetting').prop('disabled', true);
+        uiEnabled = false;
     }
 }
 
@@ -60,6 +82,16 @@ function addMessage(msg) {
     txt.scrollTop(txt[0].scrollHeight - txt.height());
 }
 
+function sendSettings() {
+    if (!uiEnabled) {
+        return;
+    }
+    var payload = {
+        'settings': settings
+    };
+    wsSend(payload);
+}
+
 function wsSend(obj) {
     ws.send(obj).done(function () {
         addMessage("➡️ " + JSON.stringify(obj));
@@ -74,19 +106,19 @@ function startSocket() {
         url: wsUrl,
         timeout: 5000,
         onOpen: function (e) {
-            ws.isConnected(function (connected) {
+            if (ws.isConnected()) {
                 console.log("WS: connected");
                 addMessage("✅ connected");
                 sendAction('getSettings');
-            });
+            }
         },
         onClose: function (e) {
-            uiEnabled(false);
+            enabledUI(false);
             console.log("WS: disconnected");
             addMessage("❌ disconnected");
         },
         onError: function (e) {
-            uiEnabled(false);
+            enabledUI(false);
             console.log("WS: error");
             addMessage("❗️ error");
         },
@@ -110,7 +142,8 @@ function sendAction(action) {
 function loadSettings(data) {
     settings.brightness = data.brightness;
     settings.interval = data.interval;
-    uiEnabled(true);
+    colorPicker.color.rgb = data.color;
+    enabledUI(true);
     $('#rangeBrightness').val(mapRange(data.brightness, 8, 255, 1, 100));
     $('#rangeSpeed').val(mapRange(data.interval, 1000, 10, 1, 100));
     sendAction('getHighscores');
diff --git a/src/display.cpp b/src/display.cpp
index c30d059..217b298 100644
--- a/src/display.cpp
+++ b/src/display.cpp
@@ -14,7 +14,8 @@ const uint8_t kMatrixOptions = (SMARTMATRIX_OPTIONS_NONE);    // see http://docs
 const uint8_t kBackgroundLayerOptions = (SM_BACKGROUND_OPTIONS_NONE);
 const uint8_t kIndexedLayerOptions = (SM_INDEXED_OPTIONS_NONE);
 
-rgb24 colorWhite = {0xff, 0xff, 0xff};
+rgb24 gameColor = {colorR, colorG, colorB};
+rgb24 textColor = {255, 255, 255};
 
 SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth, kMatrixHeight, kRefreshDepth, kDmaBufferRows, kPanelType, kMatrixOptions);
 SMARTMATRIX_ALLOCATE_BACKGROUND_LAYER(backgroundLayer, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kBackgroundLayerOptions);
@@ -27,6 +28,7 @@ void setupDisplay()
   matrix.begin();
   matrix.setBrightness(defaultBrightness);
   indexedLayer.setFont(font3x5);
+  indexedLayer.setIndexedColor(1, textColor);
   backgroundLayer.setBrightness(255);
   backgroundLayer.enableColorCorrection(true);
 }
@@ -42,7 +44,7 @@ void displayLoop()
       {
         if (g[i][j])
         {
-          backgroundLayer.drawPixel(j, i, colorWhite);
+          backgroundLayer.drawPixel(j, i, gameColor);
         }
       }
     }
@@ -83,6 +85,13 @@ void gameBrightness(int brightness)
   backgroundLayer.setBrightness(brightness);
 }
 
+void setGameColor(uint8_t r, uint8_t g, uint8_t b)
+{
+  gameColor.red = r;
+  gameColor.green = g;
+  gameColor.blue = b;
+}
+
 void clearDisplay()
 {
   indexedLayer.fillScreen(0);
diff --git a/src/display.h b/src/display.h
index 52ccbe3..a0a17cd 100644
--- a/src/display.h
+++ b/src/display.h
@@ -8,6 +8,9 @@
 extern bool runGame;
 extern int defaultBrightness;
 extern int gameEra;
+extern uint8_t colorR;
+extern uint8_t colorG;
+extern uint8_t colorB;
 
 void setupDisplay();
 void displayLoop();
@@ -15,6 +18,7 @@ void showEndScreen(int ticks);
 void showMessage(char* msg);
 void displayBrightness(int brightness);
 void gameBrightness(int brightness);
+void setGameColor(uint8_t r, uint8_t g, uint8_t b);
 void clearDisplay();
 
 #endif
diff --git a/src/main.cpp b/src/main.cpp
index 6ed2e41..5dcbb65 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -7,6 +7,9 @@
 
 int defaultBrightness;
 int gameInterval;
+uint8_t colorR;
+uint8_t colorG;
+uint8_t colorB;
 
 unsigned long lastTick;
 
@@ -17,7 +20,6 @@ void showTitle() {
   showMessage(msg);
 }
 
-
 void setup()
 {
   Serial.begin(115200);
diff --git a/src/network.cpp b/src/network.cpp
index cdbc9b0..5f78cd8 100644
--- a/src/network.cpp
+++ b/src/network.cpp
@@ -266,7 +266,11 @@ void updateSettings(StaticJsonDocument<200U> doc)
 {
   gameInterval = doc["settings"]["interval"];
   defaultBrightness = doc["settings"]["brightness"];
+  colorR = doc["settings"]["color"]["r"];
+  colorG = doc["settings"]["color"]["g"],
+  colorB = doc["settings"]["color"]["b"];
   displayBrightness(defaultBrightness);
+  setGameColor(colorR, colorG, colorB);
 }
 
 void sendSettings()
@@ -275,6 +279,10 @@ void sendSettings()
   JsonObject settings = doc.createNestedObject("settings");
   settings["brightness"] = defaultBrightness;
   settings["interval"] = gameInterval;
+  JsonObject color = settings.createNestedObject("color");
+  color["r"] = colorR;
+  color["g"] = colorG;
+  color["b"] = colorB;
   size_t strsize = measureJson(doc) + 1;
   char json[strsize];
   serializeJson(doc, json, strsize);
diff --git a/src/settings.cpp b/src/settings.cpp
index a7c7875..697212f 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -8,14 +8,21 @@ void loadSettings() {
   preferences.begin("settings", true); // true = readonly
   defaultBrightness = preferences.getUInt("brightness", 50);
   gameInterval = preferences.getUInt("interval", 100);
+  colorR = preferences.getUInt("color_r", 255);
+  colorG = preferences.getUInt("color_g", 255);
+  colorB = preferences.getUInt("color_b", 255);
   preferences.end();
   displayBrightness(defaultBrightness);
+  setGameColor(colorR, colorG, colorB);
 }
 
 void saveSettings() {
   preferences.begin("settings", false);
   preferences.putUInt("brightness", defaultBrightness);
   preferences.putUInt("interval", gameInterval);
+  preferences.putUInt("color_r", colorR);
+  preferences.putUInt("color_g", colorG);
+  preferences.putUInt("color_b", colorB);
   preferences.end();  
 }
 
diff --git a/src/settings.h b/src/settings.h
index 05a0964..b70038f 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -7,6 +7,9 @@
 
 extern int defaultBrightness;
 extern int gameInterval;
+extern uint8_t colorR;
+extern uint8_t colorG;
+extern uint8_t colorB;
 
 typedef struct {
     int games;
-- 
GitLab