From c80abfe3203f37e6df7ed00f693389283afb5e40 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Sat, 26 Jun 2021 19:10:42 -0700 Subject: [PATCH] Add more missing methods --- .../webamp-modern-2/src/skin/AnimatedLayer.ts | 48 +++++- packages/webamp-modern-2/src/skin/GuiObj.ts | 44 +++-- packages/webamp-modern-2/src/skin/MakiMap.ts | 18 ++ .../webamp-modern-2/src/skin/SystemObject.ts | 155 ++++++++++++++++++ 4 files changed, 250 insertions(+), 15 deletions(-) diff --git a/packages/webamp-modern-2/src/skin/AnimatedLayer.ts b/packages/webamp-modern-2/src/skin/AnimatedLayer.ts index 616e27dc..99501daa 100644 --- a/packages/webamp-modern-2/src/skin/AnimatedLayer.ts +++ b/packages/webamp-modern-2/src/skin/AnimatedLayer.ts @@ -1,6 +1,8 @@ import Layer from "./Layer"; export default class AnimatedLayer extends Layer { + _currentFrame: number = 0; + _frameCount: number = 0; setXmlAttr(_key: string, value: string): boolean { const key = _key.toLowerCase(); if (super.setXmlAttr(key, value)) { @@ -13,9 +15,51 @@ export default class AnimatedLayer extends Layer { return true; } getlength(): number { - return 10; + return this._frameCount; } - gotoframe(framenum: number) {} + gotoframe(framenum: number) { + this._currentFrame = framenum; + } + getcurframe(): number { + return this._currentFrame; + } + setstartframe(framenum: number) { + // TODO + } + setendframe(framenum: number) { + // TODO + } + setspeed(msperframe: number) { + // TODO + } + play() { + // TODO + } + pause() { + // TODO + } + stop() { + // TODO + } + isplaying(): boolean { + // TODO + return false; + } + + /* + extern AnimatedLayer.onPlay(); +extern AnimatedLayer.onPause(); +extern AnimatedLayer.onResume(); +extern AnimatedLayer.onStop(); +extern AnimatedLayer.onFrame(Int framenum); +extern AnimatedLayer.setAutoReplay(Boolean onoff); +extern Boolean AnimatedLayer.isPlaying(); +extern Boolean AnimatedLayer.isPaused(); +extern Boolean AnimatedLayer.isStopped(); +extern Int AnimatedLayer.getDirection(); +extern Boolean AnimatedLayer.getAutoReplay(); +extern AnimatedLayer.setRealtime(Boolean onoff); +*/ draw() { super.draw(); diff --git a/packages/webamp-modern-2/src/skin/GuiObj.ts b/packages/webamp-modern-2/src/skin/GuiObj.ts index e807d8f0..902dfc1f 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 * as Utils from "../utils"; +import { assert, num, toBool, px } from "../utils"; import { VM } from "./VM"; import XmlObj from "./XmlObj"; @@ -15,6 +15,7 @@ export default class GuiObj extends XmlObj { _dirty: boolean = false; _alpha: number = 255; _ghost: boolean = false; + _tooltip: string = ""; _div: HTMLDivElement = document.createElement("div"); setXmlAttr(_key: string, value: string): boolean { @@ -24,29 +25,32 @@ export default class GuiObj extends XmlObj { this._id = value.toLowerCase(); break; case "w": - this._width = Utils.num(value); + this._width = num(value); break; case "h": - this._height = Utils.num(value); + this._height = num(value); break; case "x": - this._x = Utils.num(value) ?? 0; + this._x = num(value) ?? 0; break; case "y": - this._y = Utils.num(value) ?? 0; + this._y = num(value) ?? 0; break; case "droptarget": this._droptarget = value; break; case "ghost": - this._ghost = Utils.toBool(value); + this._ghost = toBool(value); break; case "visible": - this._visible = Utils.toBool(value); + this._visible = toBool(value); + break; + case "tooltip": + this._tooltip = value; break; // (int) An integer [0,255] specifying the alpha blend mode of the object (0 is transparent, 255 is opaque). Default is 255. case "alpha": - this._alpha = Utils.num(value); + this._alpha = num(value); default: return false; } @@ -88,7 +92,17 @@ export default class GuiObj extends XmlObj { * @ret The top edge's position (in screen coordinates). */ gettop(): number { - return this._x; + return this._div.getBoundingClientRect().top; + } + + /** + * Get the X position, in the screen, of the + * left edge of the object. + * + * @ret The left edge's position (in screen coordinates). + */ + getleft(): number { + return this._div.getBoundingClientRect().left; } /** @@ -97,6 +111,7 @@ export default class GuiObj extends XmlObj { * @ret The height of the object. */ getheight() { + assert(this._height != null, "Expected GUIObj to have a height."); // FIXME return this._height || 100; } @@ -204,20 +219,23 @@ export default class GuiObj extends XmlObj { this._div.style.display = this._visible ? "inline-block" : "none"; this._div.style.position = "absolute"; this._renderAlpha(); + if (this._tooltip) { + this._div.setAttribute("title", this._tooltip); + } if (this._ghost) { this._div.style.pointerEvents = "none"; } if (this._x) { - this._div.style.left = Utils.px(this._x); + this._div.style.left = px(this._x); } if (this._y) { - this._div.style.top = Utils.px(this._y); + this._div.style.top = px(this._y); } if (this._width) { - this._div.style.width = Utils.px(this._width); + this._div.style.width = px(this._width); } if (this._height) { - this._div.style.height = Utils.px(this._height); + this._div.style.height = px(this.getheight()); } this._div.addEventListener("mouseup", (e) => { this.onLeftButtonUp(e.clientX, e.clientX); diff --git a/packages/webamp-modern-2/src/skin/MakiMap.ts b/packages/webamp-modern-2/src/skin/MakiMap.ts index bd3a9e86..7008d151 100644 --- a/packages/webamp-modern-2/src/skin/MakiMap.ts +++ b/packages/webamp-modern-2/src/skin/MakiMap.ts @@ -2,4 +2,22 @@ import BaseObject from "./BaseObject"; export default class MakiMap extends BaseObject { loadmap(bitmapId: string) {} + inregion(x: number, y: number): boolean { + // TODO + return true; + } + getvalue(x: number, y: number): number { + // TODO + return 12345; + } + + /* +extern Int Map.getValue(int x, int y); +extern Int Map.getARGBValue(int x, int y, int channel); // requires wa 5.51 // channel: 0=Blue, 1=Green, 2=Red, 3=Alpha. if your img has a alpha channal the returned rgb value might not be exact +extern Boolean Map.inRegion(int x, int y); +extern Map.loadMap(String bitmapid); +extern Int Map.getWidth(); +extern Int Map.getHeight(); +extern Region Map.getRegion(); +*/ } diff --git a/packages/webamp-modern-2/src/skin/SystemObject.ts b/packages/webamp-modern-2/src/skin/SystemObject.ts index b8d15524..4ec3d5ce 100644 --- a/packages/webamp-modern-2/src/skin/SystemObject.ts +++ b/packages/webamp-modern-2/src/skin/SystemObject.ts @@ -1,5 +1,6 @@ import { getClass } from "../maki/objects"; import { ParsedMaki } from "../maki/parser"; +import { V } from "../maki/v"; import { SkinContext } from "../types"; import BaseObject from "./BaseObject"; import Container from "./Container"; @@ -7,6 +8,14 @@ import Container from "./Container"; import Group from "./Group"; import { VM } from "./VM"; +const MOUSE_POS = { x: 0, y: 0 }; + +// TODO: Figure out how this could be unsubscribed eventually +document.addEventListener("mousemove", (e: MouseEvent) => { + MOUSE_POS.x = e.clientX; + MOUSE_POS.y = e.clientY; +}); + export default class SystemObject extends BaseObject { _parentGroup: Group; _parsedScript: ParsedMaki; @@ -43,6 +52,26 @@ export default class SystemObject extends BaseObject { return "TODO: Get the Real skin name"; } + /** + * This returns the X position of the mouse in the screen, + * using the screen coordinate system. + * + * @ret The mouse's current X pos. + */ + getmouseposx(): number { + return MOUSE_POS.x; + } + + /** + * This returns the Y position of the mouse in the screen, + * using the screen coordinate system. + * + * @ret The mouse's current Y pos. + */ + getmouseposy(): number { + return MOUSE_POS.y; + } + /** * Read a private config entry of Integer type. Returns * the specified default value if the section and item isn't @@ -175,6 +204,132 @@ export default class SystemObject extends BaseObject { geteq(): number { return 1; } + + /** + * Takes an angle in radians and returns the ratio between two sides of a right triangle. + * The ratio is sin(x) divided by cos(x). + * + * @ret The tangent value of the angle. + * @param value The angle for which you want to know the tangent value. + */ + tan(value: number): number { + return Math.tan(value); + } + + /** + * Takes an angle in radians and returns the ratio of two sides of a right triangle. + * The ratio is the length of the side opposite the angle divided by the length + * of the hypotenuse. The result range is from -1 to 1. + * + * Converting from degrees to radians can be done by multiplying degrees by PI/180. + * + * @ret The sine value of the angle. + * @param value The angle for which you want to know the sine value. + */ + sin(value: number): number { + return Math.sin(value); + } + + /** + * Takes an angle in radians and returns the ratio of the two sides of a right triangle. + * The ratio is the length of the side adjacent to the angle divided by the length of the + * hypotenuse. The result is range is from -1 to 1. + * + * @ret The cosine value of the angle. + * @param value The angle for which you want to know the cosine value. + */ + cos(value: number): number { + return Math.cos(value); + } + + /** + * Takes a sine value ranging from -1 to 1 and returns the angle in radians. + * The return value ranges from -PI/2 to +PI/2. + * + * @ret The angle in radians. + * @param value The sine value for which you want to know the angle. + */ + asin(value: number): number { + return Math.asin(value); + } + + /** + * Takes a cosine value ranging from -1 to 1 and returns the angle in radians. + * The return value ranges from -PI/2 to +PI/2. + * + * @ret The angle in radians. + * @param value The cosine value for which you want to know the angle. + */ + acos(value: number): number { + return Math.acos(value); + } + + /** + * Takes an angle in radians and returns the ration between two sides of a right triangle. + * The ratio is cos(x) divided by sin(x). + * + * @ret The arc tangent value of the angle. + */ + atan(value: number): number { + return Math.atan(value); + } + + /** + * @ret The arctangent of y/x. + */ + atan2(y: number, x: number): number { + return Math.atan2(y, x); + } + + /** + * Elevate a number to the N'th power. + * + * @ret The number + * @param value The number you want to elevate to the N power. + * @param pvalue The power to which you want to elevate the number. + */ + pow(value: number, pvalue: number): number { + return Math.pow(value, pvalue); + } + + /** + * Get the square of a number. + * + * @ret The number, squared. + * @param value The number for which you want the square value. + */ + sqr(value: number): number { + return value * value; + } + + log10(value: number) { + return Math.log10(value); + } + ln(value: number): number { + throw new Error("Unimplemented"); + } + + /** + * Get the square root of a number. + * + * @ret The square root of the number. + * @param value The number for which you want the square root value. + */ + sqrt(value: number): number { + return Math.sqrt(value); + } + + /** + * Get a randomely generated number. The random number will not + * be bigger than the max value indicated. Smallest value is 0. + * + * @ret The random number. + * @param max The maximum value of the random number to return. + */ + random(max: number) { + // TODO: Should this return an int? + return Math.random() * max; + } } function dumpScriptDebug(script: ParsedMaki) {