diff --git a/packages/webamp-modern-2/src/UIRoot.ts b/packages/webamp-modern-2/src/UIRoot.ts index a7c0472a..ae31ae08 100644 --- a/packages/webamp-modern-2/src/UIRoot.ts +++ b/packages/webamp-modern-2/src/UIRoot.ts @@ -7,6 +7,7 @@ import Color from "./skin/Color"; import AUDIO_PLAYER from "./skin/AudioPlayer"; import GammaGroup from "./skin/GammaGroup"; import Container from "./skin/Container"; +import Vm from "./skin/VM"; class UIRoot { // Just a temporary place to stash things @@ -19,6 +20,12 @@ class UIRoot { _activeGammaSet: GammaGroup[] | null = null; _containers: Container[] = []; + vm: Vm; + + constructor() { + this.vm = new Vm(); + } + addBitmap(bitmap: Bitmap) { this._bitmaps.push(bitmap); } diff --git a/packages/webamp-modern-2/src/skin/AnimatedLayer.ts b/packages/webamp-modern-2/src/skin/AnimatedLayer.ts index 2f9ad002..692fc14d 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; @@ -33,7 +32,9 @@ export default class AnimatedLayer extends Layer { gotoframe(framenum: number) { this._currentFrame = ensureVmInt(framenum); this._renderFrame(); - VM.dispatch(this, "onframe", [{ type: "INT", value: this._currentFrame }]); + UI_ROOT.vm.dispatch(this, "onframe", [ + { type: "INT", value: this._currentFrame }, + ]); } getcurframe(): number { return this._currentFrame; @@ -59,7 +60,7 @@ export default class AnimatedLayer extends Layer { let frame = this._startFrame; this.gotoframe(frame); - VM.dispatch(this, "onplay"); + UI_ROOT.vm.dispatch(this, "onplay"); if (frame === end) { return; } @@ -73,7 +74,7 @@ export default class AnimatedLayer extends Layer { }, this._speed); } pause() { - VM.dispatch(this, "onpause"); + UI_ROOT.vm.dispatch(this, "onpause"); // TODO } stop() { @@ -81,7 +82,7 @@ export default class AnimatedLayer extends Layer { clearInterval(this._animationInterval); this._animationInterval = null; } - VM.dispatch(this, "onstop"); + UI_ROOT.vm.dispatch(this, "onstop"); } isplaying(): boolean { return this._animationInterval != null; diff --git a/packages/webamp-modern-2/src/skin/Button.ts b/packages/webamp-modern-2/src/skin/Button.ts index 9fb10b6e..2f6009b2 100644 --- a/packages/webamp-modern-2/src/skin/Button.ts +++ b/packages/webamp-modern-2/src/skin/Button.ts @@ -1,6 +1,5 @@ import GuiObj from "./GuiObj"; import UI_ROOT from "../UIRoot"; -import { VM } from "./VM"; // http://wiki.winamp.com/wiki/XML_GUI_Objects#.3Cbutton.2F.3E_.26_.3Ctogglebutton.2F.3E export default class Button extends GuiObj { @@ -85,7 +84,9 @@ export default class Button extends GuiObj { if (onoff !== this._active) { this._active = onoff; - VM.dispatch(this, "onactivate", [{ type: "BOOL", value: onoff ? 1 : 0 }]); + UI_ROOT.vm.dispatch(this, "onactivate", [ + { type: "BOOL", value: onoff ? 1 : 0 }, + ]); } } @@ -94,7 +95,7 @@ export default class Button extends GuiObj { } onLeftClick() { - VM.dispatch(this, "onleftclick", []); + UI_ROOT.vm.dispatch(this, "onleftclick", []); } _renderBackground() { diff --git a/packages/webamp-modern-2/src/skin/Container.ts b/packages/webamp-modern-2/src/skin/Container.ts index 296059bc..78e90244 100644 --- a/packages/webamp-modern-2/src/skin/Container.ts +++ b/packages/webamp-modern-2/src/skin/Container.ts @@ -1,7 +1,6 @@ import UI_ROOT from "../UIRoot"; import { assert, px, removeAllChildNodes, toBool } from "../utils"; import Layout from "./Layout"; -import { VM } from "./VM"; import XmlObj from "./XmlObj"; // > A container is a top level object and it basically represents a window. @@ -100,14 +99,16 @@ export default class Container extends XmlObj { setLayout(id: string) { const layout = this.getlayout(id); assert(layout != null, `Could not find layout with id "${id}".`); - VM.dispatch(this, "onswitchtolayout", [ + UI_ROOT.vm.dispatch(this, "onswitchtolayout", [ { type: "OBJECT", value: this._activeLayout }, { type: "OBJECT", value: layout }, ]); this._activeLayout = layout; this._clearCurrentLayout(); this._renderLayout(); - VM.dispatch(this, "onswitchtolayout", [{ type: "OBJECT", value: layout }]); + UI_ROOT.vm.dispatch(this, "onswitchtolayout", [ + { type: "OBJECT", value: layout }, + ]); } dispatchAction( diff --git a/packages/webamp-modern-2/src/skin/GuiObj.ts b/packages/webamp-modern-2/src/skin/GuiObj.ts index 60ea06b2..66e608e8 100644 --- a/packages/webamp-modern-2/src/skin/GuiObj.ts +++ b/packages/webamp-modern-2/src/skin/GuiObj.ts @@ -1,7 +1,7 @@ +import UI_ROOT from "../UIRoot"; import { assert, num, toBool, px, assume } from "../utils"; import Bitmap from "./Bitmap"; import Group from "./Group"; -import { VM } from "./VM"; import XmlObj from "./XmlObj"; // http://wiki.winamp.com/wiki/XML_GUI_Objects#GuiObject_.28Global_params.29 @@ -194,7 +194,7 @@ export default class GuiObj extends XmlObj { * @param y The Y position in the screen where the cursor was when the event was triggered. */ onLeftButtonUp(x: number, y: number) { - VM.dispatch(this, "onleftbuttonup", [ + UI_ROOT.vm.dispatch(this, "onleftbuttonup", [ { type: "INT", value: x }, { type: "INT", value: y }, ]); @@ -216,7 +216,7 @@ export default class GuiObj extends XmlObj { y >= this.gettop(), "Expected click to be below the component's top" ); - VM.dispatch(this, "onleftbuttondown", [ + UI_ROOT.vm.dispatch(this, "onleftbuttondown", [ { type: "INT", value: x }, { type: "INT", value: y }, ]); @@ -230,7 +230,7 @@ export default class GuiObj extends XmlObj { * @param y The Y position in the screen where the cursor was when the event was triggered. */ onRightButtonUp(x: number, y: number) { - VM.dispatch(this, "onrightbuttonup", [ + UI_ROOT.vm.dispatch(this, "onrightbuttonup", [ { type: "INT", value: x }, { type: "INT", value: y }, ]); @@ -244,7 +244,7 @@ export default class GuiObj extends XmlObj { * @param y The Y position in the screen where the cursor was when the event was triggered. */ onRightButtonDown(x: number, y: number) { - VM.dispatch(this, "onrightbuttondown", [ + UI_ROOT.vm.dispatch(this, "onrightbuttondown", [ { type: "INT", value: x }, { type: "INT", value: y }, ]); @@ -255,7 +255,7 @@ export default class GuiObj extends XmlObj { * enters the objects area. */ onEnterArea() { - VM.dispatch(this, "onenterarea"); + UI_ROOT.vm.dispatch(this, "onenterarea"); } /** @@ -263,7 +263,7 @@ export default class GuiObj extends XmlObj { * leaves the objects area. */ onLeaveArea() { - VM.dispatch(this, "onleavearea"); + UI_ROOT.vm.dispatch(this, "onleavearea"); } /** @@ -366,7 +366,7 @@ export default class GuiObj extends XmlObj { window.requestAnimationFrame(update); } else { // TODO: Clear targets? - VM.dispatch(this, "ontargetreached"); + UI_ROOT.vm.dispatch(this, "ontargetreached"); } }; @@ -405,7 +405,7 @@ export default class GuiObj extends XmlObj { this._alpha = this._targetAlpha ?? this._alpha; this._renderDimensions(); this._renderAlpha(); - VM.dispatch(this, "ontargetreached"); + UI_ROOT.vm.dispatch(this, "ontargetreached"); }); } /** diff --git a/packages/webamp-modern-2/src/skin/Slider.ts b/packages/webamp-modern-2/src/skin/Slider.ts index 0562af59..e9af93de 100644 --- a/packages/webamp-modern-2/src/skin/Slider.ts +++ b/packages/webamp-modern-2/src/skin/Slider.ts @@ -1,7 +1,6 @@ import UI_ROOT from "../UIRoot"; import { assume, clamp, num, px } from "../utils"; import GuiObj from "./GuiObj"; -import { VM } from "./VM"; // http://wiki.winamp.com/wiki/XML_GUI_Objects#.3Cslider.2F.3E_.26_.3CWasabi:HSlider.2F.3E_.26_.3CWasabi:VSlider.2F.3E export default class Slider extends GuiObj { @@ -45,10 +44,10 @@ export default class Slider extends GuiObj { }; const handleMouseUp = () => { - VM.dispatch(this, "onsetfinalposition", [ + UI_ROOT.vm.dispatch(this, "onsetfinalposition", [ { type: "INT", value: this.getposition() }, ]); - VM.dispatch(this, "onpostedposition", [ + UI_ROOT.vm.dispatch(this, "onpostedposition", [ { type: "INT", value: this.getposition() }, ]); document.removeEventListener("mousemove", handleMove); @@ -112,7 +111,9 @@ export default class Slider extends GuiObj { } onsetposition(newPos: number) { - VM.dispatch(this, "onsetposition", [{ type: "INT", value: newPos }]); + UI_ROOT.vm.dispatch(this, "onsetposition", [ + { type: "INT", value: newPos }, + ]); } _renderThumb() { diff --git a/packages/webamp-modern-2/src/skin/SystemObject.ts b/packages/webamp-modern-2/src/skin/SystemObject.ts index 09cb53b5..cbe12eec 100644 --- a/packages/webamp-modern-2/src/skin/SystemObject.ts +++ b/packages/webamp-modern-2/src/skin/SystemObject.ts @@ -6,7 +6,6 @@ import Container from "./Container"; import { clamp } from "../utils"; import Group from "./Group"; import PRIVATE_CONFIG from "./PrivateConfig"; -import { VM } from "./VM"; import UI_ROOT from "../UIRoot"; const MOUSE_POS = { x: 0, y: 0 }; @@ -34,8 +33,8 @@ export default class SystemObject extends BaseObject { } initialVariable.value = this; - VM.addScript(this._parsedScript); - VM.dispatch(this, "onscriptloaded"); + UI_ROOT.vm.addScript(this._parsedScript); + UI_ROOT.vm.dispatch(this, "onscriptloaded"); } setParentGroup(group: Group) { diff --git a/packages/webamp-modern-2/src/skin/Timer.ts b/packages/webamp-modern-2/src/skin/Timer.ts index 8fb8cbd3..52ac36b5 100644 --- a/packages/webamp-modern-2/src/skin/Timer.ts +++ b/packages/webamp-modern-2/src/skin/Timer.ts @@ -1,6 +1,6 @@ +import UI_ROOT from "../UIRoot"; import { assume } from "../utils"; import BaseObject from "./BaseObject"; -import { VM } from "./VM"; export default class Timer extends BaseObject { _delay: number; @@ -21,7 +21,7 @@ export default class Timer extends BaseObject { start() { assume(this._delay != null, "Tried to start a timer without a delay"); this._timeout = setInterval(() => { - VM.dispatch(this, "ontimer"); + UI_ROOT.vm.dispatch(this, "ontimer"); }, this._delay); } diff --git a/packages/webamp-modern-2/src/skin/VM.ts b/packages/webamp-modern-2/src/skin/VM.ts index dc25b041..bbe62fa9 100644 --- a/packages/webamp-modern-2/src/skin/VM.ts +++ b/packages/webamp-modern-2/src/skin/VM.ts @@ -5,7 +5,7 @@ import BaseObject from "./BaseObject"; import { classResolver } from "./resolver"; -class Vm { +export default class Vm { _scripts: ParsedMaki[] = []; // This could easily become performance sensitive. We could make this more // performant by normalizing some of these things when scripts are added. @@ -34,5 +34,3 @@ class Vm { interpret(commandOffset, script, args, classResolver); } } - -export const VM = new Vm();