Move to Renderer V2

This commit is contained in:
duckietm
2024-04-03 09:27:56 +02:00
parent 110c3ad393
commit b3134ce50b
4080 changed files with 115593 additions and 66375 deletions
+3
View File
@@ -0,0 +1,3 @@
{
"extends": [ "@nitrots/eslint-config" ]
}
+51
View File
@@ -0,0 +1,51 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events*.json
speed-measure-plugin*.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
.git
# System Files
.DS_Store
Thumbs.db
*.zip
*.as
*.bin
+1
View File
@@ -0,0 +1 @@
export * from './src';
+22
View File
@@ -0,0 +1,22 @@
{
"name": "@nitrots/utils",
"description": "Nitro utils module",
"version": "1.0.0",
"type": "module",
"license": "GPL-3.0",
"scripts": {
"compile": "tsc --project ./tsconfig.json --noEmit false",
"eslint": "eslint ./src --fix"
},
"main": "./index",
"dependencies": {
"@nitrots/api": "1.0.0",
"@nitrots/eslint-config": "1.0.0",
"pako": "^2.1.0",
"pixi.js": "^8.0.4"
},
"devDependencies": {
"@types/pako": "^2.0.3",
"typescript": "~5.4.2"
}
}
+159
View File
@@ -0,0 +1,159 @@
import { IAdvancedMap } from '@nitrots/api';
export class AdvancedMap<T, U> implements IAdvancedMap<T, U>
{
private _length: number;
private _dictionary: Map<T, U>;
private _array: U[];
private _keys: T[];
constructor(map: Map<T, U> = null)
{
this._length = 0;
this._dictionary = new Map();
this._array = [];
this._keys = [];
if(map) for(const [key, value] of map.entries()) this.add(key, value);
}
public get length(): number
{
return this._length;
}
public get disposed(): boolean
{
return (!this._dictionary);
}
public dispose(): void
{
if(!this._dictionary)
{
for(const key of this._dictionary.keys()) this._dictionary.delete(key);
this._dictionary = null;
}
this._length = 0;
this._array = null;
this._keys = null;
}
public reset(): void
{
for(const key of this._dictionary.keys()) this._dictionary.delete(key);
this._length = 0;
this._array = [];
this._keys = [];
}
public unshift(key: T, value: U): boolean
{
if(this._dictionary.get(key) !== null) return false;
this._dictionary.set(key, value);
this._array.unshift(value);
this._keys.unshift(key);
this._length++;
return true;
}
public add(key: T, value: U): boolean
{
if(this._dictionary.get(key) !== undefined) return false;
this._dictionary.set(key, value);
this._array[this._length] = value;
this._keys[this._length] = key;
this._length++;
return true;
}
public remove(key: T): U
{
const value = this._dictionary.get(key);
if(!value) return null;
const index = this._array.indexOf(value);
if(index >= 0)
{
this._array.splice(index, 1);
this._keys.splice(index, 1);
this._length--;
}
this._dictionary.delete(key);
return value;
}
public getWithIndex(index: number): U
{
if((index < 0) || (index >= this._length)) return null;
return this._array[index];
}
public getKey(index: number): T
{
if((index < 0) || (index >= this._length)) return null;
return this._keys[index];
}
public getKeys(): T[]
{
return this._keys.slice();
}
public hasKey(key: T): boolean
{
return (this._keys.indexOf(key) > -1);
}
public getValue(key: T): U
{
return this._dictionary.get(key);
}
public getValues(): U[]
{
return this._array.slice();
}
public hasValue(value: U): boolean
{
return (this._array.indexOf(value) > -1);
}
public indexOf(value: U): number
{
return this._array.indexOf(value);
}
public concatenate(newValues: IAdvancedMap<T, U>): void
{
for(const k of (newValues as AdvancedMap<T, U>)._keys) this.add(k, newValues.getValue(k));
}
public clone(): IAdvancedMap<T, U>
{
const map = new AdvancedMap<T, U>();
map.concatenate(this);
return map;
}
}
+11
View File
@@ -0,0 +1,11 @@
export const ArrayBufferToBase64 = (buffer: ArrayBuffer) =>
{
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for(let i = 0; i < len; i++) (binary += String.fromCharCode(bytes[i]));
return window.btoa(binary);
};
+82
View File
@@ -0,0 +1,82 @@
import { IBinaryReader } from '@nitrots/api';
export class BinaryReader implements IBinaryReader
{
private _position: number;
private _dataView: DataView;
constructor(buffer: ArrayBuffer)
{
this._position = 0;
this._dataView = new DataView(buffer);
}
public readBytes(length: number): IBinaryReader
{
const buffer = new BinaryReader(this._dataView.buffer.slice(this._position, this._position + length));
this._position += length;
return buffer;
}
public readByte(): number
{
const byte = this._dataView.getInt8(this._position);
this._position++;
return byte;
}
public readShort(): number
{
const short = this._dataView.getInt16(this._position);
this._position += 2;
return short;
}
public readInt(): number
{
const int = this._dataView.getInt32(this._position);
this._position += 4;
return int;
}
public readFloat(): number
{
const float = this._dataView.getFloat32(this._position);
this._position += 4;
return float;
}
public readDouble(): number
{
const double = this._dataView.getFloat64(this._position);
this._position += 8;
return double;
}
public remaining(): number
{
return this._dataView.byteLength - this._position;
}
public toString(encoding?: string): string
{
return new TextDecoder().decode(this._dataView.buffer);
}
public toArrayBuffer(): ArrayBuffer
{
return this._dataView.buffer;
}
}
+109
View File
@@ -0,0 +1,109 @@
import { IBinaryWriter } from '@nitrots/api';
export class BinaryWriter implements IBinaryWriter
{
private _buffer: Uint8Array;
private _position: number;
constructor()
{
this._buffer = new Uint8Array();
this._position = 0;
}
public writeByte(byte: number): IBinaryWriter
{
const array = new Uint8Array(1);
array[0] = byte;
this.appendArray(array);
return this;
}
public writeBytes(bytes: ArrayBuffer | number[]): IBinaryWriter
{
const array = new Uint8Array(bytes);
this.appendArray(array);
return this;
}
public writeShort(short: number): IBinaryWriter
{
const array = new Uint8Array(2);
array[0] = short >> 8;
array[1] = short & 0xFF;
this.appendArray(array);
return this;
}
public writeInt(integer: number): IBinaryWriter
{
const array = new Uint8Array(4);
array[0] = integer >> 24;
array[1] = integer >> 16;
array[2] = integer >> 8;
array[3] = integer & 0xFF;
this.appendArray(array);
return this;
}
public writeString(string: string, includeLength: boolean = true): IBinaryWriter
{
const array = new TextEncoder().encode(string);
if(includeLength)
{
this.writeShort(array.length);
this.appendArray(array);
}
else
{
this.appendArray(array);
}
return this;
}
private appendArray(array: Uint8Array): void
{
if(!array) return;
const mergedArray = new Uint8Array(((this.position + array.length) > this._buffer.length) ? (this.position + array.length) : this._buffer.length);
mergedArray.set(this._buffer);
mergedArray.set(array, this.position);
this._buffer = mergedArray;
this.position += array.length;
}
public getBuffer(): ArrayBuffer
{
return this._buffer.buffer;
}
public get position(): number
{
return this._position;
}
public set position(pos: number)
{
this._position = pos;
}
public toString(encoding?: string): string
{
return new TextDecoder(encoding).decode(this._buffer);
}
}
+354
View File
@@ -0,0 +1,354 @@
import { IVector3D } from '@nitrots/api';
import { Vector3d } from './Vector3d';
export class ColorConverter
{
private static HEX_DIGITS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
public static hex2rgb(hex: number, out: Array<number> | Float32Array = []): Array<number> | Float32Array
{
out[0] = ((hex >> 16) & 0xFF) / 255;
out[1] = ((hex >> 8) & 0xFF) / 255;
out[2] = (hex & 0xFF) / 255;
return out;
}
public static hex2rgba(hex: number, out: Array<number> | Float32Array = []): Array<number> | Float32Array
{
out[0] = ((hex >> 16) & 0xFF) / 255;
out[1] = ((hex >> 8) & 0xFF) / 255;
out[2] = (hex & 0xFF) / 255;
out[3] = (hex & 0xFF);
return out;
}
public static rgb2hex(rgb: number[] | Float32Array): number
{
return (((rgb[0] * 255) << 16) + ((rgb[1] * 255) << 8) + (rgb[2] * 255 | 0));
}
public static rgba2hex(rgb: number[] | Float32Array): number
{
return (((rgb[0] * 255) << 16) + ((rgb[1] * 255) << 8) + (rgb[2] * 255 | 0) + (rgb[3] | 0));
}
public static rgbStringToHex(rgb: string): string
{
const extracted = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return '#' + ColorConverter.getHex(extracted[1]) + ColorConverter.getHex(extracted[2]) + ColorConverter.getHex(extracted[3]);
}
public static getHex(x: any)
{
return isNaN(x) ? '00' : ColorConverter.HEX_DIGITS[(x - x % 16) / 16] + ColorConverter.HEX_DIGITS[x % 16];
}
public static int2rgb(color: number): string
{
color >>>= 0;
const b = color & 0xFF;
const g = (color & 0xFF00) >>> 8;
const r = (color & 0xFF0000) >>> 16;
const a = ((color & 0xFF000000) >>> 24) / 255;
return 'rgba(' + [r, g, b, 1].join(',') + ')';
}
public static rgbToHSL(k: number): number
{
const _local_2: number = (((k >> 16) & 0xFF) / 0xFF);
const _local_3: number = (((k >> 8) & 0xFF) / 0xFF);
const _local_4: number = ((k & 0xFF) / 0xFF);
const _local_5: number = Math.max(_local_2, _local_3, _local_4);
const _local_6: number = Math.min(_local_2, _local_3, _local_4);
const _local_7: number = (_local_5 - _local_6);
let _local_8 = 0;
let _local_9 = 0;
let _local_10 = 0;
if(_local_7 == 0)
{
_local_8 = 0;
}
else
{
if(_local_5 == _local_2)
{
if(_local_3 > _local_4)
{
_local_8 = ((60 * (_local_3 - _local_4)) / _local_7);
}
else
{
_local_8 = (((60 * (_local_3 - _local_4)) / _local_7) + 360);
}
}
else
{
if(_local_5 == _local_3)
{
_local_8 = (((60 * (_local_4 - _local_2)) / _local_7) + 120);
}
else
{
if(_local_5 == _local_4)
{
_local_8 = (((60 * (_local_2 - _local_3)) / _local_7) + 240);
}
}
}
}
_local_9 = (0.5 * (_local_5 + _local_6));
if(_local_7 == 0)
{
_local_10 = 0;
}
else
{
if(_local_9 <= 0.5)
{
_local_10 = ((_local_7 / _local_9) * 0.5);
}
else
{
_local_10 = ((_local_7 / (1 - _local_9)) * 0.5);
}
}
const _local_11: number = Math.round(((_local_8 / 360) * 0xFF));
const _local_12: number = Math.round((_local_10 * 0xFF));
const _local_13: number = Math.round((_local_9 * 0xFF));
const _local_14: number = (((_local_11 << 16) + (_local_12 << 8)) + _local_13);
return _local_14;
}
public static hslToRGB(k: number): number
{
let _local_12: number;
let _local_13: number;
let _local_14: number;
let _local_15: number;
let _local_16: number;
const _local_2: number = (((k >> 16) & 0xFF) / 0xFF);
const _local_3: number = (((k >> 8) & 0xFF) / 0xFF);
const _local_4: number = ((k & 0xFF) / 0xFF);
let _local_5 = 0;
let _local_6 = 0;
let _local_7 = 0;
if(_local_3 > 0)
{
_local_12 = 0;
_local_13 = 0;
if(_local_4 < 0.5)
{
_local_12 = (_local_4 * (1 + _local_3));
}
else
{
_local_12 = ((_local_4 + _local_3) - (_local_4 * _local_3));
}
_local_13 = ((2 * _local_4) - _local_12);
_local_14 = (_local_2 + (1 / 3));
_local_15 = _local_2;
_local_16 = (_local_2 - (1 / 3));
if(_local_14 < 0)
{
_local_14 = (_local_14 + 1);
}
else
{
if(_local_14 > 1)
{
_local_14--;
}
}
if(_local_15 < 0)
{
_local_15 = (_local_15 + 1);
}
else
{
if(_local_15 > 1)
{
_local_15--;
}
}
if(_local_16 < 0)
{
_local_16 = (_local_16 + 1);
}
else
{
if(_local_16 > 1)
{
_local_16--;
}
}
if((_local_14 * 6) < 1)
{
_local_5 = (_local_13 + (((_local_12 - _local_13) * 6) * _local_14));
}
else
{
if((_local_14 * 2) < 1)
{
_local_5 = _local_12;
}
else
{
if((_local_14 * 3) < 2)
{
_local_5 = (_local_13 + (((_local_12 - _local_13) * 6) * ((2 / 3) - _local_14)));
}
else
{
_local_5 = _local_13;
}
}
}
if((_local_15 * 6) < 1)
{
_local_6 = (_local_13 + (((_local_12 - _local_13) * 6) * _local_15));
}
else
{
if((_local_15 * 2) < 1)
{
_local_6 = _local_12;
}
else
{
if((_local_15 * 3) < 2)
{
_local_6 = (_local_13 + (((_local_12 - _local_13) * 6) * ((2 / 3) - _local_15)));
}
else
{
_local_6 = _local_13;
}
}
}
if((_local_16 * 6) < 1)
{
_local_7 = (_local_13 + (((_local_12 - _local_13) * 6) * _local_16));
}
else
{
if((_local_16 * 2) < 1)
{
_local_7 = _local_12;
}
else
{
if((_local_16 * 3) < 2)
{
_local_7 = (_local_13 + (((_local_12 - _local_13) * 6) * ((2 / 3) - _local_16)));
}
else
{
_local_7 = _local_13;
}
}
}
}
else
{
_local_5 = _local_4;
_local_6 = _local_4;
_local_7 = _local_4;
}
const _local_8: number = Math.round((_local_5 * 0xFF));
const _local_9: number = Math.round((_local_6 * 0xFF));
const _local_10: number = Math.round((_local_7 * 0xFF));
const _local_11: number = (((_local_8 << 16) + (_local_9 << 8)) + _local_10);
return _local_11;
}
public static rgb2xyz(k: number): IVector3D
{
let _local_2: number = (((k >> 16) & 0xFF) / 0xFF);
let _local_3: number = (((k >> 8) & 0xFF) / 0xFF);
let _local_4: number = (((k >> 0) & 0xFF) / 0xFF);
if(_local_2 > 0.04045)
{
_local_2 = Math.pow(((_local_2 + 0.055) / 1.055), 2.4);
}
else
{
_local_2 = (_local_2 / 12.92);
}
if(_local_3 > 0.04045)
{
_local_3 = Math.pow(((_local_3 + 0.055) / 1.055), 2.4);
}
else
{
_local_3 = (_local_3 / 12.92);
}
if(_local_4 > 0.04045)
{
_local_4 = Math.pow(((_local_4 + 0.055) / 1.055), 2.4);
}
else
{
_local_4 = (_local_4 / 12.92);
}
_local_2 = (_local_2 * 100);
_local_3 = (_local_3 * 100);
_local_4 = (_local_4 * 100);
return new Vector3d((((_local_2 * 0.4124) + (_local_3 * 0.3576)) + (_local_4 * 0.1805)), (((_local_2 * 0.2126) + (_local_3 * 0.7152)) + (_local_4 * 0.0722)), (((_local_2 * 0.0193) + (_local_3 * 0.1192)) + (_local_4 * 0.9505)));
}
public static xyz2CieLab(k: IVector3D): IVector3D
{
let _local_2: number = (k.x / 95.047);
let _local_3: number = (k.y / 100);
let _local_4: number = (k.z / 108.883);
if(_local_2 > 0.008856)
{
_local_2 = Math.pow(_local_2, (1 / 3));
}
else
{
_local_2 = ((7.787 * _local_2) + (16 / 116));
}
if(_local_3 > 0.008856)
{
_local_3 = Math.pow(_local_3, (1 / 3));
}
else
{
_local_3 = ((7.787 * _local_3) + (16 / 116));
}
if(_local_4 > 0.008856)
{
_local_4 = Math.pow(_local_4, (1 / 3));
}
else
{
_local_4 = ((7.787 * _local_4) + (16 / 116));
}
return new Vector3d(((116 * _local_3) - 16), (500 * (_local_2 - _local_3)), (200 * (_local_3 - _local_4)));
}
public static rgb2CieLab(k: number): IVector3D
{
return ColorConverter.xyz2CieLab(ColorConverter.rgb2xyz(k));
}
public static colorize(colorA: number, colorB: number): number
{
if(colorB === 0xFFFFFFFF) return colorA;
let r = ((colorB >> 16) & 0xFF);
let g = ((colorB >> 8) & 0xFF);
let b = (colorB & 0xFF);
r = ((((colorA >> 16) & 0xFF) * r) / 0xFF);
g = ((((colorA >> 8) & 0xFF) * g) / 0xFF);
b = (((colorA & 0xFF) * b) / 0xFF);
return ((colorA && 0xFF000000) | (r << 16) | (g << 8) | b);
}
}
+9
View File
@@ -0,0 +1,9 @@
export class FurniId
{
private static BUILDER_CLUB_FURNI_ID_BASE: number = 0x7FFF0000;
public static isBuilderClubId(k: number): boolean
{
return (k >= FurniId.BUILDER_CLUB_FURNI_ID_BASE);
}
}
+5
View File
@@ -0,0 +1,5 @@
import { Application } from 'pixi.js';
const pixi = new Application();
export const GetPixi = () => pixi;
+12
View File
@@ -0,0 +1,12 @@
import { AutoDetectOptions, Renderer, autoDetectRenderer } from 'pixi.js';
let renderer: Renderer = null;
export const PrepareRenderer = async (options: Partial<AutoDetectOptions>): Promise<Renderer> =>
{
renderer = await autoDetectRenderer(options);
return renderer;
}
export const GetRenderer = () => renderer;
+5
View File
@@ -0,0 +1,5 @@
import { Container } from 'pixi.js';
const stage = new Container();
export const GetStage = () => stage;
+5
View File
@@ -0,0 +1,5 @@
import { TexturePool } from './TexturePool';
const texturePool = new TexturePool();
export const GetTexturePool = () => texturePool;
+3
View File
@@ -0,0 +1,3 @@
import { Ticker } from 'pixi.js';
export const GetTicker = () => Ticker.shared;
+3
View File
@@ -0,0 +1,3 @@
import { GetTicker } from './GetTicker';
export const GetTickerFPS = () => GetTicker().FPS;
+3
View File
@@ -0,0 +1,3 @@
import { GetTicker } from './GetTicker';
export const GetTickerTime = () => GetTicker().lastTime;
+338
View File
@@ -0,0 +1,338 @@
import { LegacyExternalInterface } from './LegacyExternalInterface';
import { NitroLogger } from './NitroLogger';
export class HabboWebTools
{
public static ADVERTISEMENT: string = 'advertisement';
public static OPENLINK: string = 'openlink';
public static OPENROOM: string = 'openroom';
public static logEventLog(data: string): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('logEventLog', data);
}
}
catch (e)
{
NitroLogger.log('External interface not working, failed to log event log.');
}
}
public static openPage(pageUrl: string): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('openPage', pageUrl);
}
else
{
NitroLogger.log('External interface not available, openPage failed.');
}
}
catch (e)
{
NitroLogger.log('Failed to open web page', pageUrl);
}
}
public static openWebPage(pageUrl: string): void
{
window.open(pageUrl);
}
public static sendHeartBeat(): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('heartBeat');
}
}
catch (e)
{
NitroLogger.log('Failed to send heartbeat');
}
}
public static openWebPageAndMinimizeClient(pageUrl: string): void
{
try
{
if(LegacyExternalInterface.available)
{
HabboWebTools.openPage(pageUrl);
}
}
catch (e)
{
NitroLogger.log('Failed to open web page', pageUrl);
}
}
public static closeWebPageAndRestoreClient(): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('closeWebPageAndRestoreClient');
}
}
catch (e)
{
NitroLogger.log('Failed to close web page and restore client!');
}
}
public static openHabblet(name: string, param: string = null): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('openHabblet', name, param);
}
}
catch (e)
{
NitroLogger.log('Failed to open Habblet', name);
}
}
public static closeHabblet(name: string, param: string = null): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('closeHabblet', name, param);
}
}
catch (e)
{
NitroLogger.log('Failed to close Habblet', name);
}
}
public static send(reasonCode: number, reasonString: string): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('disconnect', reasonCode, reasonString);
}
}
catch (e)
{
NitroLogger.log('Failed to close send ');
}
}
public static showGame(gameUrl: string): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.callGame('showGame', gameUrl);
}
}
catch (e)
{
NitroLogger.log('Failed to open game', e);
}
}
public static hideGame(): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.callGame('hideGame');
}
}
catch (e)
{
NitroLogger.log('Failed to hide game');
}
}
public static open(url: string): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('openExternalLink', escape(url));
}
else
{
NitroLogger.log(('External interface not available. Could not request to open: ' + url));
}
}
catch (e)
{
NitroLogger.log(('External interface not working. Could not request to open: ' + url));
}
}
public static roomVisited(roomId: number): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('roomVisited', roomId);
}
else
{
NitroLogger.log('External interface not available. Could not store last room visit.');
}
}
catch (e)
{
NitroLogger.log('External interface not working. Could not store last room visit.');
}
}
public static openMinimail(target: string): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('openMinimail', target);
}
else
{
NitroLogger.log('External interface not available. Could not open minimail.');
}
}
catch (e)
{
NitroLogger.log('External interface not working. Could not open minimail.');
}
}
public static openNews(): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('openNews');
}
else
{
NitroLogger.log('External interface not available. Could not open news.');
}
}
catch (e)
{
NitroLogger.log('External interface not working. Could not open news.');
}
}
public static closeNews(): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('closeNews');
}
else
{
NitroLogger.log('External interface not available. Could not close news.');
}
}
catch (e)
{
NitroLogger.log('External interface not working. Could not close news.');
}
}
public static openAvatars(): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('openAvatars');
}
else
{
NitroLogger.log('External interface not available. Could not open avatars.');
}
}
catch (e)
{
NitroLogger.log('External interface not working. Could not open avatars.');
}
}
public static openRoomEnterAd(): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('openRoomEnterAd');
}
else
{
NitroLogger.log('External interface not available. Could not open roomenterad.');
}
}
catch (e)
{
NitroLogger.log('External interface not working. Could not open roomenterad.');
}
}
public static updateFigure(figure: string): void
{
try
{
if(LegacyExternalInterface.available)
{
LegacyExternalInterface.call('updateFigure', figure);
}
else
{
NitroLogger.log('External interface not available. Could not update figure.');
}
}
catch (e)
{
NitroLogger.log('External interface not working. Could not update figure.');
}
}
}
+13
View File
@@ -0,0 +1,13 @@
const toUint32 = (x: number) => x >>> 0;
export const ToInt32 = (x: number) =>
{
const uint32 = toUint32(x);
if(uint32 >= Math.pow(2, 31))
{
return uint32 - Math.pow(2, 32);
}
return uint32;
};
@@ -0,0 +1,118 @@
declare global
{
interface Window
{
FlashExternalInterface?:
{
legacyTrack?: (
category: string,
action: string,
data: unknown[]
) => void;
logDebug?: (...params: string[]) => void;
disconnect?: (reasonCode: number, reasonString: string) => void;
logout?: () => void;
openWebPageAndMinimizeClient?: (pageUrl: string) => void;
heartBeat?: () => void;
logEventLog?: (log: string) => void;
openPage?: (pageUrl: string) => void;
closeWebPageAndRestoreClient?: () => void;
openHabblet?: (name: string, param: string) => void;
closeHabblet?: (name: string, param: string) => void;
openExternalLink?: (link: string) => void;
roomVisited?: (roomId: number) => void;
openMinimail?: (target: string) => void;
openNews?: () => void;
closeNews?: () => void;
openAvatars?: () => void;
openRoomEnterAd?: () => void;
updateFigure?: (figure: string) => void;
};
FlashExternalGameInterface?:
{
showGame?: (url: string) => void;
hideGame?: () => void;
};
}
}
export class LegacyExternalInterface
{
private static readonly MESSAGE_KEY = 'Nitro_LegacyExternalInterface';
private static _isListeningForPostMessages = false;
public static get available(): boolean
{
if(!this._isListeningForPostMessages)
{
this._isListeningForPostMessages = true;
window.addEventListener('message', (ev) =>
{
if(typeof ev.data !== 'string') return;
if(ev.data.startsWith(LegacyExternalInterface.MESSAGE_KEY))
{
const { method, params } = JSON.parse(
ev.data.substr(LegacyExternalInterface.MESSAGE_KEY.length)
);
const fn = (window as any)[method];
if(!fn) return;
fn(...params);
return;
}
});
}
return true;
}
public static call<K extends keyof typeof window.FlashExternalInterface>(
method: K,
...params: Parameters<typeof window.FlashExternalInterface[K]>
): ReturnType<typeof window.FlashExternalInterface[K]> | undefined
{
if(window.top !== window)
{
window.top.postMessage(LegacyExternalInterface.MESSAGE_KEY + JSON.stringify({
method,
params
}), '*');
}
if(!('FlashExternalInterface' in window)) return undefined;
const fn = window.FlashExternalInterface[method] as Function;
return typeof fn !== 'undefined' ? fn(...params) : undefined;
}
public static callGame<K extends keyof typeof window.FlashExternalGameInterface>(
method: K,
...params: Parameters<typeof window.FlashExternalGameInterface[K]>
): ReturnType<typeof window.FlashExternalGameInterface[K]> | undefined
{
if(window.top !== window)
{
window.top.postMessage('Nitro_LegacyExternalGameInterface' + JSON.stringify({
method,
params
}), '*');
}
if(!('FlashExternalGameInterface' in window)) return undefined;
const fn = window.FlashExternalGameInterface[method] as Function;
return typeof fn !== 'undefined' ? fn(...params) : undefined;
}
public static addCallback(name: string, func: Function)
{
(window as any)[name] = func;
}
}
+40
View File
@@ -0,0 +1,40 @@
import { ILinkEventTracker } from '@nitrots/api';
const linkTrackers: ILinkEventTracker[] = [];
export const AddLinkEventTracker = (tracker: ILinkEventTracker): void =>
{
if(linkTrackers.indexOf(tracker) >= 0) return;
linkTrackers.push(tracker);
};
export const RemoveLinkEventTracker = (tracker: ILinkEventTracker): void =>
{
const index = linkTrackers.indexOf(tracker);
if(index === -1) return;
linkTrackers.splice(index, 1);
};
export const CreateLinkEvent = (link: string): void =>
{
if(!link || (link === '')) return;
for(const tracker of linkTrackers)
{
if(!tracker) continue;
const prefix = tracker.eventUrlPrefix;
if(prefix.length > 0)
{
if(link.substr(0, prefix.length) === prefix) tracker.linkReceived(link);
}
else
{
tracker.linkReceived(link);
}
}
};
+134
View File
@@ -0,0 +1,134 @@
import { IVector3D } from '@nitrots/api';
import { Vector3d } from './Vector3d';
export class Matrix4x4
{
public static IDENTITY:Matrix4x4 = new Matrix4x4(1, 0, 0, 0, 1, 0, 0, 0, 1);
private static TOLERANS: number = 1E-18;
private _data: number[];
constructor(k: number = 0, _arg_2: number = 0, _arg_3: number = 0, _arg_4: number = 0, _arg_5: number = 0, _arg_6: number = 0, _arg_7: number = 0, _arg_8: number = 0, _arg_9: number = 0)
{
this._data = [k, _arg_2, _arg_3, _arg_4, _arg_5, _arg_6, _arg_7, _arg_8, _arg_9];
}
public static getXRotationMatrix(k: number): Matrix4x4
{
const _local_2 = ((k * Math.PI) / 180);
const _local_3 = Math.cos(_local_2);
const _local_4 = Math.sin(_local_2);
return new Matrix4x4(1, 0, 0, 0, _local_3, -(_local_4), 0, _local_4, _local_3);
}
public static getYRotationMatrix(k: number): Matrix4x4
{
const _local_2 = ((k * Math.PI) / 180);
const _local_3 = Math.cos(_local_2);
const _local_4 = Math.sin(_local_2);
return new Matrix4x4(_local_3, 0, _local_4, 0, 1, 0, -(_local_4), 0, _local_3);
}
public static getZRotationMatrix(k: number): Matrix4x4
{
const _local_2 = ((k * Math.PI) / 180);
const _local_3 = Math.cos(_local_2);
const _local_4 = Math.sin(_local_2);
return new Matrix4x4(_local_3, -(_local_4), 0, _local_4, _local_3, 0, 0, 0, 1);
}
public identity(): Matrix4x4
{
this._data = [1, 0, 0, 0, 1, 0, 0, 0, 1];
return this;
}
public vectorMultiplication(k: IVector3D): IVector3D
{
const _local_2 = (((k.x * this._data[0]) + (k.y * this._data[3])) + (k.z * this._data[6]));
const _local_3 = (((k.x * this._data[1]) + (k.y * this._data[4])) + (k.z * this._data[7]));
const _local_4 = (((k.x * this._data[2]) + (k.y * this._data[5])) + (k.z * this._data[8]));
return new Vector3d(_local_2, _local_3, _local_4);
}
public multiply(k:Matrix4x4): Matrix4x4
{
const _local_2 = (((this._data[0] * k.data[0]) + (this._data[1] * k.data[3])) + (this._data[2] * k.data[6]));
const _local_3 = (((this._data[0] * k.data[1]) + (this._data[1] * k.data[4])) + (this._data[2] * k.data[7]));
const _local_4 = (((this._data[0] * k.data[2]) + (this._data[1] * k.data[5])) + (this._data[2] * k.data[8]));
const _local_5 = (((this._data[3] * k.data[0]) + (this._data[4] * k.data[3])) + (this._data[5] * k.data[6]));
const _local_6 = (((this._data[3] * k.data[1]) + (this._data[4] * k.data[4])) + (this._data[5] * k.data[7]));
const _local_7 = (((this._data[3] * k.data[2]) + (this._data[4] * k.data[5])) + (this._data[5] * k.data[8]));
const _local_8 = (((this._data[6] * k.data[0]) + (this._data[7] * k.data[3])) + (this._data[8] * k.data[6]));
const _local_9 = (((this._data[6] * k.data[1]) + (this._data[7] * k.data[4])) + (this._data[8] * k.data[7]));
const _local_10 = (((this._data[6] * k.data[2]) + (this._data[7] * k.data[5])) + (this._data[8] * k.data[8]));
return new Matrix4x4(_local_2, _local_3, _local_4, _local_5, _local_6, _local_7, _local_8, _local_9, _local_10);
}
public scalarMultiply(k: number): void
{
let index = 0;
while(index < this._data.length)
{
this._data[index] = (this._data[index] * k);
index++;
}
}
public rotateX(k: number): Matrix4x4
{
const _local_2 = ((k * Math.PI) / 180);
const _local_3 = Math.cos(_local_2);
const _local_4 = Math.sin(_local_2);
const _local_5 = new Matrix4x4(1, 0, 0, 0, _local_3, -(_local_4), 0, _local_4, _local_3);
return _local_5.multiply(this);
}
public rotateY(k: number): Matrix4x4
{
const _local_2 = ((k * Math.PI) / 180);
const _local_3 = Math.cos(_local_2);
const _local_4 = Math.sin(_local_2);
const _local_5 = new Matrix4x4(_local_3, 0, _local_4, 0, 1, 0, -(_local_4), 0, _local_3);
return _local_5.multiply(this);
}
public rotateZ(k: number): Matrix4x4
{
const _local_2 = ((k * Math.PI) / 180);
const _local_3 = Math.cos(_local_2);
const _local_4 = Math.sin(_local_2);
const _local_5 = new Matrix4x4(_local_3, -(_local_4), 0, _local_4, _local_3, 0, 0, 0, 1);
return _local_5.multiply(this);
}
public skew(): void
{
}
public transpose(): Matrix4x4
{
return new Matrix4x4(this._data[0], this._data[3], this._data[6], this._data[1], this._data[4], this._data[7], this._data[2], this._data[5], this._data[8]);
}
public equals(k: Matrix4x4): boolean
{
return false;
}
public get data(): number[]
{
return this._data;
}
}
+58
View File
@@ -0,0 +1,58 @@
import { inflate } from 'pako';
import { Assets, Texture } from 'pixi.js';
import { ArrayBufferToBase64 } from './ArrayBufferToBase64';
import { BinaryReader } from './BinaryReader';
export class NitroBundle
{
private static TEXT_DECODER: TextDecoder = new TextDecoder('utf-8');
private _jsonFile: Object = null;
private _texture: Texture = null;
public static async from(buffer: ArrayBuffer): Promise<NitroBundle>
{
const bundle = new NitroBundle();
await bundle.parse(buffer);
return bundle;
}
public async parse(arrayBuffer: ArrayBuffer): Promise<void>
{
const binaryReader = new BinaryReader(arrayBuffer);
let fileCount = binaryReader.readShort();
while(fileCount > 0)
{
const fileNameLength = binaryReader.readShort();
const fileName = binaryReader.readBytes(fileNameLength).toString();
const fileLength = binaryReader.readInt();
const buffer = binaryReader.readBytes(fileLength);
const inflatedBuffer = inflate(buffer.toArrayBuffer());
if(fileName.endsWith('.json'))
{
this._jsonFile = JSON.parse(NitroBundle.TEXT_DECODER.decode(inflatedBuffer));
}
else
{
this._texture = await Assets.load<Texture>(`data:image/png;base64,${ ArrayBufferToBase64(inflatedBuffer) }`);
}
fileCount--;
}
}
public get jsonFile(): Object
{
return this._jsonFile;
}
public get texture(): Texture
{
return this._texture;
}
}
+9
View File
@@ -0,0 +1,9 @@
export { };
declare global
{
interface Window
{
NitroConfig?: { [index: string]: any };
}
}
+48
View File
@@ -0,0 +1,48 @@
export class NitroLogger
{
public static LOG_DEBUG: boolean = false;
public static LOG_WARN: boolean = false;
public static LOG_ERROR: boolean = false;
public static LOG_EVENTS: boolean = false;
public static LOG_PACKETS: boolean = false;
public static log(...messages: any[]): void
{
if(!this.LOG_DEBUG) return;
console.log(this.logPrefix(), ...messages);
}
public static warn(...messages: any[]): void
{
if(!this.LOG_WARN) return;
console.warn(this.logPrefix(), ...messages);
}
public static error(...messages: any[]): void
{
if(!this.LOG_ERROR) return;
console.error(this.logPrefix(), ...messages);
}
public static events(...messages: any[]): void
{
if(!this.LOG_EVENTS) return;
console.log(this.logPrefix(), ...messages);
}
public static packets(...messages: any[]): void
{
if(!this.LOG_PACKETS) return;
console.log(this.logPrefix(), ...messages);
}
private static logPrefix(): string
{
return '[Nitro]';
}
}
+31
View File
@@ -0,0 +1,31 @@
export class NitroVersion
{
public static RENDERER_VERSION: string = '2.0.0';
public static UI_VERSION: string = '';
public static sayHello(): void
{
if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1)
{
const args = [
`\n %c %c %c Nitro ${NitroVersion.UI_VERSION} - Renderer ${NitroVersion.RENDERER_VERSION} %c %c %c https://discord.nitrodev.co %c %c \n\n`,
'background: #ffffff; padding:5px 0;',
'background: #ffffff; padding:5px 0;',
'color: #ffffff; background: #000000; padding:5px 0;',
'background: #ffffff; padding:5px 0;',
'background: #ffffff; padding:5px 0;',
'background: #000000; padding:5px 0;',
'background: #ffffff; padding:5px 0;',
'background: #ffffff; padding:5px 0;'
];
self.console.log(...args);
}
else if(self.console)
{
self.console.log(`Nitro ${NitroVersion.UI_VERSION} - Renderer ${NitroVersion.RENDERER_VERSION} `);
}
}
}
+32
View File
@@ -0,0 +1,32 @@
import { IVector3D } from '@nitrots/api';
import { Matrix4x4 } from './Matrix4x4';
import { Vector3d } from './Vector3d';
export class Node3D
{
private _location: IVector3D = null;
private _transformedLocation: IVector3D = new Vector3d();
private _needsTransformation: boolean = false;
constructor(x: number, y: number, z: number)
{
this._location = new Vector3d(x, y, z);
if((x !== 0) || (y !== 0) || (z !== 0)) this._needsTransformation = true;
}
public get location(): IVector3D
{
return this._location;
}
public get transformedLocation(): IVector3D
{
return this._transformedLocation;
}
public applyTransform(matrix: Matrix4x4): void
{
if(this._needsTransformation) this._transformedLocation = matrix.vectorMultiplication(this._location);
}
}
+54
View File
@@ -0,0 +1,54 @@
export class NumberBank
{
private _reservedNumbers: number[];
private _freeNumbers: number[];
constructor(k: number)
{
if(k < 0) k = 0;
this._reservedNumbers = [];
this._freeNumbers = [];
let i = 0;
while(i < k)
{
this._freeNumbers.push(i);
i++;
}
}
public dispose(): void
{
this._reservedNumbers = null;
this._freeNumbers = null;
}
public reserveNumber(): number
{
if(this._freeNumbers.length > 0)
{
const k = this._freeNumbers.pop();
this._reservedNumbers.push(k);
return k;
}
return -1;
}
public freeNumber(k: number): void
{
const i = this._reservedNumbers.indexOf(k);
if(i >= 0)
{
this._reservedNumbers.splice(i, 1);
this._freeNumbers.push(k);
}
}
}
+19
View File
@@ -0,0 +1,19 @@
import { Point } from 'pixi.js';
export class PointMath
{
public static sum(k: Point, _arg_2: Point): Point
{
return new Point((k.x + _arg_2.x), (k.y + _arg_2.y));
}
public static sub(k: Point, _arg_2: Point): Point
{
return new Point((k.x - _arg_2.x), (k.y - _arg_2.y));
}
public static mul(k: Point, _arg_2: number): Point
{
return new Point((k.x * _arg_2), (k.y * _arg_2));
}
}
+14
View File
@@ -0,0 +1,14 @@
export class RoomId
{
private static PREVIEW_ROOM_ID_BASE: number = 0x7FFF0000;
public static makeRoomPreviewerId(roomId: number): number
{
return (roomId & 0xFFFF) + RoomId.PREVIEW_ROOM_ID_BASE;
}
public static isRoomPreviewerId(roomId: number): boolean
{
return (roomId >= RoomId.PREVIEW_ROOM_ID_BASE);
}
}
+105
View File
@@ -0,0 +1,105 @@
import { NitroLogger, TextureUtils } from '@nitrots/utils';
import { Texture } from 'pixi.js';
export class TexturePool
{
private static MAX_IDLE: number = 3600;
private _textures: { [index: string]: { [index: string]: Texture[] } } = {};
private _totalTextures: number = 0;
private _runCount: number = 0;
public getTotalTextures(): number
{
let total = 0;
for(const width in this._textures)
{
for(const height in this._textures[width])
{
total += this._textures[width][height].length;
}
}
this._totalTextures = total;
return this._totalTextures;
}
public getTexture(width: number, height: number): Texture
{
if(!this._textures[width]) this._textures[width] = {};
if(!this._textures[width][height]) this._textures[width][height] = [];
if(this._textures[width][height].length)
{
const texture = this._textures[width][height].shift();
if(texture)
{
this._totalTextures--;
return texture;
}
}
return TextureUtils.createRenderTexture(width, height);
}
public putTexture(texture: Texture)
{
if(!texture) return;
if(!this._textures[texture.width]) this._textures[texture.width] = {};
if(!this._textures[texture.width][texture.height]) this._textures[texture.width][texture.height] = [];
//@ts-ignore
delete texture.source.hitMap;
this._textures[texture.width][texture.height].push(texture);
this._totalTextures++;
}
public run(): void
{
this._runCount++;
if(!this._totalTextures) return;
for(const width in this._textures)
{
for(const height in this._textures[width])
{
const textures = this._textures[width][height];
for(let i = textures.length - 1; i >= 0; i--)
{
const texture = textures[i];
const source = texture.source;
if((source._touched > -1) && (this._runCount - source._touched) > TexturePool.MAX_IDLE)
{
//@ts-ignore
delete texture.source.hitMap;
if(!source.destroyed) texture.destroy(true);
this._textures[texture.width][texture.height].splice(i, 1);
this._totalTextures--;
NitroLogger.log(`[TexturePool] Texture disposed: ${texture.width}x${texture.height}`);
}
}
}
}
}
public get textures(): { [index: string]: { [index: string]: Texture[] } }
{
return this._textures;
}
}
+135
View File
@@ -0,0 +1,135 @@
import { Container, ExtractImageOptions, ExtractOptions, ExtractSystem, GenerateTextureOptions, GetPixelsOutput, ICanvas, Matrix, RenderTexture, Renderer, Sprite, Texture } from 'pixi.js';
import { GetRenderer } from './GetRenderer';
export class TextureUtils
{
public static generateTexture(options: GenerateTextureOptions | Container): Texture
{
return this.getRenderer().textureGenerator.generateTexture(options);
}
public static generateTextureFromImage(image: HTMLImageElement): Texture
{
return Texture.from(image);
}
public static async generateImage(options: ExtractImageOptions | Container | Texture): Promise<HTMLImageElement>
{
return this.getExtractor().image(options);
}
public static async generateImageUrl(options: ExtractImageOptions | Container | Texture): Promise<string>
{
return this.getExtractor().base64(options);
}
public static generateCanvas(options: ExtractOptions | Container | Texture): ICanvas
{
return this.getExtractor().canvas(options);
}
public static clearRenderTexture(texture: Texture): Texture
{
return this.writeToTexture(new Sprite(Texture.EMPTY), texture);
}
public static createRenderTexture(width: number, height: number): Texture
{
if((width < 0) || (height < 0)) return null;
return RenderTexture.create({ width, height });
}
public static createAndFillRenderTexture(width: number, height: number, color: number = 16777215): Texture
{
if((width < 0) || (height < 0)) return null;
return this.clearAndFillRenderTexture(this.createRenderTexture(width, height), color);
}
public static createAndWriteRenderTexture(width: number, height: number, container: Container, transform: Matrix = null): Texture
{
if((width < 0) || (height < 0)) return null;
return this.writeToTexture(container, this.createRenderTexture(width, height), true, transform);
}
public static clearAndFillRenderTexture(texture: Texture, color: number = 16777215): Texture
{
if(!texture) return null;
const sprite = new Sprite(Texture.WHITE);
sprite.tint = color;
sprite.width = texture.width;
sprite.height = texture.height;
return this.writeToTexture(sprite, texture);
}
public static writeToTexture(container: Container, target: Texture, clear: boolean = true, transform: Matrix = null): Texture
{
if(!container || !target) return null;
this.getRenderer().render({
container,
target,
clear,
transform
});
return target;
}
public static flipTextureHorizontal(texture: Texture): Texture
{
if(!texture) return null;
const matrix = new Matrix();
matrix.scale(-1, 1);
matrix.translate(texture.width, 0);
return this.createAndWriteRenderTexture(texture.width, texture.height, new Sprite(texture), matrix);
}
public static flipTextureVertical(texture: Texture): Texture
{
if(!texture) return null;
const matrix = new Matrix();
matrix.scale(1, -1);
matrix.translate(0, texture.height);
return this.createAndWriteRenderTexture(texture.width, texture.height, new Sprite(texture), matrix);
}
public static flipTextureHorizontalAndVertical(texture: Texture): Texture
{
if(!texture) return null;
const matrix = new Matrix();
matrix.scale(-1, -1);
matrix.translate(texture.width, texture.height);
return this.createAndWriteRenderTexture(texture.width, texture.height, new Sprite(texture), matrix);
}
public static getPixels(options: ExtractOptions | Container | Texture): GetPixelsOutput
{
return this.getExtractor().pixels(options);
}
public static getRenderer(): Renderer
{
return GetRenderer();
}
public static getExtractor(): ExtractSystem
{
return this.getRenderer().extract;
}
}
+215
View File
@@ -0,0 +1,215 @@
import { IVector3D } from '@nitrots/api';
export class Vector3d implements IVector3D
{
private _length: number = NaN;
constructor(
private _x: number = 0,
private _y: number = 0,
private _z: number = 0)
{}
public static sum(vector1: IVector3D, vector2: IVector3D): Vector3d
{
if(!vector1 || !vector2) return null;
return new Vector3d((vector1.x + vector2.x), (vector1.y + vector2.y), (vector1.z + vector2.z));
}
public static dif(vector1: IVector3D, vector2: IVector3D): Vector3d
{
if(!vector1 || !vector2) return null;
return new Vector3d((vector1.x - vector2.x), (vector1.y - vector2.y), (vector1.z - vector2.z));
}
public static product(vector: IVector3D, value: number): Vector3d
{
if(!vector) return null;
return new Vector3d((vector.x * value), (vector.y * value), (vector.z * value));
}
public static dotProduct(vector1: IVector3D, vector2: IVector3D): number
{
if(!vector1 || !vector2) return 0;
return (vector1.x * vector2.x) + (vector1.y * vector2.y) + (vector1.z * vector2.z);
}
public static crossProduct(vector1: IVector3D, vector2: IVector3D): Vector3d
{
if(!vector1 || !vector2) return null;
const product = new Vector3d();
product.x = ((vector1.y * vector2.z) - (vector1.z * vector2.y));
product.y = ((vector1.z * vector2.x) - (vector1.x * vector2.z));
product.z = ((vector1.x * vector2.y) - (vector1.y * vector2.x));
return product;
}
public static scalarProjection(vector1: IVector3D, vector2: IVector3D): number
{
if(!vector1 || !vector2) return -1;
const length = vector2.length;
if(length > 0)
{
return ((vector1.x * vector2.x) + (vector1.y * vector2.y) + (vector1.z * vector2.z)) / length;
}
return -1;
}
public static cosAngle(vector1: IVector3D, vector2: IVector3D): number
{
if(!vector1 || !vector2) return 0;
const totalLength = (vector1.length * vector2.length);
if(!totalLength) return 0;
return (Vector3d.dotProduct(vector1, vector2) / totalLength);
}
public static isEqual(vector1: IVector3D, vector2: IVector3D): boolean
{
if(!vector1 || !vector2) return false;
if((vector1.x !== vector2.x) || (vector1.y !== vector2.y) || (vector1.z !== vector2.z)) return false;
return true;
}
public assign(vector: IVector3D): void
{
if(!vector) return;
this._x = vector.x;
this._y = vector.y;
this._z = vector.z;
this._length = NaN;
}
public add(vector: IVector3D): void
{
if(!vector) return;
this._x += vector.x;
this._y += vector.y;
this._z += vector.z;
this._length = NaN;
}
public subtract(vector: IVector3D): void
{
if(!vector) return;
this._x -= vector.x;
this._y -= vector.y;
this._z -= vector.z;
this._length = NaN;
}
public multiply(amount: number): void
{
this._x *= amount;
this._y *= amount;
this._z *= amount;
this._length = NaN;
}
public divide(amount: number): void
{
if(!amount) return;
this._x /= amount;
this._y /= amount;
this._z /= amount;
this._length = NaN;
}
public negate(): void
{
this._x = -(this._x);
this._y = -(this._y);
this._z = -(this._z);
}
public dotProduct(vector: IVector3D): number
{
return ((this._x * vector.x) + (this._y * vector.y)) + (this._z * vector.z);
}
public crossProduct(vector: IVector3D): IVector3D
{
const newVector = new Vector3d();
newVector.x = ((this._y * vector.z) - (this._z * vector.y));
newVector.y = ((this._z * vector.x) - (this._x * vector.z));
newVector.z = ((this._x * vector.y) - (this._y * vector.x));
return newVector;
}
public normalize(): void
{
const k = (1 / this.length);
this._x = (this._x * k);
this._y = (this._y * k);
this._z = (this._z * k);
}
public get x(): number
{
return this._x;
}
public set x(k: number)
{
this._x = k;
this._length = NaN;
}
public get y(): number
{
return this._y;
}
public set y(k: number)
{
this._y = k;
this._length = NaN;
}
public get z(): number
{
return this._z;
}
public set z(k: number)
{
this._z = k;
this._length = NaN;
}
public get length(): number
{
if(isNaN(this._length))
{
this._length = Math.sqrt(((this._x * this._x) + (this._y * this._y)) + (this._z * this._z));
}
return this._length;
}
public toString(): string
{
return `[Vector3d: ${this._x}, ${this._y}, ${this._z}]`;
}
}
@@ -0,0 +1,147 @@
import { BufferImageSource, Filter, FilterSystem, GlProgram, RenderSurface, Texture } from 'pixi.js';
import { TextureUtils } from '../TextureUtils';
export interface PaletteMapFilterOptions
{
palette: number[];
channel: number;
}
export class PaletteMapFilter extends Filter
{
public static readonly CHANNEL_RED = 0;
public static readonly CHANNEL_GREEN = 1;
public static readonly CHANNEL_BLUE = 2;
public static readonly CHANNEL_ALPHA = 3;
public static readonly DEFAULT_OPTIONS: PaletteMapFilterOptions = {
palette: [],
channel: PaletteMapFilter.CHANNEL_RED,
};
public uniforms: {
uPalette: Float32Array,
uChannel: Float32Array
};
constructor(options: PaletteMapFilterOptions)
{
options = { ...PaletteMapFilter.DEFAULT_OPTIONS, ...options };
const glProgram = GlProgram.from({
vertex: `in vec2 aPosition;
out vec2 vTextureCoord;
uniform vec4 uInputSize;
uniform vec4 uOutputFrame;
uniform vec4 uOutputTexture;
vec4 filterVertexPosition( void )
{
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
return vec4(position, 0.0, 1.0);
}
vec2 filterTextureCoord( void )
{
return aPosition * (uOutputFrame.zw * uInputSize.zw);
}
void main(void)
{
gl_Position = filterVertexPosition();
vTextureCoord = filterTextureCoord();
}`,
fragment: `
in vec2 vTextureCoord;
out vec4 finalColor;
uniform sampler2D uTexture;
uniform sampler2D uLutTexture;
uniform int channel;
void main(void) {
vec4 currentColor = texture(uTexture, vTextureCoord);
vec4 adjusted = currentColor;
if(currentColor.a > 0.0)
{
if(channel == 0)
{
adjusted = texture2D(uLutTexture, vec2((currentColor.r * 255.0 + 0.5) / 256.0, 0.5));
} else if(channel == 1) {
adjusted = texture2D(uLutTexture, vec2((currentColor.g * 255.0 + 0.5) / 256.0, 0.5));
} else if(channel == 2) {
adjusted = texture2D(uLutTexture, vec2((currentColor.b * 255.0 + 0.5) / 256.0, 0.5));
} else if(channel == 3) {
adjusted = texture2D(uLutTexture, vec2((currentColor.a * 255.0 + 0.5) / 256.0, 0.5));
}
}
finalColor = vec4(adjusted.r, adjusted.g, adjusted.b, currentColor.a);
}
`,
name: 'palette-map-filter',
});
const lookUpTable = PaletteMapFilter.getLookUpTable(options.palette);
const lutTexture = new Texture({
source: new BufferImageSource({
resource: Uint8Array.from(lookUpTable),
width: lookUpTable.length / 4,
height: 1
})
});
(async () =>
{
console.log(await TextureUtils.generateImageUrl(lutTexture));
})();
super({
gpuProgram: null,
glProgram,
resources: {
paletteMapUniforms: {
uChannel: { value: options.channel, type: 'int' }
},
uLutTexture: lutTexture.source
},
});
this.uniforms = this.resources.paletteMapUniforms.uniforms;
Object.assign(this, options);
}
public apply(
filterManager: FilterSystem,
input: Texture,
output: RenderSurface,
clearMode: boolean,
): void
{
filterManager.applyFilter(this, input, output, clearMode);
}
private static getLookUpTable(data: number[]): number[]
{
const lookUpTable = [];
for(let i = 0; i < data.length; i++)
{
lookUpTable[(i * 4) + PaletteMapFilter.CHANNEL_RED] = ((data[i] >> 16) & 0xFF);
lookUpTable[(i * 4) + PaletteMapFilter.CHANNEL_GREEN] = ((data[i] >> 8) & 0xFF);
lookUpTable[(i * 4) + PaletteMapFilter.CHANNEL_BLUE] = (data[i] & 0xFF);
lookUpTable[(i * 4) + PaletteMapFilter.CHANNEL_ALPHA] = ((data[i] >> 24) & 0xFF);
}
return lookUpTable;
}
}
@@ -0,0 +1,90 @@
import { Filter, FilterSystem, GlProgram, RenderSurface, Texture } from 'pixi.js';
export interface PlaneMaskFilterOptions
{
}
export class PlaneMaskFilter extends Filter
{
public static readonly DEFAULT_OPTIONS: PlaneMaskFilterOptions = {
};
public uniforms: {
};
constructor(options: PlaneMaskFilterOptions)
{
options = { ...PlaneMaskFilter.DEFAULT_OPTIONS, ...options };
const glProgram = GlProgram.from({
vertex: `in vec2 aPosition;
out vec2 vTextureCoord;
uniform vec4 uInputSize;
uniform vec4 uOutputFrame;
uniform vec4 uOutputTexture;
vec4 filterVertexPosition( void )
{
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
return vec4(position, 0.0, 1.0);
}
vec2 filterTextureCoord( void )
{
return aPosition * (uOutputFrame.zw * uInputSize.zw);
}
void main(void)
{
gl_Position = filterVertexPosition();
vTextureCoord = filterTextureCoord();
}`,
fragment: `
in vec2 vTextureCoord;
out vec4 finalColor;
uniform sampler2D uTexture;
void main(void) {
vec4 c = texture(uTexture, vTextureCoord);
if(c.r == 0.0 && c.g == 0.0 && c.b == 0.0) {
finalColor = vec4(0.0, 0.0, 0.0, 0.0);
} else {
finalColor = c;
}
}
`,
name: 'plane-mask-filter',
});
super({
gpuProgram: null,
glProgram,
resources: {
planeMaskUniforms: {
},
},
});
this.uniforms = this.resources.planeMaskUniforms.uniforms;
Object.assign(this, options);
}
public apply(
filterManager: FilterSystem,
input: Texture,
output: RenderSurface,
clearMode: boolean,
): void
{
filterManager.applyFilter(this, input, output, clearMode);
}
}
+143
View File
@@ -0,0 +1,143 @@
import { Color, ColorSource, Filter, FilterSystem, GlProgram, RenderSurface, Texture } from 'pixi.js';
export interface WiredFilterOptions
{
lineColor: ColorSource;
color: ColorSource;
}
export class WiredFilter extends Filter
{
public static readonly DEFAULT_OPTIONS: WiredFilterOptions = {
lineColor: 0x000000,
color: 0x000000,
};
public uniforms: {
uLineColor: Float32Array,
uColor: Float32Array
};
private _lineColor!: Color;
private _color!: Color;
constructor(options: WiredFilterOptions)
{
options = { ...WiredFilter.DEFAULT_OPTIONS, ...options };
const glProgram = GlProgram.from({
vertex: `in vec2 aPosition;
out vec2 vTextureCoord;
uniform vec4 uInputSize;
uniform vec4 uOutputFrame;
uniform vec4 uOutputTexture;
vec4 filterVertexPosition( void )
{
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
return vec4(position, 0.0, 1.0);
}
vec2 filterTextureCoord( void )
{
return aPosition * (uOutputFrame.zw * uInputSize.zw);
}
void main(void)
{
gl_Position = filterVertexPosition();
vTextureCoord = filterTextureCoord();
}`,
fragment: `
in vec2 vTextureCoord;
out vec4 finalColor;
uniform sampler2D uTexture;
uniform vec3 uLineColor;
uniform vec3 uColor;
void main(void) {
vec4 currentColor = texture(uTexture, vTextureCoord);
vec3 colorLine = uLineColor * currentColor.a;
vec3 colorOverlay = uColor * currentColor.a;
if(currentColor.r == 0.0 && currentColor.g == 0.0 && currentColor.b == 0.0 && currentColor.a > 0.0) {
finalColor = vec4(colorLine.r, colorLine.g, colorLine.b, currentColor.a);
} else if(currentColor.a > 0.0) {
finalColor = vec4(colorOverlay.r, colorOverlay.g, colorOverlay.b, currentColor.a);
}
}
`,
name: 'wired-filter',
});
super({
gpuProgram: null,
glProgram,
resources: {
planeMaskUniforms: {
uLineColor: { value: new Float32Array(3), type: 'vec3<f32>' },
uColor: { value: new Float32Array(3), type: 'vec3<f32>' }
},
},
});
this.uniforms = this.resources.planeMaskUniforms.uniforms;
this._lineColor = new Color();
this.lineColor = options.lineColor ?? 0x000000;
this._color = new Color();
this.color = options.color ?? 0x000000;
Object.assign(this, options);
}
public apply(
filterManager: FilterSystem,
input: Texture,
output: RenderSurface,
clearMode: boolean,
): void
{
filterManager.applyFilter(this, input, output, clearMode);
}
public get lineColor(): ColorSource
{
return this._lineColor.value as ColorSource;
}
public set lineColor(value: ColorSource)
{
this._lineColor.setValue(value);
const [r, g, b] = this._lineColor.toArray();
this.uniforms.uLineColor[0] = r;
this.uniforms.uLineColor[1] = g;
this.uniforms.uLineColor[2] = b;
}
public get color(): ColorSource
{
return this._color.value as ColorSource;
}
public set color(value: ColorSource)
{
this._color.setValue(value);
const [r, g, b] = this._color.toArray();
this.uniforms.uColor[0] = r;
this.uniforms.uColor[1] = g;
this.uniforms.uColor[2] = b;
}
}
+3
View File
@@ -0,0 +1,3 @@
export * from './PaletteMapFilter';
export * from './PlaneMaskFilter';
export * from './WiredFilter';
+31
View File
@@ -0,0 +1,31 @@
export * from './AdvancedMap';
export * from './ArrayBufferToBase64';
export * from './BinaryReader';
export * from './BinaryWriter';
export * from './ColorConverter';
export * from './FurniId';
export * from './GetPixi';
export * from './GetRenderer';
export * from './GetStage';
export * from './GetTexturePool';
export * from './GetTicker';
export * from './GetTickerFPS';
export * from './GetTickerTime';
export * from './HabboWebTools';
export * from './Int32';
export * from './LegacyExternalInterface';
export * from './LinkTracker';
export * from './Matrix4x4';
export * from './NitroBundle';
export * from './NitroConfig';
export * from './NitroLogger';
export * from './NitroVersion';
export * from './Node3D';
export * from './NumberBank';
export * from './PointMath';
export * from './RoomId';
export * from './TexturePool';
export * from './TextureUtils';
export * from './Vector3d';
export * from './filters';
export * from './motion';
+30
View File
@@ -0,0 +1,30 @@
import { Motion } from './Motion';
export class Callback extends Motion
{
protected _callback: Function;
constructor(k: Function)
{
super(null);
this._callback = k;
}
public get running(): boolean
{
return (this._running && !!this._callback);
}
public tick(k: number): void
{
super.tick(k);
if(this._callback)
{
this._callback();
this._callback = null;
}
}
}
+61
View File
@@ -0,0 +1,61 @@
import { Motion } from './Motion';
export class Combo extends Motion
{
private _runningMotions: Motion[];
private _removedMotions: Motion[];
constructor(...motions: Motion[])
{
super((motions && motions.length) ? motions[0].target : null);
this._runningMotions = [];
this._removedMotions = [];
for(const motion of motions) this._runningMotions.push(motion);
}
public start(): void
{
super.start();
for(const motion of this._runningMotions) motion.start();
}
public tick(k: number): void
{
super.tick(k);
let motion: Motion = null;
while(((motion = this._removedMotions.pop()) !== null))
{
this._runningMotions.splice(this._removedMotions.indexOf(motion), 1);
if(motion.running) motion.stop();
}
for(const motion of this._runningMotions)
{
if(motion.running) motion.tick(k);
if(motion.complete) this._removedMotions.push(motion);
}
if(this._runningMotions.length > 0)
{
for(const motion of this._runningMotions)
{
this._target = motion.target;
if(this._target) break;
}
this._complete = false;
}
else
{
this._complete = true;
}
}
}
+21
View File
@@ -0,0 +1,21 @@
import { Motion } from './Motion';
export class Dispose extends Motion
{
constructor(k: HTMLElement)
{
super(k);
}
public tick(k: number): void
{
super.tick(k);
if(this.target)
{
this.target.remove();
this.target = null;
}
}
}
+60
View File
@@ -0,0 +1,60 @@
import { Interval } from './Interval';
export class DropBounce extends Interval
{
private _height: number;
private _offset: number;
constructor(target: HTMLElement, duration: number, height: number)
{
super(target, duration);
this._height = height;
}
public start(): void
{
super.start();
this._offset = 0;
this.target.style.top = ((this._offset - this._height) + 'px');
}
public update(time: number): void
{
super.update(time);
this.target.style.top = (((this._offset - this._height) + (this.getBounceOffset(time) * this._height)) + 'px');
}
protected getBounceOffset(k: number): number
{
if(k < 0.364) return (7.5625 * k) * k;
if(k < 0.727)
{
k = (k - 0.545);
return ((7.5625 * k) * k) + 0.75;
}
if(k < 0.909)
{
k = (k - 0.9091);
return ((7.5625 * k) * k) + 0.9375;
}
k = (k - 0.955);
return ((7.5625 * k) * k) + 0.984375;
}
public stop(): void
{
this.target.style.top = (this._offset + 'px');
super.stop();
}
}
+34
View File
@@ -0,0 +1,34 @@
import { Interval } from './Interval';
export class Ease extends Interval
{
protected _interval: Interval;
constructor(k: Interval)
{
super(k.target, k.duration);
this._interval = k;
}
public start(): void
{
super.start();
this._interval.start();
}
public update(k: number): void
{
super.update(k);
this._interval.update(k);
}
public stop(): void
{
super.stop();
this._interval.stop();
}
}
+15
View File
@@ -0,0 +1,15 @@
import { EaseRate } from './EaseRate';
import { Interval } from './Interval';
export class EaseOut extends EaseRate
{
constructor(k: Interval, _arg_2: number)
{
super(k, _arg_2);
}
public update(k: number): void
{
this._interval.update(Math.pow(k, (1 / this._rate)));
}
}
+14
View File
@@ -0,0 +1,14 @@
import { Ease } from './Ease';
import { Interval } from './Interval';
export class EaseRate extends Ease
{
protected _rate: number;
constructor(k: Interval, _arg_2: number)
{
super(k);
this._rate = _arg_2;
}
}
+47
View File
@@ -0,0 +1,47 @@
import { GetTickerTime } from '../GetTickerTime';
import { Motion } from './Motion';
export class Interval extends Motion
{
private _startTimeMs: number;
private _duration: number;
constructor(target: HTMLElement, duration: number)
{
super(target);
this._complete = false;
this._duration = duration;
}
public get duration(): number
{
return this._duration;
}
public start(): void
{
super.start();
this._complete = false;
this._startTimeMs = GetTickerTime();
}
public tick(time: number): void
{
super.tick(time);
const elapsed = ((time - this._startTimeMs) / this._duration);
if(elapsed < 1)
{
this.update(elapsed);
}
else
{
this.update(1);
this._complete = true;
}
}
}
+37
View File
@@ -0,0 +1,37 @@
import { Interval } from './Interval';
export class JumpBy extends Interval
{
protected _startX: number;
protected _startY: number;
protected _deltaX: number;
protected _deltaY: number;
protected _height: number;
protected _numJumps: number;
constructor(target: HTMLElement, duration: number, deltaX: number, deltaY: number, height: number, numJumps: number)
{
super(target, duration);
this._deltaX = deltaX;
this._deltaY = deltaY;
this._height = -(height);
this._numJumps = numJumps;
}
public start(): void
{
super.start();
this._startX = this.target.offsetLeft;
this._startY = this.target.offsetTop;
}
public update(k: number): void
{
super.update(k);
this.target.style.left = ((this._startX + (this._deltaX * k)) + 'px');
this.target.style.top = (((this._startY + (this._height * Math.abs(Math.sin(((k * Math.PI) * this._numJumps))))) + (this._deltaY * k)) + 'px');
}
}
+61
View File
@@ -0,0 +1,61 @@
export class Motion
{
protected _target: HTMLElement;
protected _running: boolean;
protected _complete: boolean = true;
protected _tag: string;
constructor(target: HTMLElement)
{
this._target = target;
}
public get running(): boolean
{
return ((this._running) && (!!this._target));
}
public get complete(): boolean
{
return this._complete;
}
public set target(k: HTMLElement)
{
this._target = k;
}
public get target(): HTMLElement
{
return this._target;
}
public set tag(k: string)
{
this._tag = k;
}
public get tag(): string
{
return this._tag;
}
public start(): void
{
this._running = true;
}
public update(k: number): void
{
}
public stop(): void
{
this._target = null;
this._running = false;
}
public tick(k: number): void
{
}
}
+194
View File
@@ -0,0 +1,194 @@
import { GetTickerFPS } from '../GetTickerFPS';
import { GetTickerTime } from '../GetTickerTime';
import { Motion } from './Motion';
export class Motions
{
private static _QUEUED_MOTIONS: Motion[] = [];
private static _RUNNING_MOTIONS: Motion[] = [];
private static _REMOVED_MOTIONS: Motion[] = [];
private static _TIMER: ReturnType<typeof setInterval> = null;
private static _IS_UPDATING: boolean = false;
public static get TIMER_TIME(): number
{
return (1000 / GetTickerFPS());
}
public static runMotion(k: Motion): Motion
{
if(((Motions._RUNNING_MOTIONS.indexOf(k) === -1) && (Motions._QUEUED_MOTIONS.indexOf(k) === -1)))
{
if(Motions._IS_UPDATING)
{
Motions._QUEUED_MOTIONS.push(k);
}
else
{
Motions._RUNNING_MOTIONS.push(k);
k.start();
}
Motions.startTimer();
}
return k;
}
public static removeMotion(k: Motion): void
{
let _local_2: number = Motions._RUNNING_MOTIONS.indexOf(k);
if(_local_2 > -1)
{
if(Motions._IS_UPDATING)
{
_local_2 = Motions._REMOVED_MOTIONS.indexOf(k);
if(_local_2 == -1) Motions._REMOVED_MOTIONS.push(k);
}
else
{
Motions._RUNNING_MOTIONS.splice(_local_2, 1);
if(k.running) k.stop();
if(!Motions._RUNNING_MOTIONS.length) Motions.stopTimer();
}
}
else
{
_local_2 = Motions._QUEUED_MOTIONS.indexOf(k);
if(_local_2 > -1) Motions._QUEUED_MOTIONS.splice(_local_2, 1);
}
}
public static getMotionByTag(k: string): Motion
{
for(const _local_2 of Motions._RUNNING_MOTIONS)
{
if(_local_2.tag == k) return _local_2;
}
for(const _local_2 of Motions._QUEUED_MOTIONS)
{
if(_local_2.tag == k) return _local_2;
}
return null;
}
public static getMotionByTarget(k: HTMLElement): Motion
{
for(const _local_2 of Motions._RUNNING_MOTIONS)
{
if(_local_2.target == k) return _local_2;
}
for(const _local_2 of Motions._QUEUED_MOTIONS)
{
if(_local_2.target == k) return _local_2;
}
return null;
}
public static getMotionByTagAndTarget(k: string, _arg_2: HTMLElement): Motion
{
for(const _local_3 of Motions._RUNNING_MOTIONS)
{
if(((_local_3.tag == k) && (_local_3.target == _arg_2))) return _local_3;
}
for(const _local_3 of Motions._QUEUED_MOTIONS)
{
if(((_local_3.tag == k) && (_local_3.target == _arg_2))) return _local_3;
}
return null;
}
public static get isRunning(): boolean
{
return !!Motions._TIMER;
}
public static get isUpdating(): boolean
{
return Motions._IS_UPDATING;
}
private static onTick(): void
{
Motions._IS_UPDATING = true;
const _local_2: number = GetTickerTime();
let _local_3: Motion = null;
// eslint-disable-next-line no-cond-assign
while(_local_3 = Motions._QUEUED_MOTIONS.pop()) Motions._RUNNING_MOTIONS.push(_local_3);
// eslint-disable-next-line no-cond-assign
while(_local_3 = Motions._REMOVED_MOTIONS.pop())
{
Motions._RUNNING_MOTIONS.splice(Motions._RUNNING_MOTIONS.indexOf(_local_3), 1);
if(_local_3.running) _local_3.stop();
}
for(_local_3 of Motions._RUNNING_MOTIONS)
{
if(_local_3.running)
{
_local_3.tick(_local_2);
if(_local_3.complete)
{
Motions.removeMotion(_local_3);
}
}
else
{
Motions.removeMotion(_local_3);
}
}
if(!Motions._RUNNING_MOTIONS.length) Motions.stopTimer();
Motions._IS_UPDATING = false;
}
private static startTimer(): void
{
if(!Motions._TIMER)
{
Motions._TIMER = setInterval(Motions.onTick, Motions.TIMER_TIME);
}
}
private static stopTimer(): void
{
if(Motions._TIMER)
{
clearInterval(Motions._TIMER);
Motions._TIMER = null;
}
}
public getNumRunningMotions(k: HTMLElement): number
{
let _local_2 = 0;
for(const _local_3 of Motions._RUNNING_MOTIONS)
{
if(_local_3.target === k) _local_2++;
}
return _local_2;
}
}
+17
View File
@@ -0,0 +1,17 @@
import { MoveTo } from './MoveTo';
export class MoveBy extends MoveTo
{
constructor(k: HTMLElement, _arg_2: number, _arg_3: number, _arg_4: number)
{
super(k, _arg_2, _arg_3, _arg_4);
}
public start(): void
{
this._endX = (this.target.offsetLeft + this._endX);
this._endY = (this.target.offsetTop + this._endY);
super.start();
}
}
+35
View File
@@ -0,0 +1,35 @@
import { Interval } from './Interval';
export class MoveTo extends Interval
{
protected _startX: number;
protected _startY: number;
protected _endX: number;
protected _endY: number;
protected _deltaX: number;
protected _deltaY: number;
constructor(k: HTMLElement, _arg_2: number, _arg_3: number, _arg_4: number)
{
super(k, _arg_2);
this._endX = _arg_3;
this._endY = _arg_4;
}
public start(): void
{
super.start();
this._startX = this.target.offsetLeft;
this._startY = this.target.offsetTop;
this._deltaX = (this._endX - this._startX);
this._deltaY = (this._endY - this._startY);
}
public update(k: number): void
{
this.target.style.left = ((this._startX + (this._deltaX * k)) + 'px');
this.target.style.top = ((this._startY + (this._deltaY * k)) + 'px');
}
}
+71
View File
@@ -0,0 +1,71 @@
import { Motion } from './Motion';
export class Queue extends Motion
{
private _motion: Motion;
private _queue: Motion[];
constructor(...motions: Motion[])
{
super((motions ? motions[0].target : null));
this._queue = [];
for(const motion of motions) this._queue.push(motion);
this._motion = motions[0];
this._complete = !this._motion;
}
public get running(): boolean
{
return ((this._running && this._motion) ? this._motion.running : false);
}
public start(): void
{
super.start();
this._motion.start();
}
public update(k: number): void
{
super.update(k);
if(this._motion.running) this._motion.update(k);
}
public stop(): void
{
super.stop();
this._motion.stop();
}
public tick(k: number): void
{
super.tick(k);
this._motion.tick(k);
if(this._motion.complete)
{
this._motion.stop();
const index = this._queue.indexOf(this._motion);
if(index < (this._queue.length - 1))
{
this._motion = this._queue[(index + 1)];
this._target = this._motion.target;
this._motion.start();
}
else
{
this._complete = true;
}
}
}
}
+35
View File
@@ -0,0 +1,35 @@
import { Interval } from './Interval';
export class ResizeTo extends Interval
{
protected _startW: number;
protected _startH: number;
protected _endW: number;
protected _endH: number;
protected _deltaW: number;
protected _deltaH: number;
constructor(k: HTMLElement, _arg_2: number, _arg_3: number, _arg_4: number)
{
super(k, _arg_2);
this._endW = _arg_3;
this._endH = _arg_4;
}
public start(): void
{
super.start();
this._startW = this.target.offsetWidth;
this._startH = this.target.offsetHeight;
this._deltaW = (this._endW - this._startW);
this._deltaH = (this._endH - this._startH);
}
public update(k: number): void
{
this.target.style.width = ((this._startW + (this._deltaW * k)) + 'px');
this.target.style.height = ((this._startH + (this._deltaH * k)) + 'px');
}
}
+37
View File
@@ -0,0 +1,37 @@
import { GetTickerTime } from '../GetTickerTime';
import { Motion } from './Motion';
export class Wait extends Motion
{
private _startTimeMs: number;
private _waitTimeMs: number;
constructor(k: number)
{
super(null);
this._waitTimeMs = k;
}
public get running(): boolean
{
return this._running;
}
public start(): void
{
super.start();
this._complete = false;
this._startTimeMs = GetTickerTime();
}
public tick(k: number): void
{
super.tick(k);
this._complete = ((k - this._startTimeMs) >= this._waitTimeMs);
if(this._complete) this.stop();
}
}
+16
View File
@@ -0,0 +1,16 @@
export * from './Callback';
export * from './Combo';
export * from './Dispose';
export * from './DropBounce';
export * from './Ease';
export * from './EaseOut';
export * from './EaseRate';
export * from './Interval';
export * from './JumpBy';
export * from './Motion';
export * from './Motions';
export * from './MoveBy';
export * from './MoveTo';
export * from './Queue';
export * from './ResizeTo';
export * from './Wait';
+31
View File
@@ -0,0 +1,31 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./src",
"outDir": "./dist",
"sourceMap": false,
"declaration": true,
"experimentalDecorators": true,
"moduleResolution": "Node",
"esModuleInterop": true,
"importHelpers": true,
"isolatedModules": true,
"resolveJsonModule": true,
"downlevelIteration": true,
"allowSyntheticDefaultImports": true,
"allowJs": true,
"skipLibCheck": true,
"noEmit": true,
"strict": false,
"strictNullChecks": false,
"target": "ES6",
"lib": [
"DOM",
"DOM.Iterable",
"ESNext"
],
"module": "ES6"
},
"include": [
"src" ]
}