diff options
author | jakob.stendahl <jakob.stendahl@infomedia.dk> | 2022-12-04 13:33:45 +0100 |
---|---|---|
committer | Jakob Stendahl <jakob.stendahl@outlook.com> | 2022-12-04 13:34:22 +0100 |
commit | c3b4742eeceee9250f8059972dd150f38e2eb021 (patch) | |
tree | edde9ea65b554ff345788a916f238aed4a772b35 | |
parent | c5dc2dfb92e4a6584d1e727bc39b8c9578f85b57 (diff) | |
download | Luxcena-Neo-c3b4742eeceee9250f8059972dd150f38e2eb021.tar.gz Luxcena-Neo-c3b4742eeceee9250f8059972dd150f38e2eb021.zip |
Fix simulation stuttering (still resource intensive) and some oter QOL upgrades
-rw-r--r-- | NeoRuntime/Runtime/luxcena_neo/strip.py | 20 | ||||
-rw-r--r-- | src/NeoRuntimeManager/index.js | 19 | ||||
-rw-r--r-- | src/SelfUpdater/index.js | 2 | ||||
-rw-r--r-- | src_frontend/ComponentLib/Button/EditorActionButton.svelte | 82 | ||||
-rw-r--r-- | src_frontend/Components/Editor/Controls.svelte | 6 | ||||
-rw-r--r-- | src_frontend/Components/Editor/Editor.svelte | 42 | ||||
-rw-r--r-- | src_frontend/Components/Editor/Output.svelte | 13 | ||||
-rw-r--r-- | src_frontend/Components/Editor/Pane.svelte | 14 | ||||
-rw-r--r-- | src_frontend/Components/Editor/Simulation.svelte | 46 | ||||
-rw-r--r-- | src_frontend/Components/Editor/TopBar.svelte | 3 |
10 files changed, 222 insertions, 25 deletions
diff --git a/NeoRuntime/Runtime/luxcena_neo/strip.py b/NeoRuntime/Runtime/luxcena_neo/strip.py index 0d23069..aa5b2d2 100644 --- a/NeoRuntime/Runtime/luxcena_neo/strip.py +++ b/NeoRuntime/Runtime/luxcena_neo/strip.py @@ -1,9 +1,27 @@ import json from os import path -import rpi_ws281x as ws from .matrix import Matrix, get_segment_range from .power_calc import calcCurrent +""" import rpi_ws281x library, or import dummy version. """ +try: + import rpi_ws281x as ws +except ModuleNotFoundError: + """ Dummy STRIP used for debugging purposes """ + class STRIP: + def __init__(self, *args, **kwargs): pass + def begin(self, *args): pass + def blank(self): pass + def show(self): pass + def setPixelColor(self, *args): pass + def setBrightness(self, *args): pass + """ Dummy ws implementation """ + class WS: + WS2812_STRIP = 1 + Adafruit_NeoPixel = STRIP + def __init__(*args): print("rpi_ws281x is not installed, using a dummy module") + ws = WS() + class Strip: diff --git a/src/NeoRuntimeManager/index.js b/src/NeoRuntimeManager/index.js index eb38632..1a56b04 100644 --- a/src/NeoRuntimeManager/index.js +++ b/src/NeoRuntimeManager/index.js @@ -33,6 +33,8 @@ let modeDebuggerId = null; let modeDebuggerProcStartHandler = null; /** @type {object} The last received matrix setup */ let matrix = null; +/** @type {object} intervall for sending current state */ +let debugModeStateEmitIntervall = null; eventEmitter.on("proc:exit", (code) => modeExitCode = code); eventEmitter.on("matrix", (_matrix) => matrix = _matrix); @@ -131,7 +133,9 @@ function stopMode(restart=false) { * @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?"}; } + if (runtimeProcess === null) { + return {success: false, reason: "no runtimeprocess", detail: "Runtimeprocess not set, did you mean to call setMode?"}; + } return runtimeProcess.start(); }; @@ -226,6 +230,14 @@ function setVariable(name, value) { } /** + * A function intented to be used in an interval to emit + * the current debug-state. + * + */ +function debugModeEmitState() { +} + +/** * Start debugger for a mode * * @param {string} modeId - The mode to debug @@ -248,6 +260,11 @@ function startDebugger(debuggerModeId) { console.log(modeDebuggerProcStartHandler); } + if (debugModeStateEmitIntervall == null) { + debugModeStateEmitIntervall = setInterval(() => { + }, 500); + } + modeDebuggerActive = true; modeDebuggerId = debuggerModeId; setTimeout(() => { diff --git a/src/SelfUpdater/index.js b/src/SelfUpdater/index.js index 68f6a1d..cc7ce13 100644 --- a/src/SelfUpdater/index.js +++ b/src/SelfUpdater/index.js @@ -212,7 +212,7 @@ class Updater { let arch = (await this.run(`uname`, ["-m"])).out.replace("\n",""); if (arch == "armv6l") { await this.run("wget", ["https://unofficial-builds.nodejs.org/download/release/v14.10.0/node-v14.10.0-linux-armv6l.tar.gz"]); - await this.run("tar", ["-xzf" "node-v14.10.0-linux-armv6l.tar.gz"]); + await this.run("tar", ["-xzf", "node-v14.10.0-linux-armv6l.tar.gz"]); await this.run("cp", ["-r", "node-v14.10.0-linux-armv6l/*", "/usr/local"]); await this.run("rm", ["-r", "node-v14.10.0-linux-armv6l"]); await this.run("rm", ["node-v14.10.0-linux-armv6l.tar.gz"]); diff --git a/src_frontend/ComponentLib/Button/EditorActionButton.svelte b/src_frontend/ComponentLib/Button/EditorActionButton.svelte new file mode 100644 index 0000000..148720c --- /dev/null +++ b/src_frontend/ComponentLib/Button/EditorActionButton.svelte @@ -0,0 +1,82 @@ +<script> + export let faIcon = false; + export let fullWidth = false; + export let backgroundColor = "#444242"; + export let color = "white"; + + export let loadingPromise = null; + $: listen(loadingPromise); + function listen(promise) { + if (promise != null) { + loading = true; + promise.then(res => { + loading = false; + success = true; + }).catch(err => { + loading = false; + success = false; + }); + } else { + loading = false; + } + } + let loading; + let success; +</script> + +<style> + button { + background: #444242; + color: var(--color); + border: none; + text-decoration: none; + /*padding: 5px 15px;*/ + /*font-size: 15px;*/ + + transition: background-color, color 0.1s ease; + border-radius: 15px; + } + button:hover { + filter: brightness(0.95); + } + button:active { + filter: brightness(0.90); + } + .fullWidth { + width: 100%; + } + .iconButton { + display: flex; + } + .iconButton .text { + margin: auto; + } + .active { + background-color: var(--active-bg-color); + color: var(--active-color); + } + i { + } +</style> + +<button + on:click + class:fullWidth={fullWidth} + class:iconButton={faIcon != false} + style="--bg-color: {backgroundColor}; + --color: {color};"> + + {#if faIcon} + <div class="icon"> + <i class={faIcon}></i> + </div> + {/if} + + {#if loading} + <i class="fas fa-spinner fa-pulse"></i> + {:else} + <div class="text"> + <slot></slot> + </div> + {/if} +</button> diff --git a/src_frontend/Components/Editor/Controls.svelte b/src_frontend/Components/Editor/Controls.svelte index 85450a5..36dd9f0 100644 --- a/src_frontend/Components/Editor/Controls.svelte +++ b/src_frontend/Components/Editor/Controls.svelte @@ -34,6 +34,10 @@ }); onMount(() => { + power_on = false; + brightnessValue = 0; + variables = {}; + openSocket.emit("power:get"); openSocket.emit("brightness:get"); openSocket.emit("vars:get") @@ -100,4 +104,4 @@ {/if} </div> {/each} -</div>
\ No newline at end of file +</div> diff --git a/src_frontend/Components/Editor/Editor.svelte b/src_frontend/Components/Editor/Editor.svelte index d77b4f5..4328222 100644 --- a/src_frontend/Components/Editor/Editor.svelte +++ b/src_frontend/Components/Editor/Editor.svelte @@ -2,7 +2,7 @@ let debuggerInitialised = false; </script> <script> - import { onDestroy } from "svelte"; + import { onMount, onDestroy } from "svelte"; import { get } from "svelte/store"; import { pop } from "svelte-spa-router"; import { EditorState, basicSetup } from "@codemirror/basic-setup" @@ -12,6 +12,7 @@ import { python } from "@codemirror/lang-python" import { HighlightStyle, tags as t } from "@codemirror/highlight" import { notif } from "../../stores/notifs"; + import EditorActionButton from "../../ComponentLib/Button/EditorActionButton.svelte"; import TopBar from "./TopBar.svelte"; import Pane from "./Pane.svelte"; import Controls from "./Controls.svelte"; @@ -200,11 +201,11 @@ parent: codeEditorEl }) }); - authorizedSocket.on("receivededitor:proc:start", () => { + authorizedSocket.on("editor:proc:start", () => { console.log("received editor:proc:start"); procIsRunning = true }); - authorizedSocket.on("received editor:proc:exit", (code) => { + authorizedSocket.on("editor:proc:exit", (code) => { console.log("received editor:proc:exit"); procIsRunning = false; }); @@ -236,6 +237,18 @@ }); } + let simulationEnabled; + let simulationToggleFn; + let simulationBackgrounds = ["--default-bg", "black", "white"]; + let simlulationBackgroundI = 0; + function toggleSimulationPower() { simulationToggleFn(); } + function nextSimulationBackground() { + simlulationBackgroundI++; + if (simlulationBackgroundI >= simulationBackgrounds.length) { + simlulationBackgroundI = 0; + } + } + function saveCode(fn) { if (codeEditorView == null) { return; } console.log("emitting editor:save"); @@ -257,6 +270,14 @@ }); } + onMount(() => { + codeEditorHasChanges = false; + procIsRunning = false; + failCount = 0; + reconnecting = false; + initDebugger(); + }); + onDestroy(() => { if (get(openSocketConnected)) { closeDebugger(); @@ -327,10 +348,19 @@ on:stop={stopProc} on:restart={restartProc} bind:procIsRunning={procIsRunning} /> -<main use:initDebugger> +<main> <div class="simulation"> - <Pane header="simulation"> - <Simulation /> + <Pane header="simulation" contentBackground={simulationBackgrounds[simlulationBackgroundI]}> + <svelte:fragment slot="actions"> + <EditorActionButton faIcon="fas fa-tint" + on:click={nextSimulationBackground} + alt="Toggle simulation"></EditorActionButton> + <EditorActionButton faIcon="fas fa-power-off" + on:click={toggleSimulationPower} + color={simulationEnabled ? "green" : "red"} + alt="Toggle simulation"></EditorActionButton> + </svelte:fragment> + <Simulation bind:toggleEnable={simulationToggleFn} bind:enabled={simulationEnabled} /> </Pane> </div> diff --git a/src_frontend/Components/Editor/Output.svelte b/src_frontend/Components/Editor/Output.svelte index 52b7216..59072f9 100644 --- a/src_frontend/Components/Editor/Output.svelte +++ b/src_frontend/Components/Editor/Output.svelte @@ -1,10 +1,12 @@ <script> + import { onMount, onDestroy } from "svelte"; import { authorizedSocket, authorizedSocketNeeded } from "../../stores/socketStore"; authorizedSocketNeeded.set(true); let scrollBox; let htmlCode = ""; let buffer = ""; + let flushBufferInterval; function addData(data, classname) { // let styles = "white-space:pre-wrap;margin:0;"; @@ -28,12 +30,21 @@ 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")); authorizedSocket.on("editor:proc:stdout", (stdout) => addData(stdout, "stdout")); authorizedSocket.on("editor:proc:stderr", (stderr) => addData(stderr, "stderr")); + + onMount(() => { + htmlCode = ""; + buffer = ""; + flushBuffer = setInterval(flushBuffer, 400); + }); + + onDestroy(() => { + clearInterval(flushBufferInterval); + }); </script> <style> diff --git a/src_frontend/Components/Editor/Pane.svelte b/src_frontend/Components/Editor/Pane.svelte index 143c569..4a375ac 100644 --- a/src_frontend/Components/Editor/Pane.svelte +++ b/src_frontend/Components/Editor/Pane.svelte @@ -2,11 +2,14 @@ export let header; export let padding = true; export let scrollable = true; + + export let contentBackground = "--default-bg"; </script> <style> .box { - background-color: #444242; + --default-bg: #444242; + background-color: var(--default-bg, #444242); border-radius: 5px; height: 100%; } @@ -15,14 +18,18 @@ padding: 10px; box-sizing: border-box; border-bottom: 1px solid #333333; + display: flex; + align-items: baseline; } .header h1 { margin: 0; + margin-right: auto; font-size: 12px; font-weight: bold; text-transform: uppercase; } .content { + background-color: var(--content-bg, #444242); height: calc(100% - 35px); width: 100%; box-sizing: border-box; @@ -31,11 +38,12 @@ .scrollable { overflow: auto; } </style> -<div class="box"> +<div class="box" style="--content-bg: {contentBackground}"> <div class="header"> <h1>{header}</h1> + <slot name="actions"></slot> </div> <div class="content" class:padding={padding} class:scrollable={scrollable}> <slot></slot> </div> -</div>
\ No newline at end of file +</div> diff --git a/src_frontend/Components/Editor/Simulation.svelte b/src_frontend/Components/Editor/Simulation.svelte index 86cc66c..3a35946 100644 --- a/src_frontend/Components/Editor/Simulation.svelte +++ b/src_frontend/Components/Editor/Simulation.svelte @@ -1,11 +1,24 @@ <script> - import { onMount } from "svelte"; + import { onMount, onDestroy } from "svelte"; import { authorizedSocket, authorizedSocketNeeded } from "../../stores/socketStore"; authorizedSocketNeeded.set(true); + export let enabled = true; + + let target_fps = 60; let svg; let pixels = []; let pixelBuffer = []; + let pixelBufferCh = false; + let pixelFlushInterval; + + export function toggleEnable() { + enabled = !enabled; + if (!enabled) { + pixelBuffer = pixelBuffer.map(x => 0); + flushPixelBuffer(true); + } + } function updateMatrix(matrix) { if (matrix == null) { return; } @@ -25,31 +38,45 @@ } async function updateColors(colors) { + if (!enabled) { return ; } pixelBuffer = colors; + pixelBufferCh = true; } - async function flushPixelBuffer() { - //console.log(pixelBuffer); + async function flushPixelBuffer(force=false) { + if (!force && (!pixelBufferCh || !enabled)) { return; } + pixelBufferCh = false; window.requestAnimationFrame((ts) => { for (let i = 0; i+2 < pixelBuffer.length; i+=3) { + let pixel; try { - document.querySelector("#sim-pixel-"+(i/3)) - .style - .setProperty( - "fill", - `rgb(${pixelBuffer[i]}, ${pixelBuffer[i+1]}, ${pixelBuffer[i+2]})`); + pixel = document.querySelector("#sim-pixel-"+(i/3)); + if (pixel == null) { continue; } + pixel.style.setProperty( + "fill", + `rgb(${pixelBuffer[i]}, ${pixelBuffer[i+1]}, ${pixelBuffer[i+2]})` + ); } catch(e) { + console.log(pixel); console.log(e); } } }); } - setInterval(flushPixelBuffer, 50); onMount(() => { + pixels = []; + pixelBuffer = []; + enabled = false; authorizedSocket.on("matrix", updateMatrix); authorizedSocket.on("strip_buffer", updateColors); authorizedSocket.emit("matrix:get"); + + pixelFlushInterval = setInterval(flushPixelBuffer, 1000/target_fps); + }); + + onDestroy(() => { + clearInterval(pixelFlushInterval); }); </script> @@ -67,7 +94,6 @@ </style> <div class="wrapper"> - <p>(still quite buggy, especially for very fast changing pixels, if nothing is happening, try to restart the script)</p> <svg viewBox="0 0 0 0" preserveAspectRatio="xMaxYMax" bind:this={svg}> {#each pixels as pixel} <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);" /> diff --git a/src_frontend/Components/Editor/TopBar.svelte b/src_frontend/Components/Editor/TopBar.svelte index c74adf0..6ca6e84 100644 --- a/src_frontend/Components/Editor/TopBar.svelte +++ b/src_frontend/Components/Editor/TopBar.svelte @@ -1,4 +1,5 @@ <script> + import { onMount } from "svelte"; import { createEventDispatcher } from 'svelte'; import { pop } from "svelte-spa-router"; import PrettyVar from "../../ComponentLib/PrettyVar.svelte"; @@ -59,4 +60,4 @@ <button on:click={() => dispatch("start")}><i class="fas fa-play"></i>Start</button> {/if} </div> -</div>
\ No newline at end of file +</div> |