diff --git a/ledder/animations/Components/Pacman.ts b/ledder/animations/Components/Pacman.ts index ea6581e..10c93f8 100644 --- a/ledder/animations/Components/Pacman.ts +++ b/ledder/animations/Components/Pacman.ts @@ -85,12 +85,12 @@ export default class Pacman extends Animator { // `)) frames.centerV(box) - let pacmanBox=new PixelBox(box) + let pacmanBox = new PixelBox(box) box.add(pacmanBox) new FxMovie(scheduler, controls, 4, 0).run(frames, pacmanBox) - new FxRotate(scheduler, controls, 1).run(frames, pacmanBox) + new FxRotate(scheduler, controls, 0.01).run(frames, pacmanBox) } diff --git a/ledder/fx/FxRotate.ts b/ledder/fx/FxRotate.ts index e44cc8c..434eecd 100644 --- a/ledder/fx/FxRotate.ts +++ b/ledder/fx/FxRotate.ts @@ -17,13 +17,13 @@ export default class FxRotate extends Fx { intervalRandomizerControl: ControlValue - constructor(scheduler: Scheduler, controlGroup: ControlGroup, xStep = -1, yStep = 0, interval = 2, intervalRandomizer = 0) { + constructor(scheduler: Scheduler, controlGroup: ControlGroup, xStep = -1, yStep = 0, interval = 1, intervalRandomizer = 0) { super(scheduler, controlGroup) this.intervalControl = controlGroup.value('Rotate interval', interval, 1, 60, 1) this.intervalRandomizerControl = controlGroup.value('Rotate interval randomizer', intervalRandomizer, 0, 60, 1, true) - this.xStepControl = controlGroup.value('Rotate X step', xStep, -5, 5, 1) - this.yStepControl = controlGroup.value('Rotate Y step', yStep, -5, 5, 1) + this.xStepControl = controlGroup.value('Rotate X step', xStep, -5, 5, 0.01) + this.yStepControl = controlGroup.value('Rotate Y step', yStep, -5, 5, 0.01) } @@ -31,7 +31,7 @@ export default class FxRotate extends Fx { //waitX and waitY will stop and resolve the promise when axis has shifted this much. //If target is specified, the pixels that are within the target bounds are added to it run(container: PixelList, bbox?: BoxInterface, waitX?: number, waitY?: number, target?: PixelBox) { - if (target!==undefined && target.size) + if (target !== undefined && target.size) throw ("Please use an empty target container") this.running = true diff --git a/ledder/server/drivers/DisplayWebsocket.ts b/ledder/server/drivers/DisplayWebsocket.ts index bfb26ed..edc96c2 100644 --- a/ledder/server/drivers/DisplayWebsocket.ts +++ b/ledder/server/drivers/DisplayWebsocket.ts @@ -1,32 +1,58 @@ -import Display from "../../Display.js"; +import Display from "../../Display.js" export class DisplayWebsocket extends Display { - imageBuf8: Uint8ClampedArray; + imageBuf8: Uint8ClampedArray ws: WebSocket - //width and height are led-display-pixels, not canvas pixels. constructor(width, height, ws) { - super( width, height); + super(width, height) - this.imageBuf8 = new Uint8ClampedArray(height * width * 4); - this.ws=ws + this.imageBuf8 = new Uint8ClampedArray(height * width * 4) + this.ws = ws } //sets a pixel in the render buffer (called from Draw-classes render() functions) + //bilinear interpolation. setPixel(x, y, color) { + const x0 = ~~x + const y0 = ~~y + + const dx = x - x0 + const dy = y - y0 + + + const w00 = (1 - dx) * (1 - dy) * color.a // Weight for top-left pixel (x0, y0) + this.setPixelRounded(x0, y0, color, w00) + + const w10 = dx * (1 - dy) * color.a // Weight for top-right pixel (x0+1, y0) + this.setPixelRounded(x0 + 1, y0, color, w10) + + const w01 = (1 - dx) * dy * color.a // Weight for bottom-left pixel (x0, y0+1) + this.setPixelRounded(x0, y0 + 1, color, w01) + + const w11 = dx * dy * color.a // Weight for bottom-right pixel (x0+1, y0+1) + this.setPixelRounded(x0 + 1, y0 + 1, color, w11) + + + } + + //weighted , after linear interpolation. + setPixelRounded(x, y, color, alpha) { if (x >= 0 && x < this.width && y >= 0 && y < this.height) { - const offset = ~~x * 4 + ( ~~y ) * 4 * this.width; - const old_a = 1 - color.a; + const offset = x * 4 + (y) * 4 * this.width + const old_a = 1 - alpha + // const old_a = 1 - this.imageBuf8[offset] = (this.imageBuf8[offset] * old_a + color.r * color.a); - this.imageBuf8[offset + 1] = (this.imageBuf8[offset + 1] * old_a + color.g * color.a); - this.imageBuf8[offset + 2] = (this.imageBuf8[offset + 2] * old_a + color.b * color.a); - this.imageBuf8[offset + 3] = 255; //alpha of canvas itself + + this.imageBuf8[offset] = (this.imageBuf8[offset] * old_a + color.r * alpha) + this.imageBuf8[offset + 1] = (this.imageBuf8[offset + 1] * old_a + color.g * alpha) + this.imageBuf8[offset + 2] = (this.imageBuf8[offset + 2] * old_a + color.b * alpha) + this.imageBuf8[offset + 3] = 255 //alpha of canvas itself } } @@ -36,11 +62,9 @@ export class DisplayWebsocket extends Display { if (this.ws) this.ws.send(this.imageBuf8) - this.imageBuf8.fill(0); //alpha of all pixels will be 0, so canvas is transparent. + this.imageBuf8.fill(0) //alpha of all pixels will be 0, so canvas is transparent. } - - } diff --git a/presets/Text/Marquee/default.json b/presets/Text/Marquee/default.json index 203d7fb..d35fc2f 100644 --- a/presets/Text/Marquee/default.json +++ b/presets/Text/Marquee/default.json @@ -70,13 +70,13 @@ "value": 60 }, "Rotate interval": { - "value": 2 + "value": 1 }, "Rotate interval randomizer": { "value": 0 }, "Rotate X step": { - "value": -1 + "value": 0.33 }, "Rotate Y step": { "value": 0