You've already forked Nitro_Render_V3
mirror of
https://github.com/duckietm/Nitro_Render_V3.git
synced 2026-06-19 15:06:20 +00:00
Move to Renderer V2
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": [ "@nitrots/eslint-config" ]
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
export * from './src';
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Application } from 'pixi.js';
|
||||
|
||||
const pixi = new Application();
|
||||
|
||||
export const GetPixi = () => pixi;
|
||||
@@ -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;
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Container } from 'pixi.js';
|
||||
|
||||
const stage = new Container();
|
||||
|
||||
export const GetStage = () => stage;
|
||||
@@ -0,0 +1,5 @@
|
||||
import { TexturePool } from './TexturePool';
|
||||
|
||||
const texturePool = new TexturePool();
|
||||
|
||||
export const GetTexturePool = () => texturePool;
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Ticker } from 'pixi.js';
|
||||
|
||||
export const GetTicker = () => Ticker.shared;
|
||||
@@ -0,0 +1,3 @@
|
||||
import { GetTicker } from './GetTicker';
|
||||
|
||||
export const GetTickerFPS = () => GetTicker().FPS;
|
||||
@@ -0,0 +1,3 @@
|
||||
import { GetTicker } from './GetTicker';
|
||||
|
||||
export const GetTickerTime = () => GetTicker().lastTime;
|
||||
@@ -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.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export { };
|
||||
|
||||
declare global
|
||||
{
|
||||
interface Window
|
||||
{
|
||||
NitroConfig?: { [index: string]: any };
|
||||
}
|
||||
}
|
||||
@@ -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]';
|
||||
}
|
||||
}
|
||||
@@ -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} `);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './PaletteMapFilter';
|
||||
export * from './PlaneMaskFilter';
|
||||
export * from './WiredFilter';
|
||||
@@ -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';
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
@@ -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" ]
|
||||
}
|
||||
Reference in New Issue
Block a user