From 582bf1d8c94a9efef21e3e567896ecd41c1afaa2 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Mon, 28 Jun 2021 20:31:49 -0700 Subject: [PATCH] Get timer working --- packages/webamp-modern-2/README.md | 4 +++ .../webamp-modern-2/src/skin/AnimatedLayer.ts | 1 - packages/webamp-modern-2/src/skin/Bitmap.ts | 2 -- packages/webamp-modern-2/src/skin/Button.ts | 8 +++++ packages/webamp-modern-2/src/skin/GuiObj.ts | 12 +++++-- packages/webamp-modern-2/src/skin/Layer.ts | 13 +++++--- packages/webamp-modern-2/src/skin/MakiMap.ts | 2 ++ .../webamp-modern-2/src/skin/PrivateConfig.ts | 21 ++++++++++++ .../webamp-modern-2/src/skin/SystemObject.ts | 7 ++-- packages/webamp-modern-2/src/skin/Timer.ts | 32 +++++++++++++++---- 10 files changed, 81 insertions(+), 21 deletions(-) create mode 100644 packages/webamp-modern-2/src/skin/PrivateConfig.ts diff --git a/packages/webamp-modern-2/README.md b/packages/webamp-modern-2/README.md index 30e83117..7218ff41 100644 --- a/packages/webamp-modern-2/README.md +++ b/packages/webamp-modern-2/README.md @@ -19,6 +19,10 @@ - [ ] Handle case (in)sensitivity of includes. - [ ] Handle forward/backward slashes issues (if they exist) +## Known Bugs + +- [ ] In GuiObj's handling of left click, it's possible for the y/x of the click event to fall outside of the element being clicked. To repro click just above the volume2 of MMD3. Y can be one pixel above the clientBoundingRect of the element. Why? + # Phases of Initialization ## Asset Parse diff --git a/packages/webamp-modern-2/src/skin/AnimatedLayer.ts b/packages/webamp-modern-2/src/skin/AnimatedLayer.ts index 2d84ea42..a3f17b86 100644 --- a/packages/webamp-modern-2/src/skin/AnimatedLayer.ts +++ b/packages/webamp-modern-2/src/skin/AnimatedLayer.ts @@ -1,7 +1,6 @@ import UI_ROOT from "../UIRoot"; import { ensureVmInt, px } from "../utils"; import Layer from "./Layer"; -import { VM } from "./VM"; export default class AnimatedLayer extends Layer { _currentFrame: number = 0; diff --git a/packages/webamp-modern-2/src/skin/Bitmap.ts b/packages/webamp-modern-2/src/skin/Bitmap.ts index 1fe069ee..68130808 100644 --- a/packages/webamp-modern-2/src/skin/Bitmap.ts +++ b/packages/webamp-modern-2/src/skin/Bitmap.ts @@ -108,8 +108,6 @@ export default class Bitmap { this._canvas.height = this.getHeight(); const ctx = this._canvas.getContext("2d"); ctx.drawImage(this._img, 0, 0, this.getWidth(), this.getHeight()); - document.body.appendChild(this._img); - document.body.appendChild(this._canvas); } return this._canvas; } diff --git a/packages/webamp-modern-2/src/skin/Button.ts b/packages/webamp-modern-2/src/skin/Button.ts index 8e59c8f3..3a8d6de7 100644 --- a/packages/webamp-modern-2/src/skin/Button.ts +++ b/packages/webamp-modern-2/src/skin/Button.ts @@ -63,6 +63,10 @@ export default class Button extends GuiObj { } } + onLeftClick() { + VM.dispatch(this, "onleftclick", []); + } + _renderBackground() { if (this._image != null) { const bitmap = UI_ROOT.getBitmap(this._image); @@ -78,6 +82,10 @@ export default class Button extends GuiObj { _bindToDom() { // TODO: Cleanup! this._div.addEventListener("mousedown", this._handleMouseDown.bind(this)); + this._div.addEventListener("click", (e) => { + // TODO: Only left button + this.onLeftClick(); + }); } _handleMouseDown(e: MouseEvent) { diff --git a/packages/webamp-modern-2/src/skin/GuiObj.ts b/packages/webamp-modern-2/src/skin/GuiObj.ts index 70cebb2a..981d8c00 100644 --- a/packages/webamp-modern-2/src/skin/GuiObj.ts +++ b/packages/webamp-modern-2/src/skin/GuiObj.ts @@ -92,7 +92,7 @@ export default class GuiObj extends XmlObj { * @ret The top edge's position (in screen coordinates). */ gettop(): number { - return this._div.getBoundingClientRect().top; + return this._div.getBoundingClientRect().y; } /** @@ -102,7 +102,7 @@ export default class GuiObj extends XmlObj { * @ret The left edge's position (in screen coordinates). */ getleft(): number { - return this._div.getBoundingClientRect().left; + return this._div.getBoundingClientRect().x; } /** @@ -170,6 +170,14 @@ export default class GuiObj extends XmlObj { * @param y The Y position in the screen where the cursor was when the event was triggered. */ onLeftButtonDown(x: number, y: number) { + assert( + x >= this.getleft(), + "Expected click to be to the right of the component's left" + ); + assert( + y >= this.gettop(), + "Expected click to be below the component's top" + ); VM.dispatch(this, "onleftbuttondown", [ { type: "INT", value: x }, { type: "INT", value: y }, diff --git a/packages/webamp-modern-2/src/skin/Layer.ts b/packages/webamp-modern-2/src/skin/Layer.ts index 0adccf35..37a04f26 100644 --- a/packages/webamp-modern-2/src/skin/Layer.ts +++ b/packages/webamp-modern-2/src/skin/Layer.ts @@ -1,7 +1,5 @@ import GuiObj from "./GuiObj"; import UI_ROOT from "../UIRoot"; -import { px } from "../utils"; -import Bitmap from "./Bitmap"; // http://wiki.winamp.com/wiki/XML_GUI_Objects#.3Clayer.2F.3E export default class Layer extends GuiObj { @@ -14,6 +12,7 @@ export default class Layer extends GuiObj { switch (key) { case "image": this._image = value; + this._renderBackground(); break; default: return false; @@ -45,12 +44,16 @@ export default class Layer extends GuiObj { return super.getwidth(); } - draw() { - super.draw(); - this._div.setAttribute("data-obj-name", "Layer"); + _renderBackground() { if (this._image != null) { const bitmap = UI_ROOT.getBitmap(this._image); this.setBackgroundImage(bitmap); } } + + draw() { + super.draw(); + this._div.setAttribute("data-obj-name", "Layer"); + this._renderBackground(); + } } diff --git a/packages/webamp-modern-2/src/skin/MakiMap.ts b/packages/webamp-modern-2/src/skin/MakiMap.ts index 2ec7ea14..e5f54bdb 100644 --- a/packages/webamp-modern-2/src/skin/MakiMap.ts +++ b/packages/webamp-modern-2/src/skin/MakiMap.ts @@ -15,6 +15,8 @@ export default class MakiMap extends BaseObject { // 0-255 getvalue(x: number, y: number): number { + assume(x >= 0, `Expected x to be positive but it was ${x}`); + assume(y >= 0, `Expected y to be positive but it was ${y}`); const canvas = this._bitmap.getCanvas(); const context = canvas.getContext("2d"); const { data } = context.getImageData(x, y, 1, 1); diff --git a/packages/webamp-modern-2/src/skin/PrivateConfig.ts b/packages/webamp-modern-2/src/skin/PrivateConfig.ts new file mode 100644 index 00000000..57bbfa9b --- /dev/null +++ b/packages/webamp-modern-2/src/skin/PrivateConfig.ts @@ -0,0 +1,21 @@ +// TODO: Persist this to local state? +class PrivateConfig { + _sections: Map> = new Map(); + _getSection(section: string) { + if (!this._sections.has(section)) { + this._sections.set(section, new Map()); + } + return this._sections.get(section); + } + getPrivateInt(section: string, item: string, defvalue: number) { + return this._getSection(section).get(item) ?? defvalue; + } + + setPrivateInt(section: string, item: string, value: number) { + return this._getSection(section).set(item, value); + } +} + +const PRIVATE_CONFIG = new PrivateConfig(); + +export default PRIVATE_CONFIG; diff --git a/packages/webamp-modern-2/src/skin/SystemObject.ts b/packages/webamp-modern-2/src/skin/SystemObject.ts index 4ec3d5ce..c1d2e24b 100644 --- a/packages/webamp-modern-2/src/skin/SystemObject.ts +++ b/packages/webamp-modern-2/src/skin/SystemObject.ts @@ -6,6 +6,7 @@ import BaseObject from "./BaseObject"; import Container from "./Container"; import Group from "./Group"; +import PRIVATE_CONFIG from "./PrivateConfig"; import { VM } from "./VM"; const MOUSE_POS = { x: 0, y: 0 }; @@ -83,9 +84,7 @@ export default class SystemObject extends BaseObject { * @param defvalue The defautl value to return if no item is found. */ getprivateint(section: string, item: string, defvalue: number) { - // TODO: Implement this! - // FIXME - return defvalue; + return PRIVATE_CONFIG.getPrivateInt(section, item, defvalue); } /** @@ -96,7 +95,7 @@ export default class SystemObject extends BaseObject { * @param value The value of the entry. */ setprivateint(section: string, item: string, value: number) { - // FIXME + PRIVATE_CONFIG.setPrivateInt(section, item, value); } /** diff --git a/packages/webamp-modern-2/src/skin/Timer.ts b/packages/webamp-modern-2/src/skin/Timer.ts index 6e3e2ec2..8fb8cbd3 100644 --- a/packages/webamp-modern-2/src/skin/Timer.ts +++ b/packages/webamp-modern-2/src/skin/Timer.ts @@ -1,21 +1,39 @@ +import { assume } from "../utils"; import BaseObject from "./BaseObject"; +import { VM } from "./VM"; export default class Timer extends BaseObject { + _delay: number; + _timeout: NodeJS.Timeout | null = null; setdelay(millisec: number) { - // TODO + assume( + this._timeout == null, + "Tried to change the delay on a running timer" + ); + this._delay = millisec; } stop() { - //TODO + if (this._timeout != null) { + clearTimeout(this._timeout); + this._timeout = null; + } } start() { - //TODO + assume(this._delay != null, "Tried to start a timer without a delay"); + this._timeout = setInterval(() => { + VM.dispatch(this, "ontimer"); + }, this._delay); + } + + isrunning(): boolean { + return this._timeout != null; + } + + getdelay(): number { + return this._delay; } /* - extern Timer.onTimer(); -extern Timer.setDelay(int millisec); -extern Int Timer.getDelay(); -extern Timer.isRunning(); extern Int Timer.getSkipped(); */ }