import { AudioSource, Component, Event, Game, IVec2Like, IVec3Like, Label, Node, NodeSpace, Sprite, Vec2, Vec3, game, randomRangeInt, toDegree, toRadian, } from 'cc'; import ObjectPool from '../Pool/ObjectPool'; declare module 'cc' { interface Game { timeScale: number; } interface Component { setNodeActive(isActive: boolean): void; setNodeActive(event: Event, customEventData?: string): void; setNodeActive(a: boolean | Event, b?: string): void; } interface Node { setActive(isActive: boolean): void; setPositionX(x: number): void; setPositionY(y: number): void; setPositionZ(z: number): void; setWorldPositionX(x: number): void; setWorldPositionY(y: number): void; setWorldPositionZ(z: number): void; translateX(x: number, ns?: NodeSpace): void; translateY(y: number, ns?: NodeSpace): void; translateZ(z: number, ns?: NodeSpace): void; setScaleX(x: number): void; setScaleY(y: number): void; setScaleZ(z: number): void; releaseToPool(): boolean; } interface Vec2 { toVec3(): Vec3; getPositionOnCircle(angle: number, radius?: number): Vec2; getAngleOnCircle(center: IVec2Like): number; } interface Vec3 { toVec2(): Vec2; getPositionOnCircle(angle: number, radius?: number): Vec3; getAngleOnCircle(center: IVec3Like): number; } interface Label { setString(value: string | number): void; } interface Sprite { setFillRange(value: number): void; } interface AudioSource { getPlaybackRate(): number; /** * Set playbackRate of this audio source * * Note: playbackRate control may be ineffective on some platforms. */ setPlaybackRate(value: number): void; } } declare global { interface String { jsonParse(): any; isNullOrWhiteSpace(): boolean; } interface Array { getRandomIndex(): number; getRandomIndex(weights: number[]): number; getRandom(): T; getRandom(weights: number[]): T; } } //#region GAME Game.prototype.timeScale = 1; // @ts-ignore game._calculateDT = function (useFixedDeltaTime: number) { this._useFixedDeltaTime = useFixedDeltaTime; if (useFixedDeltaTime) { this._startTime = performance.now(); return this.frameTime / 1000; } const now = performance.now(); this._deltaTime = now > this._startTime ? (now - this._startTime) / 1000 : 0; if (this._deltaTime > Game.DEBUG_DT_THRESHOLD) { this._deltaTime = this.frameTime / 1000; } this._startTime = now; return this._deltaTime * this.timeScale; }; //#endregion //#region COMPONENT Component.prototype.setNodeActive = function (a: boolean | Event, b?: string) { if (a instanceof Event) { this.node.active = b?.toLowerCase() === 'true'; } else { this.node.active = a; } }; //#endregion //#region NODE Node.prototype.setActive = function (isActive: boolean) { this.active = isActive; }; Node.prototype.setPositionX = function (x: number): void { this.position = new Vec3(x, this.position.y, this.position.z); }; Node.prototype.setPositionY = function (y: number): void { this.position = new Vec3(this.position.x, y, this.position.z); }; Node.prototype.setPositionZ = function (z: number): void { this.position = new Vec3(this.position.x, this.position.y, z); }; Node.prototype.setWorldPositionX = function (x: number): void { this.worldPosition = new Vec3(x, this.worldPosition.y, this.worldPosition.z); }; Node.prototype.setWorldPositionY = function (y: number): void { this.worldPosition = new Vec3(this.worldPosition.x, y, this.worldPosition.z); }; Node.prototype.setWorldPositionZ = function (z: number): void { this.worldPosition = new Vec3(this.worldPosition.x, this.worldPosition.y, z); }; Node.prototype.translateX = function (x: number, ns?: NodeSpace): void { this.translate(new Vec3(x, 0), ns); }; Node.prototype.translateY = function (y: number, ns?: NodeSpace): void { this.translate(new Vec3(0, y), ns); }; Node.prototype.translateZ = function (z: number, ns?: NodeSpace): void { this.translate(new Vec3(0, 0, z), ns); }; Node.prototype.setScaleX = function (x: number): void { this.scale = new Vec3(x, this.scale.y, this.scale.z); }; Node.prototype.setScaleY = function (y: number): void { this.scale = new Vec3(this.scale.x, y, this.scale.z); }; Node.prototype.setScaleZ = function (z: number): void { this.scale = new Vec3(this.scale.x, this.scale.y, z); }; Node.prototype.releaseToPool = function () { return ObjectPool.release(this); }; //#endregion //#region VEC2 Vec2.prototype.toVec3 = function () { return new Vec3(this.x, this.y); }; Vec2.prototype.getPositionOnCircle = function (angle: number, radius?: number) { const rad = toRadian(angle); const r = radius || 1; const x = this.x + r * -Math.cos(rad); const y = this.y + r * Math.sin(rad); return new Vec2(x, y); }; Vec2.prototype.getAngleOnCircle = function (center: IVec2Like): number { const diffX = this.x - center.x; const diffY = this.y - center.y; const angle = Math.atan2(diffY, diffX); return toDegree(angle) - 90; }; //#endregion //#region VEC3 Vec3.prototype.toVec2 = function () { return new Vec2(this.x, this.y); }; Vec3.prototype.getPositionOnCircle = function (angle: number, radius?: number) { const rad = toRadian(angle); const r = radius || 1; const x = this.x + r * -Math.cos(rad); const y = this.y + r * Math.sin(rad); return new Vec3(x, y, this.z); }; Vec3.prototype.getAngleOnCircle = function (center: IVec3Like): number { const diffX = this.x - center.x; const diffY = this.y - center.y; const angle = Math.atan2(diffY, diffX); return toDegree(angle) - 90; }; //#endregion //#region LABEL Label.prototype.setString = function (value: string | number) { if (typeof value == 'number') { this.string = value.toString(); return; } this.string = value; }; //#endregion //#region SPRITE Sprite.prototype.setFillRange = function (value: number) { this.fillRange = value; }; //#endregion //#region STRING String.prototype.jsonParse = function () { try { return JSON.parse(this); } catch (error) { console.log(error); return false; } }; String.prototype.isNullOrWhiteSpace = function () { return !this || !this.trim(); }; //#endregion //#region ARRAY Array.prototype.getRandomIndex = function (weights?: number[]) { if (weights) { let weightsClone = [...weights]; const totalWeight = weightsClone.reduce((a, b) => a + b, 0); let random = Math.random() * totalWeight; let index; this.findIndex((_, i) => (random -= weightsClone[i]) <= 0); return index; } else { return randomRangeInt(0, this.length); } }; Array.prototype.getRandom = function (weights?: number[]) { if (weights) { let weightsClone = [...weights]; const totalWeight = weightsClone.reduce((a, b) => a + b, 0); let random = Math.random() * totalWeight; const item = this.find((_, i) => (random -= weightsClone[i]) <= 0); return item; } else { return this[randomRangeInt(0, this.length)]; } }; //#endregion //#region AUDIO SOURCE //support audio playbackRate //@ts-ignore AudioSource.prototype._playbackRate = 1; //@ts-ignores AudioSource.prototype._syncStates = function () { if (this._player) { this._player.loop = this._loop; this._player.volume = this._volume; // this._player._sourceNode.playbackRate = this._playbackRate; this._operationsBeforeLoading.forEach((opInfo): void => { if (opInfo.op === 'SEEK') { this._cachedCurrentTime = (opInfo.params && opInfo.params[0]) as number; if (this._player) { // eslint-disable-next-line @typescript-eslint/no-empty-function this._player.seek(this._cachedCurrentTime).catch((e): void => {}); } } else { this[opInfo.op]?.(); } }); try { this._player._player._sourceNode.playbackRate.value = this._playbackRate; } catch (e) { console.log(e); } this._operationsBeforeLoading.length = 0; } }; AudioSource.prototype.getPlaybackRate = function () { return this._playbackRate; }; AudioSource.prototype.setPlaybackRate = function (value: number) { if (this._player) { try { this._player._player._sourceNode.playbackRate.value = value; } catch (e) { console.log(e); } this._playbackRate = this._player.playbackRate; } else { this._playbackRate = value; } }; //#endregion