diff options
author | Jakob Stendahl <jakob.stendahl@outlook.com> | 2022-04-28 20:06:38 +0200 |
---|---|---|
committer | Jakob Stendahl <jakob.stendahl@outlook.com> | 2022-04-28 20:08:55 +0200 |
commit | 916ab40d65c9c25f63256f2cd98be297c3da2208 (patch) | |
tree | dcf07544310fd34f79e72f34ef0e653f30a163f0 | |
parent | 4ee57ab935718a269fe7ab65b26ff27837d49003 (diff) | |
download | Luxcena-Neo-916ab40d65c9c25f63256f2cd98be297c3da2208.tar.gz Luxcena-Neo-916ab40d65c9c25f63256f2cd98be297c3da2208.zip |
:bug: Small bugfixes
-rw-r--r-- | NeoRuntime/Runtime/luxcena_neo/strip.py | 12 | ||||
-rw-r--r-- | NeoRuntime/Runtime/neo_runtime.py | 2 | ||||
-rw-r--r-- | src/NeoRuntimeManager/IPC.js | 16 | ||||
-rw-r--r-- | src/NeoRuntimeManager/RuntimeProcess.js | 9 | ||||
-rw-r--r-- | src/NeoRuntimeManager/index.js | 74 | ||||
-rw-r--r-- | src/SocketIO/index.js | 42 | ||||
-rw-r--r-- | src/UserData/index.js | 4 | ||||
-rw-r--r-- | src_frontend/App.svelte | 12 | ||||
-rw-r--r-- | src_frontend/Components/Editor/Editor.svelte | 75 | ||||
-rw-r--r-- | src_frontend/Components/Editor/Output.svelte | 9 | ||||
-rw-r--r-- | src_frontend/Components/Editor/Simulation.svelte | 27 |
11 files changed, 180 insertions, 102 deletions
diff --git a/NeoRuntime/Runtime/luxcena_neo/strip.py b/NeoRuntime/Runtime/luxcena_neo/strip.py index d673e1b..0d23069 100644 --- a/NeoRuntime/Runtime/luxcena_neo/strip.py +++ b/NeoRuntime/Runtime/luxcena_neo/strip.py @@ -16,7 +16,7 @@ class Strip: self.LED_PIN = int(strip_conf["led_pin"]) # 18 uses PWM, 10 uses SPI /dev/spidev0.0 self.LED_DMA = int(strip_conf["led_dma"]) # DMA channel for generating the signal, on the newer ones, try 10 self.LED_COUNT = sum(self.SEGMENTS) # Number of LEDs in strip - + # Setup the color calibration array if ("color_calibration" in strip_conf) and (strip_conf["color_calibration"] != ""): self.COLOR_CALIBRATION = strip_conf["led_calibration"] @@ -34,7 +34,7 @@ class Strip: self.__set_brightness = 255 # Keeping what the brightness actually is self.__actual_brightness = self.__set_brightness - + # Setup the strip instance self.strip = ws.Adafruit_NeoPixel( self.LED_COUNT, @@ -50,7 +50,7 @@ class Strip: # Blank out all the LEDs self.blank() - + # Setup matrix print(" * Generating matrix") # try: @@ -58,7 +58,7 @@ class Strip: self.pixelMatrix.dump() # except: # print("Something went wrong while setting up your self-defined matrix.") - + # Read in state file, so we can revoces the last state. self.__globvars_path = path.join(path.split(path.dirname(path.abspath(__file__)))[0], "state.json") if path.exists(self.__globvars_path): @@ -100,7 +100,7 @@ class Strip: self.save_globvars() else: raise Exception("Value ({}) outside allowed range (0-255)".format(value)) - + def _set_brightness(self, value): self.__actual_brightness = value self.strip.setBrightness(value) @@ -145,7 +145,7 @@ class Strip: def get_pixel_color(self, n): """Get the 24-bit RGB color value for the LED at position n.""" return self.strip.getPixelColor(n) - + def blank(self): """Will turn off all pixels, this also calls show for you.""" for n in range(self.LED_COUNT): diff --git a/NeoRuntime/Runtime/neo_runtime.py b/NeoRuntime/Runtime/neo_runtime.py index 01e5a9e..7733a4b 100644 --- a/NeoRuntime/Runtime/neo_runtime.py +++ b/NeoRuntime/Runtime/neo_runtime.py @@ -119,7 +119,7 @@ class NeoRuntime: ws.close() last_send = time.perf_counter() - + if self.__send_strip_buffer: time.sleep(0.05) buffer = [2] diff --git a/src/NeoRuntimeManager/IPC.js b/src/NeoRuntimeManager/IPC.js index 6428a13..56c8b5d 100644 --- a/src/NeoRuntimeManager/IPC.js +++ b/src/NeoRuntimeManager/IPC.js @@ -61,7 +61,7 @@ class IPC { .on('connect', () => { clearInterval(this.reconnectInterval); this.reconnectInterval = false; - // logger.info("IPC Connected."); + logger.info("IPC Connected."); }) .on("ready", () => { this.connected = true; @@ -100,30 +100,30 @@ class IPC { } this.eventEmitter.emit("matrix", json_data); break; - + case DATATYPE.STRIP_BUF: this.eventEmitter.emit("strip_buffer", Array.from(data.values()).slice(1)); break; - + default: logger.info(data); } - + }) .on("timeout", () => { logger.info("IPC Timeout"); }) .on("close", (hadError) => { - // logger.info("IPC Close, hadError: ", hadError); + logger.info("IPC Close, hadError: ", hadError); this.connected = false; this.reconnect(); }) .on("end", () => { - // logger.info("IPC End"); + logger.info("IPC End"); this.connected = false; }) .on('error', (data) => { - // logger.info('IPC Server not active.'); + logger.info('IPC Server not active.'); this.connected = false; this.reconnect(); }) @@ -137,7 +137,7 @@ class IPC { sendCommand(commandType, name, value) { if (this.connected) { let buf; - + switch (commandType) { case (COMMAND.SET_GLOB): buf = Buffer.allocUnsafe(3); diff --git a/src/NeoRuntimeManager/RuntimeProcess.js b/src/NeoRuntimeManager/RuntimeProcess.js index c5c4749..be78fa9 100644 --- a/src/NeoRuntimeManager/RuntimeProcess.js +++ b/src/NeoRuntimeManager/RuntimeProcess.js @@ -23,12 +23,12 @@ class RuntimeProcess { start() { if (this.isRunning) { console.log("PROCESS ALREADY RUNNING"); - return; + return {success: false, reason: "already running"}; } this.isRunning = true; this.proc = spawn.spawn( - `${__appdir}/NeoRuntime/Runtime/venv/bin/python`, - //"python", + // `${__appdir}/NeoRuntime/Runtime/venv/bin/python`, + "python3", [ "-u", // This makes us able to get real-time output `${__appdir}/NeoRuntime/Runtime/neo_runtime.py`, @@ -75,6 +75,7 @@ class RuntimeProcess { this.exitCode = code; }); + return {success: true}; } stop(restart=false) { @@ -85,8 +86,10 @@ class RuntimeProcess { }); } this.proc.kill("SIGINT"); + return {success: true} } catch (err) { console.log(err); + return {success:false, reason:err} } } } diff --git a/src/NeoRuntimeManager/index.js b/src/NeoRuntimeManager/index.js index a178bf1..eb38632 100644 --- a/src/NeoRuntimeManager/index.js +++ b/src/NeoRuntimeManager/index.js @@ -39,9 +39,9 @@ eventEmitter.on("matrix", (_matrix) => matrix = _matrix); /** * Check if a path id actually a mode (if it is a folder with a script.py file) - * + * * @param {string} path - Path to check. - * + * * @return {boolean} wether the path points to a valid mode. */ function isMode(path) { @@ -54,7 +54,7 @@ function isMode(path) { /** * Get all ids of modes that can be set. - * + * * @returns {array} All modeids */ function listModes() { @@ -77,9 +77,9 @@ function listModes() { /** * Change mode, stop the old one and start the new one. - * + * * @param {string} _modeId - Id of the mode to change to. - * + * * @return {object} A standardform return object. */ function setMode(_modeId) { @@ -93,7 +93,7 @@ function setMode(_modeId) { logger.info(`Changing mode to "${_modeId}".`); stopMode(); - + modeId = _modeId; neoModules.userData.config.activeMode = modeId; eventEmitter.emit("change", "mode", modeId); @@ -106,7 +106,7 @@ function setMode(_modeId) { /** * Get current mode - * + * * @return {string} current modeId */ function currentMode() { @@ -115,7 +115,7 @@ function currentMode() { /** * Will attempt to stop current mode - * + * * @return {object} A standardform return object. */ function stopMode(restart=false) { @@ -127,18 +127,17 @@ function stopMode(restart=false) { /** * Will attempt to start current mode - * + * * @return {object} A standardform return object. */ function startMode() { if (runtimeProcess === null) { return {success: false, reason: "no runtimeprocess", detail: "Runtimeprocess not set, did you mean to call setMode?"}; } - runtimeProcess.start(); - return {success: true} + return runtimeProcess.start(); }; /** * Will attempt to restart current mode - * + * * @return {object} A standardform return object. */ function restartMode() { @@ -147,7 +146,7 @@ function restartMode() { /** * Checks if mode is running currently - * + * * @return {boolean} if mode is running */ function modeRunning() { @@ -157,9 +156,9 @@ function modeRunning() { /** * Get the full system path to a mode - * + * * @param {string} modeId - * + * * @return {string} Full path of mode */ function getModePath(modeId) { @@ -172,24 +171,9 @@ function getModePath(modeId) { } /** - * This should be called by RuntimeProcess when a variable changes in the mode - * - * @param {string} location - This is globvars/variables - * @param {string} name - Name of the variable - * @param {any} newValue - The new value of the variable - */ -function onVariableChange(location, name, newValue) { - if (location == "variables") { - eventEmitter.emit("change", `variable/${name}`, newValue) - } else if (location == "globvars") { - eventEmitter.emit("change", `${name}`, newValue) - } -} - -/** * Function that returns all globvars (brightness, power_on) as the values they * had last time we heard from the python script. - * + * * @return {object} */ function getGlobvars() { @@ -199,15 +183,15 @@ function getGlobvars() { /** * Sets value of a globvar power_on/brightness. - * + * * @param {string} name - Name of the variable power_on/brightness * @param {any} value - The value the variable should be set to - * + * * @return {object} Standardform return object */ function setGlobvar(name, value) { if (!modeRunning()) { return; } - + switch(name) { case "power_on": return ipc.sendCommand(IPC.COMMAND.SET_GLOB, IPC.GLOBVAR.POWER_ON, (value) ? 1 : 0); @@ -220,7 +204,7 @@ function setGlobvar(name, value) { /** * Get all variables declared in mode - * + * * @return {object} */ function getVariables() { @@ -230,10 +214,10 @@ function getVariables() { /** * Sets value of a variable - * + * * @param {string} name - Name of the variable * @param {any} value - The value the variable should be set to - * + * * @return {object} Standardform return object */ function setVariable(name, value) { @@ -243,9 +227,9 @@ function setVariable(name, value) { /** * Start debugger for a mode - * + * * @param {string} modeId - The mode to debug - * + * * @return {object} Standardform return object */ function startDebugger(debuggerModeId) { @@ -258,17 +242,17 @@ function startDebugger(debuggerModeId) { modeDebuggerProcStartHandler = eventEmitter.on("proc:start", () => { setTimeout(() => { ipc.sendCommand(IPC.COMMAND.SET_SEND_STRIP_BUF, true); - }, 500); + }, 2000); }); + } else { + console.log(modeDebuggerProcStartHandler); } modeDebuggerActive = true; modeDebuggerId = debuggerModeId; - if (debuggerModeId != modeId) { + setTimeout(() => { setMode(debuggerModeId); - } else { - restartMode(); - } + }, 300); return {success: true, code: fs.readFileSync(getModePath(debuggerModeId) + "/script.py").toString()} } @@ -284,7 +268,7 @@ function saveModeCode(_modeId, code) { /** * Stop the active debugger - * + * * @return {object} Standardform return object */ function stopDebugger() { diff --git a/src/SocketIO/index.js b/src/SocketIO/index.js index 88b5459..ff8f378 100644 --- a/src/SocketIO/index.js +++ b/src/SocketIO/index.js @@ -12,6 +12,7 @@ let logger = require(__appdir + "/src/Logger"); var exec = require('child_process').exec; var CryptoJS = require("crypto-js"); let fs = require("fs"); +const { performance } = require("perf_hooks"); let neoModules; @@ -82,7 +83,7 @@ function createOpenSocketNamespace(io) { } session_tokens[token] = { - expire: (~~Date.now())+(86400), + expire: (~~Date.now())+(2678400), host: socket.handshake.headers.host, user: {username: user.username} }; @@ -139,7 +140,7 @@ function authorize_middleware(socket, next) { const token = socket.handshake.auth.token; if (session_tokens.hasOwnProperty(token) && - session_tokens[token].host === socket.handshake.headers.host && + // session_tokens[token].host === socket.handshake.headers.host && session_tokens[token].expire > (~~(Date.now()))) { socket.data.user = session_tokens[token].user; next(); @@ -266,8 +267,8 @@ function createAuthorizedNamespace(io) { /* Editor/debugger */ let onProcStart = () => socket.emit("editor:proc:start"); let onProcStop = (code) => socket.emit("editor:proc:exit", code); - let onProcStdout = (stdout) => socket.emit("editor:proc:stdout", stdout); - let onProcStderr = (stderr) => socket.emit("editor:proc:stderr", stderr); + let onProcStdout = (stdout) => socket.volatile.emit("editor:proc:stdout", stdout); + let onProcStderr = (stderr) => socket.volatile.emit("editor:proc:stderr", stderr); let closeDebugger = () => { debuggerOpen = false; neoModules.neoRuntimeManager.event.removeListener("proc:start", onProcStart); @@ -277,6 +278,10 @@ function createAuthorizedNamespace(io) { return neoModules.neoRuntimeManager.stopDebugger(); }; socket.on("editor:open", (modeId, fn) => { + neoModules.neoRuntimeManager.event.on("proc:start", onProcStart); + neoModules.neoRuntimeManager.event.on("proc:exit", onProcStop); + neoModules.neoRuntimeManager.event.on("proc:stdout", onProcStdout); + neoModules.neoRuntimeManager.event.on("proc:stderr", onProcStderr); let res = neoModules.neoRuntimeManager.startDebugger(modeId); if (!res.success) { fn(res); return; } logger.info(`Starting debugger for ${modeId}.`) @@ -284,20 +289,21 @@ function createAuthorizedNamespace(io) { fn({success: true}) socket.emit("editor:code", modeId, res.code); - neoModules.neoRuntimeManager.event.on("proc:start", onProcStart); - neoModules.neoRuntimeManager.event.on("proc:exit", onProcStop); - neoModules.neoRuntimeManager.event.on("proc:stdout", onProcStdout); - neoModules.neoRuntimeManager.event.on("proc:stderr", onProcStderr); if (neoModules.neoRuntimeManager.modeRunning()) { socket.emit("editor:proc:start"); } }); socket.on("editor:save", (modeId, code, fn) => { - if (!debuggerOpen) { fn({success: false, reason: "Debugger not open"}); return; }; + if (!debuggerOpen) { fn({success: false, reason: "debugger not open"}); return; }; fn(neoModules.neoRuntimeManager.saveModeCode(modeId, code)); }); socket.on("editor:startmode", (fn) => { - fn(neoModules.neoRuntimeManager.startMode()); + if (neoModules.neoRuntimeManager.modeRunning()) { + fn({success: true}); + socket.emit("editor:proc:start"); + } else { + fn(neoModules.neoRuntimeManager.startMode()); + } }); socket.on("editor:stopmode", (fn) => { fn(neoModules.neoRuntimeManager.stopMode()); @@ -327,8 +333,12 @@ function createAuthorizedNamespace(io) { neoModules.neoRuntimeManager.event.on("matrix", (matrix) => { authorizedNamespace.emit("matrix", matrix); }); + let lastStripBufferEmit = performance.now(); neoModules.neoRuntimeManager.event.on("strip_buffer", (strip_buffer) => { - authorizedNamespace.emit("strip_buffer", strip_buffer); + if ((performance.now() - lastStripBufferEmit) > 50) { + authorizedNamespace.volatile.emit("strip_buffer", strip_buffer); + lastStripBufferEmit = performance.now(); + } // We just drop packets }); neoModules.selfUpdater.updater.event.on("step", (step) => { authorizedNamespace.emit("updater:step", step); @@ -342,6 +352,16 @@ function createAuthorizedNamespace(io) { } /** + * Protect + */ +function limitEmits(fn) { + let lastEmit = performance.now(); + + return { + } +} + +/** * Creates an access-token from the clients host-name and the current EPOCH. * * @param {client} diff --git a/src/UserData/index.js b/src/UserData/index.js index 5ac32f6..e442a79 100644 --- a/src/UserData/index.js +++ b/src/UserData/index.js @@ -57,8 +57,8 @@ function ensureStripConfig() { if (config.DEFAULT.led_dma == null) { config.DEFAULT.led_dma = 10; } if (config.DEFAULT.led_invert == null) { config.DEFAULT.led_invert = false; } if (config.DEFAULT.led_channel == null) { config.DEFAULT.led_channel = 0 } - if (config.DEFAULT.segments == null) { config.DEFAULT.segments = ""; } - if (config.DEFAULT.matrix == null) { config.DEFAULT.matrix = ""; } + if (config.DEFAULT.segments == null) { config.DEFAULT.segments = "50 50"; } + if (config.DEFAULT.matrix == null) { config.DEFAULT.matrix = "[[[0,false]],[[1,false]]]"; } fse.writeFileSync(__configdir + "/strip.ini", ini.encode(config)) } diff --git a/src_frontend/App.svelte b/src_frontend/App.svelte index d9f5f92..c5648ca 100644 --- a/src_frontend/App.svelte +++ b/src_frontend/App.svelte @@ -30,10 +30,10 @@ component: UnknownRoute })); - let updateInProgess = false; - openSocket.on("updater", (state) => { - if (state == "start") { updateInProgess = true; } - }); + //let updateInProgess = false; + //openSocket.on("updater", (state) => { + // if (state == "start") { updateInProgess = true; } + //}); </script> <style> @@ -104,7 +104,7 @@ </style> -{#if $updateInProgess || $connected} +{#if $connected} <Router routes={main_router_routes} /> {:else if $reconnecting} <div class="no-connection"> @@ -116,4 +116,4 @@ <div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div> <div>No server connection, attempting to connect...</div> </div> -{/if}
\ No newline at end of file +{/if} diff --git a/src_frontend/Components/Editor/Editor.svelte b/src_frontend/Components/Editor/Editor.svelte index fc5d589..d77b4f5 100644 --- a/src_frontend/Components/Editor/Editor.svelte +++ b/src_frontend/Components/Editor/Editor.svelte @@ -3,6 +3,7 @@ </script> <script> import { onDestroy } from "svelte"; + import { get } from "svelte/store"; import { pop } from "svelte-spa-router"; import { EditorState, basicSetup } from "@codemirror/basic-setup" import { EditorView, keymap } from "@codemirror/view" @@ -17,7 +18,7 @@ import Output from "./Output.svelte"; import Simulation from "./Simulation.svelte"; - import { authorizedSocket, authorizedSocketNeeded } from "../../stores/socketStore"; + import { authorizedSocket, authorizedSocketNeeded, openSocketConnected } from "../../stores/socketStore"; authorizedSocketNeeded.set(true); export let modeId; @@ -26,16 +27,50 @@ let codeEditorEl; let codeEditorHasChanges = false; let procIsRunning = false; + let failCount = 0; + let reconnecting = false; function initDebugger() { if (debuggerInitialised) { return; } debuggerInitialised = true; + console.log("emitting editor:open"); authorizedSocket.emit("editor:open", `user/${modeId}`, (res) => { - if (!res.success) { notif({title: res.reason, type: "danger"}); return; } + handleError(res); }); } + function notifErr(err) { + if (err.hasOwnProperty("detail")) { + notif({title: err.reason, type: "danger"}); + } else { + notif({title: err.reason, text: err.detail, type: "danger"}); + } + } + + function handleError(err) { + console.log(err); + if (err.success) { return; } + failCount++; + if (failCount < 10) { + if (err.reason == "debugger not open") { + if (!reconnecting) { + reconnecting = true; + console.log("emitting editor:open"); + authorizedSocket.emit("editor:open", `user/${modeId}`, (res) => { + reconnecting = false; + handleError(res); + }); + } + } else { + notifErr(err); + } + } else { + notifErr(err); + } + } + authorizedSocket.on("editor:code", (modeId, code) => { + console.log("received editor:code"); const chalky = "#e5c07b", coral = "#e06c75", cyan = "#56b6c2", @@ -165,38 +200,47 @@ parent: codeEditorEl }) }); - authorizedSocket.on("editor:proc:start", () => procIsRunning = true); - authorizedSocket.on("editor:proc:exit", (code) => { + authorizedSocket.on("receivededitor:proc:start", () => { + console.log("received editor:proc:start"); + procIsRunning = true + }); + authorizedSocket.on("received editor:proc:exit", (code) => { + console.log("received editor:proc:exit"); procIsRunning = false; }); function startProc() { - saveCode(() => { + saveCode((res) => { + handleError(res); + console.log("emitting editor:startmode"); authorizedSocket.emit("editor:startmode", (res) => { - if (!res.success) { notif({title: res.reason, type: "danger"}); } + handleError(res); }); }); } function stopProc() { + console.log("emitting editor:stopmode"); authorizedSocket.emit("editor:stopmode", (res) => { - if (!res.success) { notif({title: res.reason, type: "danger"}); } + handleError(res); }); } function restartProc () { saveCode((res) => { - if (!res.success) { notif({title: res.reason, type: "danger"}); } + handleError(res); + console.log("emitting editor:restartmode"); authorizedSocket.emit("editor:restartmode", (res) => { - if (!res.success) { notif({title: res.reason, type: "danger"}); } + handleError(res); }); }); } function saveCode(fn) { if (codeEditorView == null) { return; } + console.log("emitting editor:save"); authorizedSocket.emit("editor:save", `user/${modeId}`, codeEditorView.state.doc.toString(), res => { - if (!res.success) { notif({title: res.reason, type: "danger"}); } + handleError(res); if (fn != null) { fn(res) } }); codeEditorHasChanges = false; @@ -204,16 +248,21 @@ function closeDebugger() { saveCode((res) => { - if (!res.success) { notif({title: res.reason, type: "danger"}); } + handleError(res); + console.log("emitting editor:close"); authorizedSocket.emit("editor:close", res => { - if (!res.success) { notif({title: res.reason, type: "danger"}); } + handleError(res); debuggerInitialised = false; }); }); } onDestroy(() => { - closeDebugger(); + if (get(openSocketConnected)) { + closeDebugger(); + } else { + debuggerInitialised = false; + } }) document.addEventListener("keydown", function(e) { diff --git a/src_frontend/Components/Editor/Output.svelte b/src_frontend/Components/Editor/Output.svelte index 9e4c953..52b7216 100644 --- a/src_frontend/Components/Editor/Output.svelte +++ b/src_frontend/Components/Editor/Output.svelte @@ -4,6 +4,7 @@ let scrollBox; let htmlCode = ""; + let buffer = ""; function addData(data, classname) { // let styles = "white-space:pre-wrap;margin:0;"; @@ -17,11 +18,17 @@ styles += "color: red"; break; } - htmlCode += `<span style="${styles}">${data}</span>`; + buffer += `<span style="${styles}">${data}</span>`; if (scrollBox != null) { scrollBox.scrollTop = scrollBox.scrollHeight + 100; } } + + function flushBuffer() { + htmlCode += buffer; + buffer = ""; + }; + setInterval(flushBuffer, 400); authorizedSocket.on("editor:proc:start", () => htmlCode = ""); authorizedSocket.on("editor:proc:exit", (code) => addData(`\nMode exited with ${code}\n\n`, "exit")); diff --git a/src_frontend/Components/Editor/Simulation.svelte b/src_frontend/Components/Editor/Simulation.svelte index abe202c..86cc66c 100644 --- a/src_frontend/Components/Editor/Simulation.svelte +++ b/src_frontend/Components/Editor/Simulation.svelte @@ -5,6 +5,7 @@ let svg; let pixels = []; + let pixelBuffer = []; function updateMatrix(matrix) { if (matrix == null) { return; } @@ -24,12 +25,26 @@ } async function updateColors(colors) { - for (let i = 0; i+2 < colors.length; i+=3) { - try { - document.querySelector("#sim-pixel-"+(i/3)).style.setProperty("fill", `rgb(${colors[i]}, ${colors[i+1]}, ${colors[i+2]})`); - } catch(e) {} - } + pixelBuffer = colors; + } + + async function flushPixelBuffer() { + //console.log(pixelBuffer); + window.requestAnimationFrame((ts) => { + for (let i = 0; i+2 < pixelBuffer.length; i+=3) { + try { + document.querySelector("#sim-pixel-"+(i/3)) + .style + .setProperty( + "fill", + `rgb(${pixelBuffer[i]}, ${pixelBuffer[i+1]}, ${pixelBuffer[i+2]})`); + } catch(e) { + console.log(e); + } + } + }); } + setInterval(flushPixelBuffer, 50); onMount(() => { authorizedSocket.on("matrix", updateMatrix); @@ -58,4 +73,4 @@ <rect id="sim-pixel-{pixel.n}" x="{pixel.x*2+1}" y="{pixel.y*2+1}" width="1" height="1" style="fill:rgb(0,0,0);filter:blur(0.2px);" /> {/each} </svg> -</div>
\ No newline at end of file +</div> |