From 06fc257c30497beb714d08b84ed42290e28b2c2d Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Wed, 30 Jun 2021 22:50:32 -0700 Subject: [PATCH] Fix click events, and get basic GuiObject animations working --- packages/webamp-modern-2/assets/favicon.ico | Bin 0 -> 21238 bytes packages/webamp-modern-2/src/index.html | 5 +- packages/webamp-modern-2/src/index.ts | 11 ++- packages/webamp-modern-2/src/skin/Group.ts | 3 +- packages/webamp-modern-2/src/skin/GuiObj.ts | 81 ++++++++++++++++---- 5 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 packages/webamp-modern-2/assets/favicon.ico diff --git a/packages/webamp-modern-2/assets/favicon.ico b/packages/webamp-modern-2/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b3e5f7b192868827f72661dae681c81ff88ca578 GIT binary patch literal 21238 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 a6ekgkON$A1CZ+`3x; literal 0 HcmV?d00001 diff --git a/packages/webamp-modern-2/src/index.html b/packages/webamp-modern-2/src/index.html index c1a3e406..aca909ae 100644 --- a/packages/webamp-modern-2/src/index.html +++ b/packages/webamp-modern-2/src/index.html @@ -4,6 +4,7 @@ + Webamp Modern -
+
+

Downloading JavaScript...

+
Work in Progress
diff --git a/packages/webamp-modern-2/src/index.ts b/packages/webamp-modern-2/src/index.ts index 8850b2f9..5d611171 100644 --- a/packages/webamp-modern-2/src/index.ts +++ b/packages/webamp-modern-2/src/index.ts @@ -11,20 +11,26 @@ function hack() { } async function main() { + const status = document.getElementById("status"); + status.innerText = "Downloading skin..."; // const response = await fetch("assets/CornerAmp_Redux.wal"); // const response = await fetch("assets/Default_winamp3_build499.wal"); const response = await fetch("assets/MMD3.wal"); const data = await response.blob(); + status.innerText = "Loading .wal archive..."; const zip = await JSZip.loadAsync(data); + status.innerText = "Parsing XML and initializing images..."; const parser = new SkinParser(zip); await parser.parse(); let node = document.createElement("div"); + status.innerText = "Enabling Colors..."; UI_ROOT.enableDefaultGammaSet(); + status.innerText = "Rendering skin for the first time..."; for (const container of parser._containers) { container.draw(); node.appendChild(container.getDiv()); @@ -35,7 +41,6 @@ async function main() { select.style.bottom = "0px"; select.style.left = "0px"; select.addEventListener("change", (e) => { - console.log(e.target.value); UI_ROOT.enableGammaSet(e.target.value); }); for (const set of UI_ROOT._gammaSets.keys()) { @@ -51,12 +56,12 @@ async function main() { document.body.appendChild(div); document.body.appendChild(node); - console.log("RENDER"); + status.innerText = "Initializing Maki..."; for (const container of parser._containers) { container.init({ containers: parser._containers }); } - console.log("INIT"); + status.innerText = ""; } main(); diff --git a/packages/webamp-modern-2/src/skin/Group.ts b/packages/webamp-modern-2/src/skin/Group.ts index ccfa91a9..61671e36 100644 --- a/packages/webamp-modern-2/src/skin/Group.ts +++ b/packages/webamp-modern-2/src/skin/Group.ts @@ -125,7 +125,8 @@ export default class Group extends GuiObj { draw() { super.draw(); this._div.setAttribute("data-obj-name", "Group"); - // this._div.style.pointerEvents = "none"; + // It seems Groups are not responsive to click events. + this._div.style.pointerEvents = "none"; this._div.style.overflow = "hidden"; this._div.style.height = Utils.px(this._maximumHeight); this._div.style.width = Utils.px(this._maximumWidth); diff --git a/packages/webamp-modern-2/src/skin/GuiObj.ts b/packages/webamp-modern-2/src/skin/GuiObj.ts index 1f287797..6055a30f 100644 --- a/packages/webamp-modern-2/src/skin/GuiObj.ts +++ b/packages/webamp-modern-2/src/skin/GuiObj.ts @@ -1,5 +1,5 @@ import { SkinContext } from "../types"; -import { assert, num, toBool, px } from "../utils"; +import { assert, num, toBool, px, assume } from "../utils"; import Bitmap from "./Bitmap"; import { VM } from "./VM"; import XmlObj from "./XmlObj"; @@ -16,6 +16,12 @@ export default class GuiObj extends XmlObj { _alpha: number = 255; _ghost: boolean = false; _tooltip: string = ""; + _targetX: number | null = null; + _targetY: number | null = null; + _targetWidth: number | null = null; + _targetHeight: number | null = null; + _targetAlpha: number | null = null; + _targetSpeed: number | null = null; _div: HTMLDivElement = document.createElement("div"); setXmlAttr(_key: string, value: string): boolean { @@ -240,7 +246,7 @@ export default class GuiObj extends XmlObj { * @param x The target X position of the object. */ settargetx(x: number) { - // TOOD + this._targetX = x; } /** @@ -250,7 +256,7 @@ export default class GuiObj extends XmlObj { * @param y The target Y position of the object. */ settargety(y: number) { - // TODO + this._targetY = y; } /** @@ -259,7 +265,7 @@ export default class GuiObj extends XmlObj { * @param w The target width of the object. */ settargetw(w: number) { - // TODO + this._targetWidth = w; } /** @@ -267,8 +273,8 @@ export default class GuiObj extends XmlObj { * * @param h The target height of the object. */ - settargeth(r: number) { - // TODO + settargeth(h: number) { + this._targetHeight = h; } /** @@ -279,7 +285,7 @@ export default class GuiObj extends XmlObj { * @param alpha The target alpha value. */ settargeta(alpha: number) { - // TODO + this._targetAlpha = alpha; } /** @@ -289,14 +295,56 @@ export default class GuiObj extends XmlObj { * @param insecond The number of seconds in which to reach the target. */ settargetspeed(insecond: number) { - // TODO + this._targetSpeed = insecond; } /** * Begin transition to previously set target. */ gototarget() { - // TODO + const duration = this._targetSpeed * 1000; + const startTime = performance.now(); + + const changes = { + _x: { + start: this._x, + delta: this._targetX == null ? 0 : this._targetX - this._x, + }, + _y: { + start: this._y, + delta: this._targetY == null ? 0 : this._targetY - this._y, + }, + _width: { + start: this._width, + delta: this._targetWidth == null ? 0 : this._targetWidth - this._width, + }, + _height: { + start: this._height, + delta: + this._targetHeight == null ? 0 : this._targetHeight - this._height, + }, + _alpha: { + start: this._alpha, + delta: this._targetAlpha == null ? 0 : this._targetAlpha - this._alpha, + }, + }; + + const update = (time: number) => { + const timeDiff = time - startTime; + const progress = timeDiff / duration; + for (const [key, { start, delta }] of Object.entries(changes)) { + this[key] = start + delta * progress; + } + this._renderDimensions(); + if (timeDiff < duration) { + window.requestAnimationFrame(update); + } else { + VM.dispatch(this, "ontargetreached"); + } + }; + + window.requestAnimationFrame(update); + // this._renderDimensions(); } /** @@ -304,11 +352,11 @@ export default class GuiObj extends XmlObj { * it's previously set target. */ ontargetreached() { - // TODO + assume(false, "Unimplemented"); } canceltarget() { - // TODO + assume(false, "Unimplemented"); } /** @@ -319,11 +367,11 @@ export default class GuiObj extends XmlObj { // modifies the x/y targets so that they compensate for gained width/height. useful to make drawers that open up without jittering reversetarget(reverse: number) { - // TODO + assume(false, "Unimplemented"); } onStartup() { - // TODO + assume(false, "Unimplemented"); } /** @@ -355,6 +403,11 @@ export default class GuiObj extends XmlObj { _renderVisibility() { this._div.style.display = this._visible ? "inline-block" : "none"; } + _renderTransate() { + this._div.style.transform = `translate(${px(this._x ?? 0)}, ${px( + this._y ?? 0 + )})`; + } _renderX() { this._div.style.left = px(this._x ?? 0); } @@ -402,6 +455,8 @@ export default class GuiObj extends XmlObj { } if (this._ghost) { this._div.style.pointerEvents = "none"; + } else { + this._div.style.pointerEvents = "auto"; } this._renderDimensions();