From 872b465cdeddf1c2ae515c8189bf1b496ca06db3 Mon Sep 17 00:00:00 2001 From: pissang Date: Sat, 23 Apr 2022 20:00:26 +0800 Subject: [PATCH] wip: update core module to typescript --- src/.eslintrc.js | 5 +- src/Geometry.ts | 4 +- src/GeometryBase.ts | 12 +- src/Material.ts | 4 +- src/Scene.ts | 2 +- src/Shader.ts | 4 +- src/StandardMaterial.ts | 4 +- src/TextureCube.ts | 2 +- src/application.ts | 4 +- src/async/Task.ts | 8 +- src/async/TaskGroup.ts | 2 +- src/claygl.ts | 7 +- src/compositor/TexturePool.ts | 2 +- src/core/Base.ts | 23 +- src/core/Cache.ts | 90 ++--- src/core/GLInfo.ts | 65 +-- src/core/LRU.ts | 144 +++---- src/core/LinkedList.ts | 414 +++++++++----------- src/core/{mixin/notifier.ts => Notifier.ts} | 69 ++-- src/core/color.ts | 216 +++++----- src/core/glenum.ts | 3 +- src/core/mixin/extend.ts | 106 ----- src/core/request.ts | 22 +- src/core/util.ts | 301 ++++++-------- src/core/vendor.ts | 42 +- src/createCompositor.ts | 2 +- src/deferred/Renderer.ts | 2 +- src/geometry/Cube.ts | 2 +- src/gpu/GLProgram.ts | 4 +- src/light/AmbientSH.ts | 3 +- src/loader/GLTF.ts | 43 +- src/plugin/GestureMgr.ts | 2 +- src/shader/builtin.ts | 2 +- src/shader/source/util.glsl | 6 +- src/shader/source/util.glsl.ts | 2 +- src/util/sh.ts | 6 +- src/util/transferable.ts | 4 +- 37 files changed, 699 insertions(+), 934 deletions(-) rename src/core/{mixin/notifier.ts => Notifier.ts} (78%) delete mode 100644 src/core/mixin/extend.ts diff --git a/src/.eslintrc.js b/src/.eslintrc.js index aaedcefd..2653563a 100644 --- a/src/.eslintrc.js +++ b/src/.eslintrc.js @@ -11,8 +11,9 @@ module.exports = { 'no-array-constructor': 2, 'no-label-var': 2, 'no-undef-init': 2, - 'no-unused-vars': 0, - '@typescript-eslint/no-unused-vars': [1, { vars: 'local', args: 'none' }] + 'no-dupe-class-members': 0, + '@typescript-eslint/no-unused-vars': [1, { vars: 'local', args: 'none' }], + '@typescript-eslint/no-dupe-class-members': 2 }, globals: { console: true, diff --git a/src/Geometry.ts b/src/Geometry.ts index 436c96ab..0996fede 100644 --- a/src/Geometry.ts +++ b/src/Geometry.ts @@ -184,7 +184,7 @@ const Geometry = GeometryBase.extend( let normals = attributes.normal.value; if (!normals || normals.length !== positions.length) { - normals = attributes.normal.value = new vendor.Float32Array(positions.length); + normals = attributes.normal.value = new Float32Array(positions.length); } else { // Reset for (let i = 0; i < normals.length; i++) { @@ -433,7 +433,7 @@ const Geometry = GeometryBase.extend( } if (this.indices.length > 0xffff) { - this.indices = new vendor.Uint32Array(this.indices); + this.indices = new Uint32Array(this.indices); } const attributes = this.attributes; diff --git a/src/GeometryBase.ts b/src/GeometryBase.ts index c0d37e06..91ae5f87 100644 --- a/src/GeometryBase.ts +++ b/src/GeometryBase.ts @@ -7,11 +7,11 @@ import vendor from './core/vendor'; function getArrayCtorByType(type) { return ( { - byte: vendor.Int8Array, - ubyte: vendor.Uint8Array, - short: vendor.Int16Array, - ushort: vendor.Uint16Array - }[type] || vendor.Float32Array + byte: Int8Array, + ubyte: Uint8Array, + short: Int16Array, + ushort: Uint16Array + }[type] || Float32Array ); } @@ -393,7 +393,7 @@ const GeometryBase = Base.extend( */ initIndicesFromArray: function (array) { let value; - const ArrayConstructor = this.vertexCount > 0xffff ? vendor.Uint32Array : vendor.Uint16Array; + const ArrayConstructor = this.vertexCount > 0xffff ? Uint32Array : Uint16Array; // Convert 2d array to flat if (array[0] && array[0].length) { let n = 0; diff --git a/src/Material.ts b/src/Material.ts index b33e243c..6de8ee8e 100644 --- a/src/Material.ts +++ b/src/Material.ts @@ -1,7 +1,7 @@ // @ts-nocheck import Base from './core/Base'; -import util from './core/util'; -import colorUtil from './core/color'; +import * as util from './core/util'; +import * as colorUtil from './core/color'; const parseColor = colorUtil.parseToFloat; const programKeyCache = {}; diff --git a/src/Scene.ts b/src/Scene.ts index 60bcff1f..e3d0540f 100644 --- a/src/Scene.ts +++ b/src/Scene.ts @@ -3,7 +3,7 @@ import Node from './Node'; import Light from './Light'; import Camera from './Camera'; import BoundingBox from './math/BoundingBox'; -import util from './core/util'; +import * as util from './core/util'; import mat4 from './glmatrix/mat4'; import LRUCache from './core/LRU'; import Matrix4 from './math/Matrix4'; diff --git a/src/Shader.ts b/src/Shader.ts index 2ed814e3..6464c680 100644 --- a/src/Shader.ts +++ b/src/Shader.ts @@ -6,7 +6,7 @@ * http://www.nvidia.com/object/using_sas.html * https://github.com/KhronosGroup/collada2json/issues/45 */ -import util from './core/util'; +import * as util from './core/util'; import vendor from './core/vendor'; const uniformRegex = @@ -263,7 +263,7 @@ function parseDeclarations(type, line) { continue; } else if (token === ')') { - declarations[currentDeclaration].value = new vendor.Float32Array(declarationValue); + declarations[currentDeclaration].value = new Float32Array(declarationValue); declarationValue = null; opType = TYPE_NORMAL; continue; diff --git a/src/StandardMaterial.ts b/src/StandardMaterial.ts index 9976f40e..ae17182b 100644 --- a/src/StandardMaterial.ts +++ b/src/StandardMaterial.ts @@ -3,7 +3,7 @@ import Material from './Material'; import Shader from './Shader'; import standardEssl from './shader/source/standard.glsl.js'; -import util from './core/util'; +import * as util from './core/util'; // Import standard shader Shader.import(standardEssl); @@ -82,7 +82,7 @@ const StandardMaterial = Material.extend( }, function (option) { // PENDING - util.extend(this, option); + Object.assign(this, option); // Extend after shader is created. util.defaults( this, diff --git a/src/TextureCube.ts b/src/TextureCube.ts index b3350499..64e280cb 100644 --- a/src/TextureCube.ts +++ b/src/TextureCube.ts @@ -1,7 +1,7 @@ // @ts-nocheck import Texture from './Texture'; import glenum from './core/glenum'; -import util from './core/util'; +import * as util from './core/util'; import mathUtil from './math/util'; import vendor from './core/vendor'; const isPowerOfTwo = mathUtil.isPowerOfTwo; diff --git a/src/application.ts b/src/application.ts index 2cdb6761..395bc7d8 100644 --- a/src/application.ts +++ b/src/application.ts @@ -35,12 +35,12 @@ import AmbientSHLight from './light/AmbientSH'; import ShadowMapPass from './prePass/ShadowMap'; import RayPicking from './picking/RayPicking'; import LRUCache from './core/LRU'; -import util from './core/util'; +import * as util from './core/util'; import shUtil from './util/sh'; import textureUtil from './util/texture'; import vendor from './core/vendor'; -import colorUtil from './core/color'; +import * as colorUtil from './core/color'; const parseColor = colorUtil.parseToFloat; import shaderLibrary from './shader/builtin'; diff --git a/src/async/Task.ts b/src/async/Task.ts index 4c39c3ff..3ce04a53 100644 --- a/src/async/Task.ts +++ b/src/async/Task.ts @@ -1,7 +1,7 @@ // @ts-nocheck -import notifier from '../core/mixin/notifier'; +import notifier from '../core/otifierr import vendor from '../core/vendor'; -import util from '../core/util'; +import * as util from '../core/util'; /** * @constructor @@ -52,7 +52,7 @@ Task.prototype.isSettled = function () { return this._fullfilled || this._rejected; }; -util.extend(Task.prototype, notifier); +Object.assign(Task.prototype, notifier); function makeRequestTask(url, responseType) { const task = new Task(); @@ -116,6 +116,6 @@ Task.makeTask = function () { return new Task(); }; -util.extend(Task.prototype, notifier); +Object.assign(Task.prototype, notifier); export default Task; diff --git a/src/async/TaskGroup.ts b/src/async/TaskGroup.ts index 6534f209..a07a70d5 100644 --- a/src/async/TaskGroup.ts +++ b/src/async/TaskGroup.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import util from '../core/util'; +import * as util from '../core/util'; import Task from './Task'; /** diff --git a/src/claygl.ts b/src/claygl.ts index b9e9d84f..4d241d47 100644 --- a/src/claygl.ts +++ b/src/claygl.ts @@ -46,10 +46,9 @@ import glenum$26 from './core/glenum'; import GLInfo$27 from './core/GLInfo'; import LinkedList$28 from './core/LinkedList'; import LRU$29 from './core/LRU'; -import extend$30 from './core/mixin/extend'; -import notifier$31 from './core/mixin/notifier'; +import notifier$31 from './core/notifier import request$32 from './core/request'; -import util$33 from './core/util'; +import * as util$33 from './core/util'; import vendor$34 from './core/vendor'; import createCompositor$35 from './createCompositor'; import GBuffer$36 from './deferred/GBuffer'; @@ -87,7 +86,7 @@ import Matrix4$67 from './math/Matrix4'; import Plane$68 from './math/Plane'; import Quaternion$69 from './math/Quaternion'; import Ray$70 from './math/Ray'; -import util$71 from './math/util'; +import * as util$71 from './math/util'; import Value$72 from './math/Value'; import Vector2$73 from './math/Vector2'; import Vector3$74 from './math/Vector3'; diff --git a/src/compositor/TexturePool.ts b/src/compositor/TexturePool.ts index 093e77a0..38ef5957 100644 --- a/src/compositor/TexturePool.ts +++ b/src/compositor/TexturePool.ts @@ -1,7 +1,7 @@ // @ts-nocheck import Texture2D from '../Texture2D'; import glenum from '../core/glenum'; -import util from '../core/util'; +import * as util from '../core/util'; const TexturePool = function () { this._pool = {}; diff --git a/src/core/Base.ts b/src/core/Base.ts index 948fb380..6c28998d 100644 --- a/src/core/Base.ts +++ b/src/core/Base.ts @@ -1,7 +1,4 @@ -// @ts-nocheck -import extendMixin from './mixin/extend'; -import notifierMixin from './mixin/notifier'; -import util from './util'; +import * as util from './util'; /** * Base class of all objects @@ -9,20 +6,12 @@ import util from './util'; * @alias clay.core.Base * @mixes clay.core.mixin.notifier */ -const Base = function () { - /** - * @type {number} - */ - this.__uid__ = util.genGUID(); -}; -Base.__initializers__ = [ - function (opts) { - util.extend(this, opts); +class Base { + __uid__: number; + constructor() { + this.__uid__ = util.genGUID(); } -]; - -util.extend(Base, extendMixin); -util.extend(Base.prototype, notifierMixin); +} export default Base; diff --git a/src/core/Cache.ts b/src/core/Cache.ts index eac33c1d..e15bfa67 100644 --- a/src/core/Cache.ts +++ b/src/core/Cache.ts @@ -1,109 +1,103 @@ -// @ts-nocheck -import util from './util'; +import * as util from './util'; const DIRTY_PREFIX = '__dt__'; -const Cache = function () { - this._contextId = 0; +class Cache = Record> { + private _contextId = 0; + private _caches: D[] = []; + private _context = {} as D; - this._caches = []; + constructor() {} - this._context = {}; -}; - -Cache.prototype = { - use: function (contextId, documentSchema) { + use(contextId: number, documentSchema?: () => D) { const caches = this._caches; if (!caches[contextId]) { - caches[contextId] = {}; + caches[contextId] = {} as D; if (documentSchema) { caches[contextId] = documentSchema(); } } this._contextId = contextId; - this._context = caches[contextId]; - }, + } - put: function (key, value) { + put(key: T, value: D[T]) { this._context[key] = value; - }, + } - get: function (key) { + get(key: T): D[T] { return this._context[key]; - }, + } - dirty: function (field) { + dirty(field: string) { field = field || ''; const key = DIRTY_PREFIX + field; - this.put(key, true); - }, + this.put(key, true as any); + } - dirtyAll: function (field) { + dirtyAll(field: string) { field = field || ''; const key = DIRTY_PREFIX + field; const caches = this._caches; for (let i = 0; i < caches.length; i++) { if (caches[i]) { - caches[i][key] = true; + (caches[i] as any)[key] = true; } } - }, + } - fresh: function (field) { + fresh(field: string) { field = field || ''; const key = DIRTY_PREFIX + field; - this.put(key, false); - }, + this.put(key, false as any); + } - freshAll: function (field) { + freshAll(field: string) { field = field || ''; const key = DIRTY_PREFIX + field; const caches = this._caches; for (let i = 0; i < caches.length; i++) { if (caches[i]) { - caches[i][key] = false; + (caches[i] as any)[key] = false; } } - }, + } - isDirty: function (field) { + isDirty(field: string) { field = field || ''; const key = DIRTY_PREFIX + field; const context = this._context; return !util.hasOwn(context, key) || context[key] === true; - }, + } - deleteContext: function (contextId) { + deleteContext(contextId: number) { delete this._caches[contextId]; - this._context = {}; - }, + this._context = {} as D; + } - delete: function (key) { + delete(key: string) { delete this._context[key]; - }, + } - clearAll: function () { - this._caches = {}; - }, + clearAll() { + this._caches = []; + } - getContext: function () { + getContext() { return this._context; - }, + } - eachContext: function (cb, context) { + eachContext(cb: (key: string) => void) { const keys = Object.keys(this._caches); keys.forEach(function (key) { - cb && cb.call(context, key); + cb(key); }); - }, + } - miss: function (key) { + miss(key: string) { return !util.hasOwn(this._context, key); } -}; - -Cache.prototype.constructor = Cache; +} export default Cache; diff --git a/src/core/GLInfo.ts b/src/core/GLInfo.ts index d2c926d1..4378f58d 100644 --- a/src/core/GLInfo.ts +++ b/src/core/GLInfo.ts @@ -1,4 +1,3 @@ -// @ts-nocheck const EXTENSION_LIST = [ 'OES_texture_float', 'OES_texture_half_float', @@ -20,46 +19,52 @@ const EXTENSION_LIST = [ 'EXT_frag_depth', 'EXT_sRGB', 'ANGLE_instanced_arrays' -]; +] as const; const PARAMETER_NAMES = ['MAX_TEXTURE_SIZE', 'MAX_CUBE_MAP_TEXTURE_SIZE']; -function GLInfo(_gl) { - const extensions = {}; - const parameters = {}; +/* global WebGLRenderingContext */ +class GLInfo { + private _extensions: Record = {}; + private _parameters: Record = {}; + gl: WebGLRenderingContext; - // Get webgl extension - for (let i = 0; i < EXTENSION_LIST.length; i++) { - const extName = EXTENSION_LIST[i]; - createExtension(extName); - } - // Get parameters - for (let i = 0; i < PARAMETER_NAMES.length; i++) { - const name = PARAMETER_NAMES[i]; - parameters[name] = _gl.getParameter(_gl[name]); - } - - this.getExtension = function (name) { - if (!(name in extensions)) { - createExtension(name); + constructor(gl: WebGLRenderingContext) { + this.gl = gl; + // Get webgl extension + for (let i = 0; i < EXTENSION_LIST.length; i++) { + const extName = EXTENSION_LIST[i]; + this._createExtension(extName); } - return extensions[name]; - }; + // Get parameters + for (let i = 0; i < PARAMETER_NAMES.length; i++) { + const name = PARAMETER_NAMES[i]; + this._parameters[name] = gl.getParameter((gl as any)[name]); + } + } - this.getParameter = function (name) { - return parameters[name]; - }; + getExtension(name: string) { + if (!(name in this._extensions)) { + this._createExtension(name); + } + return this._extensions[name]; + } - function createExtension(name) { - if (_gl.getExtension) { - let ext = _gl.getExtension(name); + getParameter(name: string) { + return this._parameters[name]; + } + + private _createExtension(name: string) { + const gl = this.gl; + if (gl.getExtension) { + let ext = gl.getExtension(name); if (!ext) { - ext = _gl.getExtension('MOZ_' + name); + ext = gl.getExtension('MOZ_' + name); } if (!ext) { - ext = _gl.getExtension('WEBKIT_' + name); + ext = gl.getExtension('WEBKIT_' + name); } - extensions[name] = ext; + this._extensions[name] = ext; } } } diff --git a/src/core/LRU.ts b/src/core/LRU.ts index 47a07ca6..54fe707b 100644 --- a/src/core/LRU.ts +++ b/src/core/LRU.ts @@ -1,82 +1,92 @@ -// @ts-nocheck -import LinkedList from './LinkedList'; -import util from './util'; +import LinkedList, { Entry } from './LinkedList'; +import * as util from './util'; + +interface LRUEntry extends Entry { + key: string; +} /** * LRU Cache * @constructor - * @alias clay.core.LRU */ -const LRU = function (maxSize) { - this._list = new LinkedList(); +class LRU { + private _list = new LinkedList(); + private _map: Record> = {}; + private _maxSize: number; - this._map = {}; - - this._maxSize = maxSize || 10; -}; - -/** - * Set cache max size - * @param {number} size - */ -LRU.prototype.setMaxSize = function (size) { - this._maxSize = size; -}; - -/** - * @param {string} key - * @param {} value - */ -LRU.prototype.put = function (key, value) { - if (!util.hasOwn(this._map, key)) { - const len = this._list.length(); - if (len >= this._maxSize && len > 0) { - // Remove the least recently used - const leastUsedEntry = this._list.head; - this._list.remove(leastUsedEntry); - delete this._map[leastUsedEntry.key]; - } - - const entry = this._list.insert(value); - entry.key = key; - this._map[key] = entry; + constructor(maxSize: number) { + this._maxSize = maxSize || 10; } -}; -/** - * @param {string} key - * @return {} - */ -LRU.prototype.get = function (key) { - const entry = this._map[key]; - if (util.hasOwn(this._map, key)) { - // Put the latest used entry in the tail - if (entry !== this._list.tail) { + /** + * Set cache max size + * @param size + */ + setMaxSize(size: number) { + this._maxSize = size; + } + + /** + * Put a value and return removed. + * @param key + * @param value + */ + put(key: string, value: T) { + if (!util.hasOwn(this._map, key)) { + const len = this._list.length(); + let removed; + if (len >= this._maxSize && len > 0) { + // Remove the least recently used + const leastUsedEntry = this._list.head as LRUEntry; + if (leastUsedEntry) { + removed = leastUsedEntry.value; + this._list.remove(leastUsedEntry); + delete this._map[leastUsedEntry.key]; + } + } + + const entry = this._list.insert(value) as LRUEntry; + entry.key = key; + this._map[key] = entry; + return removed; + } + } + + /** + * @param key + * @return + */ + get(key: string): T | undefined { + const entry = this._map[key]; + if (util.hasOwn(this._map, key)) { + // Put the latest used entry in the tail + if (entry !== this._list.tail) { + this._list.remove(entry); + this._list.insertEntry(entry); + } + + return entry.value; + } + } + + /** + * @param key + */ + remove(key: string) { + const entry = this._map[key]; + if (typeof entry !== 'undefined') { + delete this._map[key]; this._list.remove(entry); - this._list.insertEntry(entry); } - - return entry.value; } -}; -/** - * @param {string} key - */ -LRU.prototype.remove = function (key) { - const entry = this._map[key]; - if (typeof entry !== 'undefined') { - delete this._map[key]; - this._list.remove(entry); + /** + * Clear the cache + */ + clear() { + this._list.clear(); + this._map = {}; } -}; - -/** - * Clear the cache - */ -LRU.prototype.clear = function () { - this._list.clear(); - this._map = {}; -}; +} export default LRU; diff --git a/src/core/LinkedList.ts b/src/core/LinkedList.ts index fd7c9ca7..2b5795a6 100644 --- a/src/core/LinkedList.ts +++ b/src/core/LinkedList.ts @@ -1,52 +1,70 @@ -// @ts-nocheck /** * Simple double linked list. Compared with array, it has O(1) remove operation. * @constructor * @alias clay.core.LinkedList */ -const LinkedList = function () { - /** - * @type {clay.core.LinkedList.Entry} - */ - this.head = null; + +export class Entry { + value: T; + next?: Entry; + prev?: Entry; + constructor(val: T) { + /** + * @type {} + */ + this.value = val; + } +} +class LinkedList { + head?: Entry; + tail?: Entry; + + private _length = 0; + constructor() {} /** - * @type {clay.core.LinkedList.Entry} + * Insert a new value at the tail */ - this.tail = null; - - this._length = 0; -}; - -/** - * Insert a new value at the tail - * @param {} val - * @return {clay.core.LinkedList.Entry} - */ -LinkedList.prototype.insert = function (val) { - const entry = new LinkedList.Entry(val); - this.insertEntry(entry); - return entry; -}; - -/** - * Insert a new value at idx - * @param {number} idx - * @param {} val - * @return {clay.core.LinkedList.Entry} - */ -LinkedList.prototype.insertAt = function (idx, val) { - if (idx < 0) { - return; + insert(val: T) { + const entry = new Entry(val); + this.insertEntry(entry); + return entry; } - let next = this.head; - let cursor = 0; - while (next && cursor != idx) { - next = next.next; - cursor++; + + /** + * Insert a new value at idx + * @param idx + * @param val + */ + insertAt(idx: number, val: T) { + if (idx < 0) { + return; + } + let next = this.head; + let cursor = 0; + while (next && cursor != idx) { + next = next.next; + cursor++; + } + if (next) { + const entry = new Entry(val); + const prev = next.prev; + if (!prev) { + //next is head + this.head = entry; + } else { + prev.next = entry; + entry.prev = prev; + } + entry.next = next; + next.prev = entry; + } else { + this.insert(val); + } } - if (next) { - const entry = new LinkedList.Entry(val); + + insertBeforeEntry(val: T, next: Entry) { + const entry = new Entry(val); const prev = next.prev; if (!prev) { //next is head @@ -57,197 +75,155 @@ LinkedList.prototype.insertAt = function (idx, val) { } entry.next = next; next.prev = entry; - } else { - this.insert(val); - } -}; -LinkedList.prototype.insertBeforeEntry = function (val, next) { - const entry = new LinkedList.Entry(val); - const prev = next.prev; - if (!prev) { - //next is head - this.head = entry; - } else { - prev.next = entry; - entry.prev = prev; + this._length++; } - entry.next = next; - next.prev = entry; - this._length++; -}; - -/** - * Insert an entry at the tail - * @param {clay.core.LinkedList.Entry} entry - */ -LinkedList.prototype.insertEntry = function (entry) { - if (!this.head) { - this.head = this.tail = entry; - } else { - this.tail.next = entry; - entry.prev = this.tail; - this.tail = entry; - } - this._length++; -}; - -/** - * Remove entry. - * @param {clay.core.LinkedList.Entry} entry - */ -LinkedList.prototype.remove = function (entry) { - const prev = entry.prev; - const next = entry.next; - if (prev) { - prev.next = next; - } else { - // Is head - this.head = next; - } - if (next) { - next.prev = prev; - } else { - // Is tail - this.tail = prev; - } - entry.next = entry.prev = null; - this._length--; -}; - -/** - * Remove entry at index. - * @param {number} idx - * @return {} - */ -LinkedList.prototype.removeAt = function (idx) { - if (idx < 0) { - return; - } - let curr = this.head; - let cursor = 0; - while (curr && cursor != idx) { - curr = curr.next; - cursor++; - } - if (curr) { - this.remove(curr); - return curr.value; - } -}; -/** - * Get head value - * @return {} - */ -LinkedList.prototype.getHead = function () { - if (this.head) { - return this.head.value; - } -}; -/** - * Get tail value - * @return {} - */ -LinkedList.prototype.getTail = function () { - if (this.tail) { - return this.tail.value; - } -}; -/** - * Get value at idx - * @param {number} idx - * @return {} - */ -LinkedList.prototype.getAt = function (idx) { - if (idx < 0) { - return; - } - let curr = this.head; - let cursor = 0; - while (curr && cursor != idx) { - curr = curr.next; - cursor++; - } - return curr.value; -}; - -/** - * @param {} value - * @return {number} - */ -LinkedList.prototype.indexOf = function (value) { - let curr = this.head; - let cursor = 0; - while (curr) { - if (curr.value === value) { - return cursor; - } - curr = curr.next; - cursor++; - } -}; - -/** - * @return {number} - */ -LinkedList.prototype.length = function () { - return this._length; -}; - -/** - * If list is empty - */ -LinkedList.prototype.isEmpty = function () { - return this._length === 0; -}; - -/** - * @param {Function} cb - * @param {} context - */ -LinkedList.prototype.forEach = function (cb, context) { - let curr = this.head; - let idx = 0; - const haveContext = typeof context != 'undefined'; - while (curr) { - if (haveContext) { - cb.call(context, curr.value, idx); + /** + * Insert an entry at the tail + * @param entry + */ + insertEntry(entry: Entry) { + if (!this.head) { + this.head = this.tail = entry; } else { - cb(curr.value, idx); + this.tail!.next = entry; + entry.prev = this.tail; + this.tail = entry; } - curr = curr.next; - idx++; + this._length++; } -}; - -/** - * Clear the list - */ -LinkedList.prototype.clear = function () { - this.tail = this.head = null; - this._length = 0; -}; - -/** - * @constructor - * @param {} val - */ -LinkedList.Entry = function (val) { - /** - * @type {} - */ - this.value = val; /** - * @type {clay.core.LinkedList.Entry} + * Remove entry. + * @param entry */ - this.next = null; + remove(entry: Entry) { + const prev = entry.prev; + const next = entry.next; + if (prev) { + prev.next = next; + } else { + // Is head + this.head = next; + } + if (next) { + next.prev = prev; + } else { + // Is tail + this.tail = prev; + } + entry.next = entry.prev = undefined; + this._length--; + } /** - * @type {clay.core.LinkedList.Entry} + * Remove entry at index. + * @param idx + * @return */ - this.prev = null; -}; + removeAt(idx: number) { + if (idx < 0) { + return; + } + let curr = this.head; + let cursor = 0; + while (curr && cursor != idx) { + curr = curr.next; + cursor++; + } + if (curr) { + this.remove(curr); + return curr.value; + } + } + /** + * Get head value + * @return {} + */ + getHead() { + if (this.head) { + return this.head.value; + } + } + /** + * Get tail value + * @return {} + */ + getTail() { + if (this.tail) { + return this.tail.value; + } + } + /** + * Get value at idx + * @param idx + * @return + */ + getAt(idx: number): T | undefined { + if (idx < 0) { + return; + } + let curr = this.head; + let cursor = 0; + while (curr && cursor != idx) { + curr = curr.next; + cursor++; + } + return curr && curr.value; + } + + /** + * @param value + */ + indexOf(value: T): number { + let curr = this.head; + let cursor = 0; + while (curr) { + if (curr.value === value) { + return cursor; + } + curr = curr.next; + cursor++; + } + return -1; + } + + /** + * Length of list + */ + length(): number { + return this._length; + } + + /** + * If list is empty + */ + isEmpty() { + return this._length === 0; + } + + /** + * @param cb + * @param context + */ + forEach(cb: (value: T, idx: number) => void) { + let curr = this.head; + let idx = 0; + while (curr) { + cb(curr.value, idx); + curr = curr.next; + idx++; + } + } + + /** + * Clear the list + */ + clear() { + this.tail = this.head = undefined; + this._length = 0; + } +} export default LinkedList; diff --git a/src/core/mixin/notifier.ts b/src/core/Notifier.ts similarity index 78% rename from src/core/mixin/notifier.ts rename to src/core/Notifier.ts index 8eb7a602..e5014800 100644 --- a/src/core/mixin/notifier.ts +++ b/src/core/Notifier.ts @@ -1,28 +1,29 @@ -// @ts-nocheck -import util from '../util'; +import * as util from './util'; -function Handler(action, context) { - this.action = action; - this.context = context; +class Handler { + action: Function; + context: any; + constructor(action: Function, context: any) { + this.action = action; + this.context = context; + } } /** * @mixin * @alias clay.core.mixin.notifier */ -const notifier = { +class Notifier { + private _handlers?: Record; /** * Trigger event * @param {string} name */ - trigger: function (name) { - if (!this.__handlers__) { - return; - } - if (!util.hasOwn(this.__handlers__, name)) { + trigger(name: string) { + if (!util.hasOwn(this._handlers, name)) { return; } - const hdls = this.__handlers__[name]; + const hdls = this._handlers![name]; const l = hdls.length; const args = arguments; let i = -1; @@ -59,7 +60,7 @@ const notifier = { } return; } - }, + } /** * Register event handler * @param {string} name @@ -67,11 +68,11 @@ const notifier = { * @param {Object} [context] * @chainable */ - on: function (name, action, context) { + on(name: string, action: Function, context: any) { if (!name || !action) { return; } - const handlers = this.__handlers__ || (this.__handlers__ = {}); + const handlers = this._handlers || (this._handlers = {}); if (!handlers[name]) { handlers[name] = []; } else { @@ -83,7 +84,7 @@ const notifier = { handlers[name].push(handler); return this; - }, + } /** * Register event, event will only be triggered once and then removed @@ -92,17 +93,17 @@ const notifier = { * @param {Object} [context] * @chainable */ - once: function (name, action, context) { + once(name: string, action: Function, context: any) { if (!name || !action) { return; } const self = this; function wrapper() { self.off(name, wrapper); - action.apply(this, arguments); + action.apply(self, arguments); } return this.on(name, wrapper, context); - }, + } /** * Alias of once('before' + name) @@ -111,13 +112,13 @@ const notifier = { * @param {Object} [context] * @chainable */ - before: function (name, action, context) { + before(name: string, action: Function, context: any) { if (!name || !action) { return; } name = 'before' + name; return this.on(name, action, context); - }, + } /** * Alias of once('after' + name) @@ -126,13 +127,13 @@ const notifier = { * @param {Object} [context] * @chainable */ - after: function (name, action, context) { + after(name: string, action: Function, context: any) { if (!name || !action) { return; } name = 'after' + name; return this.on(name, action, context); - }, + } /** * Alias of on('success') @@ -140,9 +141,9 @@ const notifier = { * @param {Object} [context] * @chainable */ - success: function (action, context) { + success(action: Function, context: any) { return this.once('success', action, context); - }, + } /** * Alias of on('error') @@ -150,9 +151,9 @@ const notifier = { * @param {Object} [context] * @chainable */ - error: function (action, context) { + error(action: Function, context: any) { return this.once('error', action, context); - }, + } /** * Remove event listener @@ -160,8 +161,8 @@ const notifier = { * @param {Object} [context] * @chainable */ - off: function (name, action) { - const handlers = this.__handlers__ || (this.__handlers__ = {}); + off(name: string, action: Function) { + const handlers = this._handlers || (this._handlers = {}); if (!action) { handlers[name] = []; @@ -179,7 +180,7 @@ const notifier = { } return this; - }, + } /** * If registered the event handler @@ -187,8 +188,8 @@ const notifier = { * @param {Function} action * @return {boolean} */ - has: function (name, action) { - const handlers = this.__handlers__; + has(name: string, action: Function) { + const handlers = this._handlers; if (!handlers || !handlers[name]) { return false; @@ -200,6 +201,6 @@ const notifier = { } } } -}; +} -export default notifier; +export default Notifier; diff --git a/src/core/color.ts b/src/core/color.ts index ebba43f2..43eed6b1 100644 --- a/src/core/color.ts +++ b/src/core/color.ts @@ -1,12 +1,9 @@ -// @ts-nocheck /** * @namespace clay.core.color */ import LRU from '../core/LRU'; -const colorUtil = {}; - -const kCSSColorTable = { +const kCSSColorTable: Record = { transparent: [0, 0, 0, 0], aliceblue: [240, 248, 255, 1], antiquewhite: [250, 235, 215, 1], @@ -157,24 +154,24 @@ const kCSSColorTable = { yellowgreen: [154, 205, 50, 1] }; -function clampCssByte(i) { +function clampCssByte(i: number) { // Clamp to integer 0 .. 255. i = Math.round(i); // Seems to be what Chrome does (vs truncation). return i < 0 ? 0 : i > 255 ? 255 : i; } -function clampCssAngle(i) { +function clampCssAngle(i: number) { // Clamp to integer 0 .. 360. i = Math.round(i); // Seems to be what Chrome does (vs truncation). return i < 0 ? 0 : i > 360 ? 360 : i; } -function clampCssFloat(f) { +function clampCssFloat(f: number) { // Clamp to float 0.0 .. 1.0. return f < 0 ? 0 : f > 1 ? 1 : f; } -function parseCssInt(str) { +function parseCssInt(str: string) { // int or percentage. if (str.length && str.charAt(str.length - 1) === '%') { return clampCssByte((parseFloat(str) / 100) * 255); @@ -182,15 +179,15 @@ function parseCssInt(str) { return clampCssByte(parseInt(str, 10)); } -function parseCssFloat(str) { +function parseCssFloat(str: string | number) { // float or percentage. - if (str.length && str.charAt(str.length - 1) === '%') { - return clampCssFloat(parseFloat(str) / 100); + if ((str as string).length && (str as string).charAt((str as string).length - 1) === '%') { + return clampCssFloat(parseFloat(str as string) / 100); } - return clampCssFloat(parseFloat(str)); + return clampCssFloat(parseFloat(str as string)); } -function cssHueToRgb(m1, m2, h) { +function cssHueToRgb(m1: number, m2: number, h: number) { if (h < 0) { h += 1; } else if (h > 1) { @@ -209,18 +206,18 @@ function cssHueToRgb(m1, m2, h) { return m1; } -function lerpNumber(a, b, p) { +function lerpNumber(a: number, b: number, p: number) { return a + (b - a) * p; } -function setRgba(out, r, g, b, a) { +function setRgba(out: number[], r: number, g: number, b: number, a: number) { out[0] = r; out[1] = g; out[2] = b; out[3] = a; return out; } -function copyRgba(out, a) { +function copyRgba(out: number[], a: number[]) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; @@ -228,10 +225,10 @@ function copyRgba(out, a) { return out; } -const colorCache = new LRU(20); -let lastRemovedArr = null; +const colorCache = new LRU(20); +let lastRemovedArr: number[] | undefined; -function putToCache(colorStr, rgbaArr) { +function putToCache(colorStr: string, rgbaArr: number[]) { // Reuse removed array if (lastRemovedArr) { copyRgba(lastRemovedArr, rgbaArr); @@ -240,12 +237,11 @@ function putToCache(colorStr, rgbaArr) { } /** - * @name clay.core.color.parse - * @param {string} colorStr - * @param {Array.} out - * @return {Array.} + * @param colorStr + * @param out + * @return */ -colorUtil.parse = function (colorStr, rgbaArr) { +export function parse(colorStr: string, rgbaArr?: number[]) { if (!colorStr) { return; } @@ -301,8 +297,8 @@ colorUtil.parse = function (colorStr, rgbaArr) { const op = str.indexOf('('), ep = str.indexOf(')'); if (op !== -1 && ep + 1 === str.length) { - const fname = str.substr(0, op); - const params = str.substr(op + 1, ep - (op + 1)).split(','); + const fname = str.slice(0, op); + const params = str.slice(op + 1, ep - (op + 1)).split(','); let alpha = 1; // To allow case fallthrough. switch (fname) { case 'rgba': @@ -310,7 +306,7 @@ colorUtil.parse = function (colorStr, rgbaArr) { setRgba(rgbaArr, 0, 0, 0, 1); return; } - alpha = parseCssFloat(params.pop()); // jshint ignore:line + alpha = parseCssFloat(params.pop()!); // jshint ignore:line // Fall through. case 'rgb': if (params.length !== 3) { @@ -331,7 +327,7 @@ colorUtil.parse = function (colorStr, rgbaArr) { setRgba(rgbaArr, 0, 0, 0, 1); return; } - params[3] = parseCssFloat(params[3]); + params[3] = parseCssFloat(params[3]) as any; hsla2rgba(params, rgbaArr); putToCache(colorStr, rgbaArr); return rgbaArr; @@ -350,10 +346,10 @@ colorUtil.parse = function (colorStr, rgbaArr) { setRgba(rgbaArr, 0, 0, 0, 1); return; -}; +} -colorUtil.parseToFloat = function (colorStr, rgbaArr) { - rgbaArr = colorUtil.parse(colorStr, rgbaArr); +export function parseToFloat(colorStr: string, rgbaArr?: number[]) { + rgbaArr = parse(colorStr, rgbaArr); if (!rgbaArr) { return; } @@ -361,20 +357,19 @@ colorUtil.parseToFloat = function (colorStr, rgbaArr) { rgbaArr[1] /= 255; rgbaArr[2] /= 255; return rgbaArr; -}; +} /** - * @name clay.core.color.hsla2rgba - * @param {Array.} hsla - * @param {Array.} rgba - * @return {Array.} rgba + * @param hsla + * @param rgba + * @return rgba */ -function hsla2rgba(hsla, rgba) { - const h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360; // 0 .. 1 +export function hsla2rgba(hsla: (number | string)[], rgba?: number[]) { + const h = (((parseFloat(hsla[0] as any) % 360) + 360) % 360) / 360; // 0 .. 1 // NOTE(deanm): According to the CSS spec s/l should only be // percentages, but we don't bother and let float or percentage. - const s = parseCssFloat(hsla[1]); - const l = parseCssFloat(hsla[2]); + const s = parseCssFloat(hsla[1] as any); + const l = parseCssFloat(hsla[2] as any); const m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; const m1 = l * 2 - m2; @@ -388,18 +383,17 @@ function hsla2rgba(hsla, rgba) { ); if (hsla.length === 4) { - rgba[3] = hsla[3]; + rgba[3] = +hsla[3]; } return rgba; } /** - * @name clay.core.color.rgba2hsla - * @param {Array.} rgba - * @return {Array.} hsla + * @param rgba + * @return hsla */ -function rgba2hsla(rgba) { +export function rgba2hsla(rgba: number[]) { if (!rgba) { return; } @@ -439,16 +433,16 @@ function rgba2hsla(rgba) { H = 2 / 3 + deltaG - deltaR; } - if (H < 0) { + if (H && H < 0) { H += 1; } - if (H > 1) { + if (H && H > 1) { H -= 1; } } - const hsla = [H * 360, S, L]; + const hsla = [(H as number) * 360, S, L]; if (rgba[3] != null) { hsla.push(rgba[3]); @@ -458,13 +452,12 @@ function rgba2hsla(rgba) { } /** - * @name clay.core.color.lift - * @param {string} color - * @param {number} level - * @return {string} + * @param color + * @param level + * @return */ -colorUtil.lift = function (color, level) { - const colorArr = colorUtil.parse(color); +export function lift(color: string, level: number): string | undefined { + const colorArr = parse(color); if (colorArr) { for (let i = 0; i < 3; i++) { if (level < 0) { @@ -473,33 +466,31 @@ colorUtil.lift = function (color, level) { colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0; } } - return colorUtil.stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb'); + return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb'); } -}; +} /** - * @name clay.core.color.toHex - * @param {string} color - * @return {string} + * @param color + * @return */ -colorUtil.toHex = function (color) { - const colorArr = colorUtil.parse(color); +export function toHex(color: string): string | undefined { + const colorArr = parse(color); if (colorArr) { return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + +colorArr[2]) .toString(16) .slice(1); } -}; +} /** * Map value to color. Faster than lerp methods because color is represented by rgba array. - * @name clay.core.color - * @param {number} normalizedValue A float between 0 and 1. - * @param {Array.>} colors List of rgba color array - * @param {Array.} [out] Mapped gba color array - * @return {Array.} will be null/undefined if input illegal. + * @param normalizedValue A float between 0 and 1. + * @param colors List of rgba color array + * @param out Mapped gba color array + * @return will be null/undefined if input illegal. */ -colorUtil.fastLerp = function (normalizedValue, colors, out) { +export function fastLerp(normalizedValue: number, colors: number[][], out?: number[]) { if (!(colors && colors.length) || !(normalizedValue >= 0 && normalizedValue <= 1)) { return; } @@ -518,9 +509,7 @@ colorUtil.fastLerp = function (normalizedValue, colors, out) { out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)); return out; -}; - -colorUtil.fastMapToColor = colorUtil.fastLerp; +} /** * @param {number} normalizedValue A float between 0 and 1. @@ -529,7 +518,7 @@ colorUtil.fastMapToColor = colorUtil.fastLerp; * @return {(string|Object)} Result color. If fullOutput, * return {color: ..., leftIndex: ..., rightIndex: ..., value: ...}, */ -colorUtil.lerp = function (normalizedValue, colors, fullOutput) { +export function lerp(normalizedValue: number, colors: string[]) { if (!(colors && colors.length) || !(normalizedValue >= 0 && normalizedValue <= 1)) { return; } @@ -537,11 +526,14 @@ colorUtil.lerp = function (normalizedValue, colors, fullOutput) { const value = normalizedValue * (colors.length - 1); const leftIndex = Math.floor(value); const rightIndex = Math.ceil(value); - const leftColor = colorUtil.parse(colors[leftIndex]); - const rightColor = colorUtil.parse(colors[rightIndex]); + const leftColor = parse(colors[leftIndex]); + const rightColor = parse(colors[rightIndex]); + if (!leftColor || !rightColor) { + return; + } const dv = value - leftIndex; - const color = colorUtil.stringify( + return stringify( [ clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)), clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)), @@ -550,71 +542,55 @@ colorUtil.lerp = function (normalizedValue, colors, fullOutput) { ], 'rgba' ); - - return fullOutput - ? { - color: color, - leftIndex: leftIndex, - rightIndex: rightIndex, - value: value - } - : color; -}; - -/** - * @deprecated - */ -colorUtil.mapToColor = colorUtil.lerp; +} /** * @name clay.core.color - * @param {string} color - * @param {number=} h 0 ~ 360, ignore when null. - * @param {number=} s 0 ~ 1, ignore when null. - * @param {number=} l 0 ~ 1, ignore when null. - * @return {string} Color string in rgba format. + * @param color + * @param h 0 ~ 360, ignore when null. + * @param s 0 ~ 1, ignore when null. + * @param l 0 ~ 1, ignore when null. + * @return Color string in rgba format. */ -colorUtil.modifyHSL = function (color, h, s, l) { - color = colorUtil.parse(color); +export function modifyHSL(color: string, h: number, s: number, l: number): string | undefined { + let colorArr = parse(color); - if (color) { - color = rgba2hsla(color); - h != null && (color[0] = clampCssAngle(h)); - s != null && (color[1] = parseCssFloat(s)); - l != null && (color[2] = parseCssFloat(l)); + if (colorArr) { + colorArr = rgba2hsla(colorArr)!; + h != null && (colorArr[0] = clampCssAngle(h)); + s != null && (colorArr[1] = parseCssFloat(s)); + l != null && (colorArr[2] = parseCssFloat(l)); - return colorUtil.stringify(hsla2rgba(color), 'rgba'); + return stringify(hsla2rgba(colorArr), 'rgba'); } -}; +} /** * @param {string} color * @param {number=} alpha 0 ~ 1 * @return {string} Color string in rgba format. */ -colorUtil.modifyAlpha = function (color, alpha) { - color = colorUtil.parse(color); +export function modifyAlpha(color: string, alpha: number) { + const colorArr = parse(color); - if (color && alpha != null) { - color[3] = clampCssFloat(alpha); - return colorUtil.stringify(color, 'rgba'); + if (colorArr && alpha != null) { + colorArr[3] = clampCssFloat(alpha); + return stringify(colorArr, 'rgba'); } -}; +} /** - * @param {Array.} arrColor like [12,33,44,0.4] - * @param {string} type 'rgba', 'hsva', ... - * @return {string} Result color. (If input illegal, return undefined). + * @param colorArr like [12,33,44,0.4] + * @param type 'rgba', 'hsva', ... + * @return Result color. (If input illegal, return undefined). */ -colorUtil.stringify = function (arrColor, type) { - if (!arrColor || !arrColor.length) { +export function stringify(colorArr: number[], type: 'rgba' | 'hsva' | 'hsla' | 'rgb') { + if (!colorArr || !colorArr.length) { return; } - let colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2]; + let colorStr = colorArr[0] + ',' + colorArr[1] + ',' + colorArr[2]; if (type === 'rgba' || type === 'hsva' || type === 'hsla') { - colorStr += ',' + arrColor[3]; + colorStr += ',' + colorArr[3]; } return type + '(' + colorStr + ')'; -}; - -export default colorUtil; +} diff --git a/src/core/glenum.ts b/src/core/glenum.ts index 5df7cfa4..8e08edc4 100644 --- a/src/core/glenum.ts +++ b/src/core/glenum.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /** * @namespace clay.core.glenum * @see http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14 @@ -418,4 +417,4 @@ export default { CONTEXT_LOST_WEBGL: 0x9242, UNPACK_COLORSPACE_CONVERSION_WEBGL: 0x9243, BROWSER_DEFAULT_WEBGL: 0x9244 -}; +} as const; diff --git a/src/core/mixin/extend.ts b/src/core/mixin/extend.ts deleted file mode 100644 index 6b8a36bc..00000000 --- a/src/core/mixin/extend.ts +++ /dev/null @@ -1,106 +0,0 @@ -// @ts-nocheck - -import util from '../util'; - -/** - * Extend a sub class from base class - * @param {object|Function} makeDefaultOpt default option of this sub class, method of the sub can use this.xxx to access this option - * @param {Function} [initialize] Initialize after the sub class is instantiated - * @param {Object} [proto] Prototype methods/properties of the sub class - * @memberOf clay.core.mixin.extend - * @return {Function} - */ -function derive(makeDefaultOpt, initialize /*optional*/, proto /*optional*/) { - if (typeof initialize == 'object') { - proto = initialize; - initialize = null; - } - - const _super = this; - - let propList; - if (!(makeDefaultOpt instanceof Function)) { - // Optimize the property iterate if it have been fixed - propList = []; - for (const propName in makeDefaultOpt) { - if (util.hasOwn(makeDefaultOpt, propName)) { - propList.push(propName); - } - } - } - - const sub = function (options) { - // call super constructor - _super.apply(this, arguments); - - if (makeDefaultOpt instanceof Function) { - // Invoke makeDefaultOpt each time if it is a function, So we can make sure each - // property in the object will not be shared by mutiple instances - extend(this, makeDefaultOpt.call(this, options)); - } else { - extendWithPropList(this, makeDefaultOpt, propList); - } - - if (this.constructor === sub) { - // Initialize function will be called in the order of inherit - const initializers = sub.__initializers__; - for (let i = 0; i < initializers.length; i++) { - initializers[i].apply(this, arguments); - } - } - }; - // save super constructor - sub.__super__ = _super; - // Initialize function will be called after all the super constructor is called - if (!_super.__initializers__) { - sub.__initializers__ = []; - } else { - sub.__initializers__ = _super.__initializers__.slice(); - } - if (initialize) { - sub.__initializers__.push(initialize); - } - - const Ctor = function () {}; - Ctor.prototype = _super.prototype; - sub.prototype = new Ctor(); - sub.prototype.constructor = sub; - extend(sub.prototype, proto); - - // extend the derive method as a static method; - sub.extend = _super.extend; - - // DEPCRATED - sub.derive = _super.extend; - - return sub; -} - -function extend(target, source) { - if (!source) { - return; - } - for (const name in source) { - if (util.hasOwn(source, name)) { - target[name] = source[name]; - } - } -} - -function extendWithPropList(target, source, propList) { - for (let i = 0; i < propList.length; i++) { - const propName = propList[i]; - target[propName] = source[propName]; - } -} - -/** - * @alias clay.core.mixin.extend - * @mixin - */ -export default { - extend: derive, - - // DEPCRATED - derive: derive -}; diff --git a/src/core/request.ts b/src/core/request.ts index 81f5adec..f88ab641 100644 --- a/src/core/request.ts +++ b/src/core/request.ts @@ -1,5 +1,10 @@ -// @ts-nocheck -function get(options) { +function get(options: { + url: string; + responseType?: XMLHttpRequest['responseType']; + onprogress?: (percent: number, loaded: number, total: number) => void; + onload?: (data: any) => void; + onerror?: () => void; +}) { /* global XMLHttpRequest */ const xhr = new XMLHttpRequest(); @@ -10,18 +15,19 @@ function get(options) { // arraybuffer, blob, document, json, text xhr.responseType = options.responseType || 'text'; - if (options.onprogress) { + const onprogress = options.onprogress; + if (onprogress) { //https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest xhr.onprogress = function (e) { if (e.lengthComputable) { const percent = e.loaded / e.total; - options.onprogress(percent, e.loaded, e.total); + onprogress(percent, e.loaded, e.total); } else { - options.onprogress(null); + onprogress(0, 0, 0); } }; } - xhr.onload = function (e) { + xhr.onload = function () { if (xhr.status >= 400) { options.onerror && options.onerror(); } else { @@ -34,6 +40,4 @@ function get(options) { xhr.send(null); } -export default { - get: get -}; +export { get }; diff --git a/src/core/util.ts b/src/core/util.ts index b92f152a..3d4ae4d1 100644 --- a/src/core/util.ts +++ b/src/core/util.ts @@ -1,202 +1,129 @@ -// @ts-nocheck let guid = 0; const ArrayProto = Array.prototype; const nativeForEach = ArrayProto.forEach; /** - * Util functions - * @namespace clay.core.util + * Generate GUID + * @return {number} + * @memberOf clay.core.util */ -const util = { - /** - * Generate GUID - * @return {number} - * @memberOf clay.core.util - */ - genGUID: function () { - return ++guid; - }, - /** - * Relative path to absolute path - * @param {string} path - * @param {string} basePath - * @return {string} - * @memberOf clay.core.util - */ - relative2absolute: function (path, basePath) { - if (!basePath || path.match(/^\//)) { - return path; - } - const pathParts = path.split('/'); - const basePathParts = basePath.split('/'); +export function genGUID(): number { + return ++guid; +} +/** + * Relative path to absolute path + * @param {string} path + * @param {string} basePath + * @return {string} + * @memberOf clay.core.util + */ +export function relative2absolute(path: string, basePath: string) { + if (!basePath || path.match(/^\//)) { + return path; + } + const pathParts = path.split('/'); + const basePathParts = basePath.split('/'); - let item = pathParts[0]; - while (item === '.' || item === '..') { - if (item === '..') { - basePathParts.pop(); - } - pathParts.shift(); - item = pathParts[0]; + let item = pathParts[0]; + while (item === '.' || item === '..') { + if (item === '..') { + basePathParts.pop(); } - return basePathParts.join('/') + '/' + pathParts.join('/'); - }, + pathParts.shift(); + item = pathParts[0]; + } + return basePathParts.join('/') + '/' + pathParts.join('/'); +} - /** - * Extend target with source - * @param {Object} target - * @param {Object} source - * @return {Object} - * @memberOf clay.core.util - */ - extend: function (target, source) { - if (source) { - for (const name in source) { - if (util.hasOwn(source, name)) { - target[name] = source[name]; - } - } - } - return target; - }, - - /** - * Extend properties to target if not exist. - * @param {Object} target - * @param {Object} source - * @return {Object} - * @memberOf clay.core.util - */ - defaults: function (target, source) { - if (source) { - for (const propName in source) { - if (target[propName] === undefined) { - target[propName] = source[propName]; - } - } - } - return target; - }, - /** - * Extend properties with a given property list to avoid for..in.. iteration. - * @param {Object} target - * @param {Object} source - * @param {Array.} propList - * @return {Object} - * @memberOf clay.core.util - */ - extendWithPropList: function (target, source, propList) { - if (source) { - for (let i = 0; i < propList.length; i++) { - const propName = propList[i]; +/** + * Extend properties to target if not exist. + * @param {Object} target + * @param {Object} source + * @return {Object} + * @memberOf clay.core.util + */ +export function defaults(target: any, source: any) { + if (source) { + for (const propName in source) { + if (target[propName] === undefined) { target[propName] = source[propName]; } } - return target; - }, - /** - * Extend properties to target if not exist. With a given property list avoid for..in.. iteration. - * @param {Object} target - * @param {Object} source - * @param {Array.} propList - * @return {Object} - * @memberOf clay.core.util - */ - defaultsWithPropList: function (target, source, propList) { - if (source) { - for (let i = 0; i < propList.length; i++) { - const propName = propList[i]; - if (target[propName] == null) { - target[propName] = source[propName]; - } - } - } - return target; - }, - /** - * @param {Object|Array} obj - * @param {Function} iterator - * @param {Object} [context] - * @memberOf clay.core.util - */ - each: function (obj, iterator, context) { - if (!(obj && iterator)) { - return; - } - if (obj.forEach && obj.forEach === nativeForEach) { - obj.forEach(iterator, context); - } else if (obj.length === +obj.length) { - for (let i = 0, len = obj.length; i < len; i++) { - iterator.call(context, obj[i], i, obj); - } - } else { - for (const key in obj) { - if (util.hasOwn(obj, key)) { - iterator.call(context, obj[key], key, obj); - } - } - } - }, - - /** - * Is object - * @param {} obj - * @return {boolean} - * @memberOf clay.core.util - */ - isObject: function (obj) { - return obj === Object(obj); - }, - - /** - * Is array ? - * @param {} obj - * @return {boolean} - * @memberOf clay.core.util - */ - isArray: function (obj) { - return Array.isArray(obj); - }, - - /** - * Is array like, which have a length property - * @param {} obj - * @return {boolean} - * @memberOf clay.core.util - */ - isArrayLike: function (obj) { - if (!obj) { - return false; - } else { - return obj.length === +obj.length; - } - }, - - /** - * @param {} obj - * @return {} - * @memberOf clay.core.util - */ - clone: function (obj) { - if (!util.isObject(obj)) { - return obj; - } else if (util.isArray(obj)) { - return obj.slice(); - } else if (util.isArrayLike(obj)) { - // is typed array - const ret = new obj.constructor(obj.length); - for (let i = 0; i < obj.length; i++) { - ret[i] = obj[i]; - } - return ret; - } else { - return util.extend({}, obj); - } - }, - - hasOwn: function (obj, key) { - return obj != null && Object.prototype.hasOwnProperty.call(obj, key); } -}; + return target; +} +/** + * @param {Object|Array} obj + * @param {Function} iterator + * @param {Object} [context] + * @deprecated + */ +export function each(obj: any, iterator: Function, context: any) { + if (!(obj && iterator)) { + return; + } + if (obj.forEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (let i = 0, len = obj.length; i < len; i++) { + iterator.call(context, obj[i], i, obj); + } + } else { + for (const key in obj) { + if (hasOwn(obj, key)) { + iterator.call(context, obj[key], key, obj); + } + } + } +} -export default util; +/** + * Is object + * @param {} obj + * @return {boolean} + * @memberOf clay.core.util + */ +export function isObject(obj: any) { + return obj === Object(obj); +} + +/** + * Is array like, which have a length property + * @param {} obj + * @return {boolean} + * @memberOf clay.core.util + */ +export function isArrayLike(obj: any): obj is ArrayLike { + if (!obj) { + return false; + } else { + return obj.length === +obj.length; + } +} + +/** + * @param {} obj + * @return {} + * @memberOf clay.core.util + */ +export function clone(obj: T): T { + if (!isObject(obj)) { + return obj; + } else if (Array.isArray(obj)) { + return obj.slice() as unknown as T; + } else if (isArrayLike(obj)) { + // is typed array + const ret = new (obj as any).constructor(obj.length); + for (let i = 0; i < obj.length; i++) { + ret[i] = obj[i]; + } + return ret; + } else { + return Object.assign({}, obj); + } +} + +export function hasOwn(obj: any, key: string) { + return obj != null && Object.prototype.hasOwnProperty.call(obj, key); +} diff --git a/src/core/vendor.ts b/src/core/vendor.ts index f71c6075..d82c5177 100644 --- a/src/core/vendor.ts +++ b/src/core/vendor.ts @@ -1,9 +1,20 @@ -// @ts-nocheck -import request from './request'; +import { get } from './request'; -let supportWebGL; +let supportWebGL: boolean; -const vendor = {}; +interface Vendor { + supportWebGL: () => boolean; + requestAnimationFrame: (cb: () => void) => void; + /* global HTMLCanvasElement HTMLImageElement */ + createCanvas: () => HTMLCanvasElement; + createImage: () => HTMLImageElement; + request: { + get: typeof get; + }; + addEventListener: (dom: any, type: string, func: Function, useCapture?: boolean) => void; + removeEventListener: (dom: any, type: string, func: Function) => void; +} +const vendor = {} as Vendor; /** * If support WebGL @@ -25,21 +36,7 @@ vendor.supportWebGL = function () { return supportWebGL; }; -vendor.Int8Array = typeof Int8Array === 'undefined' ? Array : Int8Array; - -vendor.Uint8Array = typeof Uint8Array === 'undefined' ? Array : Uint8Array; - -vendor.Uint16Array = typeof Uint16Array === 'undefined' ? Array : Uint16Array; - -vendor.Uint32Array = typeof Uint32Array === 'undefined' ? Array : Uint32Array; - -vendor.Int16Array = typeof Int16Array === 'undefined' ? Array : Int16Array; - -vendor.Float32Array = typeof Float32Array === 'undefined' ? Array : Float32Array; - -vendor.Float64Array = typeof Float64Array === 'undefined' ? Array : Float64Array; - -let g = {}; +let g: any; if (typeof window !== 'undefined') { g = window; } else if (typeof global !== 'undefined') { @@ -49,10 +46,7 @@ if (typeof window !== 'undefined') { vendor.requestAnimationFrame = g.requestAnimationFrame || - g.msRequestAnimationFrame || - g.mozRequestAnimationFrame || - g.webkitRequestAnimationFrame || - function (func) { + function (func: () => void) { setTimeout(func, 16); }; @@ -65,7 +59,7 @@ vendor.createImage = function () { }; vendor.request = { - get: request.get + get }; vendor.addEventListener = function (dom, type, func, useCapture) { diff --git a/src/createCompositor.ts b/src/createCompositor.ts index c2841506..3bcb0a71 100644 --- a/src/createCompositor.ts +++ b/src/createCompositor.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import util from './core/util'; +import * as util from './core/util'; import Compositor from './compositor/Compositor'; import CompoSceneNode from './compositor/SceneNode'; import CompoTextureNode from './compositor/TextureNode'; diff --git a/src/deferred/Renderer.ts b/src/deferred/Renderer.ts index 8ae08cbf..3557d212 100644 --- a/src/deferred/Renderer.ts +++ b/src/deferred/Renderer.ts @@ -17,7 +17,7 @@ import Vector3 from '../math/Vector3'; import GBuffer from './GBuffer'; import prezGlsl from '../shader/source/prez.glsl.js'; -import utilGlsl from '../shader/source/util.glsl.js'; +import * as utilGlsl from '../shader/source/util.glsl.js'; import lightvolumeGlsl from '../shader/source/deferred/lightvolume.glsl.js'; // Light shaders diff --git a/src/geometry/Cube.ts b/src/geometry/Cube.ts index 22a05549..de42cc2c 100644 --- a/src/geometry/Cube.ts +++ b/src/geometry/Cube.ts @@ -66,7 +66,7 @@ const Cube = Geometry.extend( for (let k = 0; k < attrList.length; k++) { this.attributes[attrList[k]].init(vertexNumber); } - this.indices = new vendor.Uint16Array(faceNumber); + this.indices = new Uint16Array(faceNumber); let faceOffset = 0; let vertexOffset = 0; for (const pos in planes) { diff --git a/src/gpu/GLProgram.ts b/src/gpu/GLProgram.ts index 533c7830..12e4b08b 100644 --- a/src/gpu/GLProgram.ts +++ b/src/gpu/GLProgram.ts @@ -29,7 +29,7 @@ function checkShaderErrorMsg(_gl, shader, shaderString) { } } -const tmpFloat32Array16 = new vendor.Float32Array(16); +const tmpFloat32Array16 = new Float32Array(16); const GLProgram = Base.extend( { @@ -163,7 +163,7 @@ const GLProgram = Base.extend( case 'm4v': // Raw value if (Array.isArray(value) && Array.isArray(value[0])) { - const array = new vendor.Float32Array(value.length * 16); + const array = new Float32Array(value.length * 16); let cursor = 0; for (let i = 0; i < value.length; i++) { const item = value[i]; diff --git a/src/light/AmbientSH.ts b/src/light/AmbientSH.ts index e4f4f383..7984483b 100644 --- a/src/light/AmbientSH.ts +++ b/src/light/AmbientSH.ts @@ -1,6 +1,5 @@ // @ts-nocheck import Light from '../Light'; -import vendor from '../core/vendor'; /** * Spherical Harmonic Ambient Light @@ -19,7 +18,7 @@ const AmbientSHLight = Light.extend( coefficients: [] }, function () { - this._coefficientsTmpArr = new vendor.Float32Array(9 * 3); + this._coefficientsTmpArr = new Float32Array(9 * 3); }, { type: 'AMBIENT_SH_LIGHT', diff --git a/src/loader/GLTF.ts b/src/loader/GLTF.ts index e7444560..07c9017b 100644 --- a/src/loader/GLTF.ts +++ b/src/loader/GLTF.ts @@ -6,7 +6,7 @@ * TODO Morph targets */ import Base from '../core/Base'; -import util from '../core/util'; +import * as util from '../core/util'; import vendor from '../core/vendor'; import Scene from '../Scene'; @@ -45,12 +45,12 @@ const semanticAttributeMap = { }; const ARRAY_CTOR_MAP = { - 5120: vendor.Int8Array, - 5121: vendor.Uint8Array, - 5122: vendor.Int16Array, - 5123: vendor.Uint16Array, - 5125: vendor.Uint32Array, - 5126: vendor.Float32Array + 5120: Int8Array, + 5121: Uint8Array, + 5122: Int16Array, + 5123: Uint16Array, + 5125: Uint32Array, + 5126: Float32Array }; const SIZE_MAP = { SCALAR: 1, @@ -67,7 +67,7 @@ function getAccessorData(json, lib, accessorIdx, isIndices) { const buffer = lib.bufferViews[accessorInfo.bufferView]; const byteOffset = accessorInfo.byteOffset || 0; - const ArrayCtor = ARRAY_CTOR_MAP[accessorInfo.componentType] || vendor.Float32Array; + const ArrayCtor = ARRAY_CTOR_MAP[accessorInfo.componentType] || Float32Array; let size = SIZE_MAP[accessorInfo.type]; if (size == null && isIndices) { @@ -79,7 +79,7 @@ function getAccessorData(json, lib, accessorIdx, isIndices) { // eslint-disable-next-line accessorInfo.extensions && accessorInfo.extensions['WEB3D_quantized_attributes']; if (quantizeExtension) { - const decodedArr = new vendor.Float32Array(size * accessorInfo.count); + const decodedArr = new Float32Array(size * accessorInfo.count); const decodeMatrix = quantizeExtension.decodeMatrix; const decodeOffset = []; const decodeScale = []; @@ -540,7 +540,7 @@ const GLTFLoader = Base.extend( const offset = IBMInfo.byteOffset || 0; const size = IBMInfo.count * 16; - const array = new vendor.Float32Array(buffer, offset, size); + const array = new Float32Array(buffer, offset, size); skeleton.setJointMatricesArray(array); } else { @@ -812,7 +812,7 @@ const GLTFLoader = Base.extend( } if (isStandardMaterial) { material = new StandardMaterial( - util.extend( + Object.assign( { name: materialInfo.name, alphaTest: alphaTest, @@ -1000,7 +1000,7 @@ const GLTFLoader = Base.extend( let attributeArray = getAccessorData(json, lib, accessorIdx); // WebGL attribute buffer not support uint32. // Direct use Float32Array may also have issue. - if (attributeArray instanceof vendor.Uint32Array) { + if (attributeArray instanceof Uint32Array) { attributeArray = new Float32Array(attributeArray); } if (semantic === 'WEIGHTS_0' && size === 4) { @@ -1035,13 +1035,13 @@ const GLTFLoader = Base.extend( } let attributeType = 'float'; - if (attributeArray instanceof vendor.Uint16Array) { + if (attributeArray instanceof Uint16Array) { attributeType = 'ushort'; - } else if (attributeArray instanceof vendor.Int16Array) { + } else if (attributeArray instanceof Int16Array) { attributeType = 'short'; - } else if (attributeArray instanceof vendor.Uint8Array) { + } else if (attributeArray instanceof Uint8Array) { attributeType = 'ubyte'; - } else if (attributeArray instanceof vendor.Int8Array) { + } else if (attributeArray instanceof Int8Array) { attributeType = 'byte'; } geometry.attributes[attributeName].type = attributeType; @@ -1062,14 +1062,11 @@ const GLTFLoader = Base.extend( // Parse indices if (primitiveInfo.indices != null) { geometry.indices = getAccessorData(json, lib, primitiveInfo.indices, true); - if ( - geometry.vertexCount <= 0xffff && - geometry.indices instanceof vendor.Uint32Array - ) { - geometry.indices = new vendor.Uint16Array(geometry.indices); + if (geometry.vertexCount <= 0xffff && geometry.indices instanceof Uint32Array) { + geometry.indices = new Uint16Array(geometry.indices); } - if (geometry.indices instanceof vendor.Uint8Array) { - geometry.indices = new vendor.Uint16Array(geometry.indices); + if (geometry.indices instanceof Uint8Array) { + geometry.indices = new Uint16Array(geometry.indices); } } diff --git a/src/plugin/GestureMgr.ts b/src/plugin/GestureMgr.ts index 9a3b418d..ae174ff9 100644 --- a/src/plugin/GestureMgr.ts +++ b/src/plugin/GestureMgr.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import util from '../core/util'; +import * as util from '../core/util'; const GestureMgr = function () { this._track = []; diff --git a/src/shader/builtin.ts b/src/shader/builtin.ts index 736486fb..174dd1ec 100644 --- a/src/shader/builtin.ts +++ b/src/shader/builtin.ts @@ -1,6 +1,6 @@ // @ts-nocheck import lightEssl from './source/header/light'; -import utilEssl from './source/util.glsl.js'; +import * as utilEssl from './source/util.glsl.js'; import basicEssl from './source/basic.glsl.js'; import lambertEssl from './source/lambert.glsl.js'; diff --git a/src/shader/source/util.glsl b/src/shader/source/util.glsl index 4f771527..a79d6d8b 100644 --- a/src/shader/source/util.glsl +++ b/src/shader/source/util.glsl @@ -55,7 +55,7 @@ float edgeFactor(float width) // Pack depth // !!!! Float value can only be [0.0 - 1.0) @export clay.util.encode_float -vec4 encodeFloat(let in float depth) +vec4 encodeFloat(const in float depth) { // const float PackUpscale = 256. / 255.; // fraction -> 0..1 (including 1) // const vec3 PackFactors = vec3(256. * 256. * 256., 256. * 256., 256.); @@ -75,7 +75,7 @@ vec4 encodeFloat(let in float depth) @end @export clay.util.decode_float -float decodeFloat(let in vec4 color) +float decodeFloat(const in vec4 color) { // const float UnpackDownscale = 255. / 256.; // 0..1 -> fraction (excluding 1) // const vec3 PackFactors = vec3(256. * 256. * 256., 256. * 256., 256.); @@ -252,7 +252,7 @@ vec3 parallaxCorrect(in vec3 dir, in vec3 pos, in vec3 boxMin, in vec3 boxMax) { @export clay.util.clamp_sample // Sample with stereo clamp -vec4 clampSample(let in sampler2D texture, let in vec2 coord) +vec4 clampSample(const in sampler2D texture, const in vec2 coord) { #ifdef STEREO // Left is 0.0 - 0.5, Right is 0.5 - 1.0, avoid leaking diff --git a/src/shader/source/util.glsl.ts b/src/shader/source/util.glsl.ts index 42a112d3..21a2e0d8 100644 --- a/src/shader/source/util.glsl.ts +++ b/src/shader/source/util.glsl.ts @@ -1 +1 @@ -export default "\n@export clay.util.rand\nhighp float rand(vec2 uv) {\n const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n highp float dt = dot(uv.xy, vec2(a,b)), sn = mod(dt, 3.141592653589793);\n return fract(sin(sn) * c);\n}\n@end\n@export clay.util.calculate_attenuation\nuniform float attenuationFactor : 5.0;\nfloat lightAttenuation(float dist, float range)\n{\n float attenuation = 1.0;\n attenuation = dist*dist/(range*range+1.0);\n float att_s = attenuationFactor;\n attenuation = 1.0/(attenuation*att_s+1.0);\n att_s = 1.0/(att_s+1.0);\n attenuation = attenuation - att_s;\n attenuation /= 1.0 - att_s;\n return clamp(attenuation, 0.0, 1.0);\n}\n@end\n@export clay.util.edge_factor\n#ifdef SUPPORT_STANDARD_DERIVATIVES\nfloat edgeFactor(float width)\n{\n vec3 d = fwidth(v_Barycentric);\n vec3 a3 = smoothstep(vec3(0.0), d * width, v_Barycentric);\n return min(min(a3.x, a3.y), a3.z);\n}\n#else\nfloat edgeFactor(float width)\n{\n return 1.0;\n}\n#endif\n@end\n@export clay.util.encode_float\nvec4 encodeFloat(let in float depth)\n{\n const vec4 bitShifts = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);\n const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);\n vec4 res = fract(depth * bitShifts);\n res -= res.xxyz * bit_mask;\n return res;\n}\n@end\n@export clay.util.decode_float\nfloat decodeFloat(let in vec4 color)\n{\n const vec4 bitShifts = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);\n return dot(color, bitShifts);\n}\n@end\n@export clay.util.float\n@import clay.util.encode_float\n@import clay.util.decode_float\n@end\n@export clay.util.rgbm_decode\nvec3 RGBMDecode(vec4 rgbm, float range) {\n return range * rgbm.rgb * rgbm.a;\n}\n@end\n@export clay.util.rgbm_encode\nvec4 RGBMEncode(vec3 color, float range) {\n if (dot(color, color) == 0.0) {\n return vec4(0.0);\n }\n vec4 rgbm;\n color /= range;\n rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0);\n rgbm.a = ceil(rgbm.a * 255.0) / 255.0;\n rgbm.rgb = color / rgbm.a;\n return rgbm;\n}\n@end\n@export clay.util.rgbm\n@import clay.util.rgbm_decode\n@import clay.util.rgbm_encode\nvec4 decodeHDR(vec4 color)\n{\n#if defined(RGBM_DECODE) || defined(RGBM)\n return vec4(RGBMDecode(color, 8.12), 1.0);\n#else\n return color;\n#endif\n}\nvec4 encodeHDR(vec4 color)\n{\n#if defined(RGBM_ENCODE) || defined(RGBM)\n return RGBMEncode(color.xyz, 8.12);\n#else\n return color;\n#endif\n}\n@end\n@export clay.util.srgb\nvec4 sRGBToLinear(in vec4 value) {\n return vec4(mix(pow(value.rgb * 0.9478672986 + vec3(0.0521327014), vec3(2.4)), value.rgb * 0.0773993808, vec3(lessThanEqual(value.rgb, vec3(0.04045)))), value.w);\n}\nvec4 linearTosRGB(in vec4 value) {\n return vec4(mix(pow(value.rgb, vec3(0.41666)) * 1.055 - vec3(0.055), value.rgb * 12.92, vec3(lessThanEqual(value.rgb, vec3(0.0031308)))), value.w);\n}\n@end\n@export clay.chunk.skinning_header\n#ifdef SKINNING\nattribute vec3 weight : WEIGHT;\nattribute vec4 joint : JOINT;\n#ifdef USE_SKIN_MATRICES_TEXTURE\nuniform sampler2D skinMatricesTexture : ignore;\nuniform float skinMatricesTextureSize: ignore;\nmat4 getSkinMatrix(sampler2D tex, float idx) {\n float j = idx * 4.0;\n float x = mod(j, skinMatricesTextureSize);\n float y = floor(j / skinMatricesTextureSize) + 0.5;\n vec2 scale = vec2(skinMatricesTextureSize);\n return mat4(\n texture2D(tex, vec2(x + 0.5, y) / scale),\n texture2D(tex, vec2(x + 1.5, y) / scale),\n texture2D(tex, vec2(x + 2.5, y) / scale),\n texture2D(tex, vec2(x + 3.5, y) / scale)\n );\n}\nmat4 getSkinMatrix(float idx) {\n return getSkinMatrix(skinMatricesTexture, idx);\n}\n#else\nuniform mat4 skinMatrix[JOINT_COUNT] : SKIN_MATRIX;\nmat4 getSkinMatrix(float idx) {\n return skinMatrix[int(idx)];\n}\n#endif\n#endif\n@end\n@export clay.chunk.skin_matrix\nmat4 skinMatrixWS = getSkinMatrix(joint.x) * weight.x;\nif (weight.y > 1e-4)\n{\n skinMatrixWS += getSkinMatrix(joint.y) * weight.y;\n}\nif (weight.z > 1e-4)\n{\n skinMatrixWS += getSkinMatrix(joint.z) * weight.z;\n}\nfloat weightW = 1.0-weight.x-weight.y-weight.z;\nif (weightW > 1e-4)\n{\n skinMatrixWS += getSkinMatrix(joint.w) * weightW;\n}\n@end\n@export clay.chunk.instancing_header\n#ifdef INSTANCING\nattribute vec4 instanceMat1;\nattribute vec4 instanceMat2;\nattribute vec4 instanceMat3;\n#endif\n@end\n@export clay.chunk.instancing_matrix\nmat4 instanceMat = mat4(\n vec4(instanceMat1.xyz, 0.0),\n vec4(instanceMat2.xyz, 0.0),\n vec4(instanceMat3.xyz, 0.0),\n vec4(instanceMat1.w, instanceMat2.w, instanceMat3.w, 1.0)\n);\n@end\n@export clay.util.parallax_correct\nvec3 parallaxCorrect(in vec3 dir, in vec3 pos, in vec3 boxMin, in vec3 boxMax) {\n vec3 first = (boxMax - pos) / dir;\n vec3 second = (boxMin - pos) / dir;\n vec3 further = max(first, second);\n float dist = min(further.x, min(further.y, further.z));\n vec3 fixedPos = pos + dir * dist;\n vec3 boxCenter = (boxMax + boxMin) * 0.5;\n return normalize(fixedPos - boxCenter);\n}\n@end\n@export clay.util.clamp_sample\nvec4 clampSample(let in sampler2D texture, let in vec2 coord)\n{\n#ifdef STEREO\n float eye = step(0.5, coord.x) * 0.5;\n vec2 coordClamped = clamp(coord, vec2(eye, 0.0), vec2(0.5 + eye, 1.0));\n#else\n vec2 coordClamped = clamp(coord, vec2(0.0), vec2(1.0));\n#endif\n return texture2D(texture, coordClamped);\n}\n@end\n@export clay.util.ACES\nvec3 ACESToneMapping(vec3 color)\n{\n const float A = 2.51;\n const float B = 0.03;\n const float C = 2.43;\n const float D = 0.59;\n const float E = 0.14;\n return (color * (A * color + B)) / (color * (C * color + D) + E);\n}\n@end\n@export clay.util.logdepth_vertex_header\n#ifdef LOG_DEPTH\n#ifdef SUPPORT_FRAG_DEPTH\nvarying float v_FragDepth;\n#else\nuniform float logDepthBufFC: LOG_DEPTH_BUFFER_FC;\n#endif\n#endif\n@end\n@export clay.util.logdepth_vertex_main\n#ifdef LOG_DEPTH\n #ifdef SUPPORT_FRAG_DEPTH\n v_FragDepth = 1.0 + gl_Position.w;\n #else\n gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * logDepthBufFC - 1.0;\n gl_Position.z *= gl_Position.w;\n #endif\n#endif\n@end\n@export clay.util.logdepth_fragment_header\n#if defined(LOG_DEPTH) && defined(SUPPORT_FRAG_DEPTH)\nvarying float v_FragDepth;\nuniform float logDepthBufFC : LOG_DEPTH_BUFFER_FC;\n#endif\n@end\n@export clay.util.logdepth_fragment_main\n#if defined(LOG_DEPTH) && defined(SUPPORT_FRAG_DEPTH)\n gl_FragDepthEXT = log2(v_FragDepth) * logDepthBufFC * 0.5;\n#endif\n@end\n"; +export default '\n@export clay.util.rand\nhighp float rand(vec2 uv) {\n const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n highp float dt = dot(uv.xy, vec2(a,b)), sn = mod(dt, 3.141592653589793);\n return fract(sin(sn) * c);\n}\n@end\n@export clay.util.calculate_attenuation\nuniform float attenuationFactor : 5.0;\nfloat lightAttenuation(float dist, float range)\n{\n float attenuation = 1.0;\n attenuation = dist*dist/(range*range+1.0);\n float att_s = attenuationFactor;\n attenuation = 1.0/(attenuation*att_s+1.0);\n att_s = 1.0/(att_s+1.0);\n attenuation = attenuation - att_s;\n attenuation /= 1.0 - att_s;\n return clamp(attenuation, 0.0, 1.0);\n}\n@end\n@export clay.util.edge_factor\n#ifdef SUPPORT_STANDARD_DERIVATIVES\nfloat edgeFactor(float width)\n{\n vec3 d = fwidth(v_Barycentric);\n vec3 a3 = smoothstep(vec3(0.0), d * width, v_Barycentric);\n return min(min(a3.x, a3.y), a3.z);\n}\n#else\nfloat edgeFactor(float width)\n{\n return 1.0;\n}\n#endif\n@end\n@export clay.util.encode_float\nvec4 encodeFloat(const in float depth)\n{\n const vec4 bitShifts = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);\n const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);\n vec4 res = fract(depth * bitShifts);\n res -= res.xxyz * bit_mask;\n return res;\n}\n@end\n@export clay.util.decode_float\nfloat decodeFloat(const in vec4 color)\n{\n const vec4 bitShifts = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);\n return dot(color, bitShifts);\n}\n@end\n@export clay.util.float\n@import clay.util.encode_float\n@import clay.util.decode_float\n@end\n@export clay.util.rgbm_decode\nvec3 RGBMDecode(vec4 rgbm, float range) {\n return range * rgbm.rgb * rgbm.a;\n}\n@end\n@export clay.util.rgbm_encode\nvec4 RGBMEncode(vec3 color, float range) {\n if (dot(color, color) == 0.0) {\n return vec4(0.0);\n }\n vec4 rgbm;\n color /= range;\n rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0);\n rgbm.a = ceil(rgbm.a * 255.0) / 255.0;\n rgbm.rgb = color / rgbm.a;\n return rgbm;\n}\n@end\n@export clay.util.rgbm\n@import clay.util.rgbm_decode\n@import clay.util.rgbm_encode\nvec4 decodeHDR(vec4 color)\n{\n#if defined(RGBM_DECODE) || defined(RGBM)\n return vec4(RGBMDecode(color, 8.12), 1.0);\n#else\n return color;\n#endif\n}\nvec4 encodeHDR(vec4 color)\n{\n#if defined(RGBM_ENCODE) || defined(RGBM)\n return RGBMEncode(color.xyz, 8.12);\n#else\n return color;\n#endif\n}\n@end\n@export clay.util.srgb\nvec4 sRGBToLinear(in vec4 value) {\n return vec4(mix(pow(value.rgb * 0.9478672986 + vec3(0.0521327014), vec3(2.4)), value.rgb * 0.0773993808, vec3(lessThanEqual(value.rgb, vec3(0.04045)))), value.w);\n}\nvec4 linearTosRGB(in vec4 value) {\n return vec4(mix(pow(value.rgb, vec3(0.41666)) * 1.055 - vec3(0.055), value.rgb * 12.92, vec3(lessThanEqual(value.rgb, vec3(0.0031308)))), value.w);\n}\n@end\n@export clay.chunk.skinning_header\n#ifdef SKINNING\nattribute vec3 weight : WEIGHT;\nattribute vec4 joint : JOINT;\n#ifdef USE_SKIN_MATRICES_TEXTURE\nuniform sampler2D skinMatricesTexture : ignore;\nuniform float skinMatricesTextureSize: ignore;\nmat4 getSkinMatrix(sampler2D tex, float idx) {\n float j = idx * 4.0;\n float x = mod(j, skinMatricesTextureSize);\n float y = floor(j / skinMatricesTextureSize) + 0.5;\n vec2 scale = vec2(skinMatricesTextureSize);\n return mat4(\n texture2D(tex, vec2(x + 0.5, y) / scale),\n texture2D(tex, vec2(x + 1.5, y) / scale),\n texture2D(tex, vec2(x + 2.5, y) / scale),\n texture2D(tex, vec2(x + 3.5, y) / scale)\n );\n}\nmat4 getSkinMatrix(float idx) {\n return getSkinMatrix(skinMatricesTexture, idx);\n}\n#else\nuniform mat4 skinMatrix[JOINT_COUNT] : SKIN_MATRIX;\nmat4 getSkinMatrix(float idx) {\n return skinMatrix[int(idx)];\n}\n#endif\n#endif\n@end\n@export clay.chunk.skin_matrix\nmat4 skinMatrixWS = getSkinMatrix(joint.x) * weight.x;\nif (weight.y > 1e-4)\n{\n skinMatrixWS += getSkinMatrix(joint.y) * weight.y;\n}\nif (weight.z > 1e-4)\n{\n skinMatrixWS += getSkinMatrix(joint.z) * weight.z;\n}\nfloat weightW = 1.0-weight.x-weight.y-weight.z;\nif (weightW > 1e-4)\n{\n skinMatrixWS += getSkinMatrix(joint.w) * weightW;\n}\n@end\n@export clay.chunk.instancing_header\n#ifdef INSTANCING\nattribute vec4 instanceMat1;\nattribute vec4 instanceMat2;\nattribute vec4 instanceMat3;\n#endif\n@end\n@export clay.chunk.instancing_matrix\nmat4 instanceMat = mat4(\n vec4(instanceMat1.xyz, 0.0),\n vec4(instanceMat2.xyz, 0.0),\n vec4(instanceMat3.xyz, 0.0),\n vec4(instanceMat1.w, instanceMat2.w, instanceMat3.w, 1.0)\n);\n@end\n@export clay.util.parallax_correct\nvec3 parallaxCorrect(in vec3 dir, in vec3 pos, in vec3 boxMin, in vec3 boxMax) {\n vec3 first = (boxMax - pos) / dir;\n vec3 second = (boxMin - pos) / dir;\n vec3 further = max(first, second);\n float dist = min(further.x, min(further.y, further.z));\n vec3 fixedPos = pos + dir * dist;\n vec3 boxCenter = (boxMax + boxMin) * 0.5;\n return normalize(fixedPos - boxCenter);\n}\n@end\n@export clay.util.clamp_sample\nvec4 clampSample(const in sampler2D texture, const in vec2 coord)\n{\n#ifdef STEREO\n float eye = step(0.5, coord.x) * 0.5;\n vec2 coordClamped = clamp(coord, vec2(eye, 0.0), vec2(0.5 + eye, 1.0));\n#else\n vec2 coordClamped = clamp(coord, vec2(0.0), vec2(1.0));\n#endif\n return texture2D(texture, coordClamped);\n}\n@end\n@export clay.util.ACES\nvec3 ACESToneMapping(vec3 color)\n{\n const float A = 2.51;\n const float B = 0.03;\n const float C = 2.43;\n const float D = 0.59;\n const float E = 0.14;\n return (color * (A * color + B)) / (color * (C * color + D) + E);\n}\n@end\n@export clay.util.logdepth_vertex_header\n#ifdef LOG_DEPTH\n#ifdef SUPPORT_FRAG_DEPTH\nvarying float v_FragDepth;\n#else\nuniform float logDepthBufFC: LOG_DEPTH_BUFFER_FC;\n#endif\n#endif\n@end\n@export clay.util.logdepth_vertex_main\n#ifdef LOG_DEPTH\n #ifdef SUPPORT_FRAG_DEPTH\n v_FragDepth = 1.0 + gl_Position.w;\n #else\n gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * logDepthBufFC - 1.0;\n gl_Position.z *= gl_Position.w;\n #endif\n#endif\n@end\n@export clay.util.logdepth_fragment_header\n#if defined(LOG_DEPTH) && defined(SUPPORT_FRAG_DEPTH)\nvarying float v_FragDepth;\nuniform float logDepthBufFC : LOG_DEPTH_BUFFER_FC;\n#endif\n@end\n@export clay.util.logdepth_fragment_main\n#if defined(LOG_DEPTH) && defined(SUPPORT_FRAG_DEPTH)\n gl_FragDepthEXT = log2(v_FragDepth) * logDepthBufFC * 0.5;\n#endif\n@end\n'; diff --git a/src/util/sh.ts b/src/util/sh.ts index 1a5d6843..e0d7af09 100644 --- a/src/util/sh.ts +++ b/src/util/sh.ts @@ -35,10 +35,10 @@ function projectEnvironmentMapGPU(renderer, envMap) { framebuffer.bind(renderer); // TODO Only chrome and firefox support Float32Array - const pixels = new vendor.Float32Array(9 * 4); + const pixels = new Float32Array(9 * 4); renderer.gl.readPixels(0, 0, 9, 1, Texture.RGBA, Texture.FLOAT, pixels); - const coeff = new vendor.Float32Array(9 * 3); + const coeff = new Float32Array(9 * 3); for (let i = 0; i < 9; i++) { coeff[i * 3] = pixels[i * 4]; coeff[i * 3 + 1] = pixels[i * 4 + 1]; @@ -88,7 +88,7 @@ const normalTransform = { // Project on cpu. function projectEnvironmentMapCPU(renderer, cubePixels, width, height) { - const coeff = new vendor.Float32Array(9 * 3); + const coeff = new Float32Array(9 * 3); const normal = vec3.create(); const texel = vec3.create(); const fetchNormal = vec3.create(); diff --git a/src/util/transferable.ts b/src/util/transferable.ts index 55a1edb5..eafad30b 100644 --- a/src/util/transferable.ts +++ b/src/util/transferable.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import util from '../core/util'; +import * as util from '../core/util'; import Geometry from '../Geometry'; import BoundingBox from '../math/BoundingBox'; import Vector3 from '../math/Vector3'; @@ -25,7 +25,7 @@ const transferableUtil = { return null; } const data = { - metadata: util.extend({}, META) + metadata: Object.assign({}, META) }; //transferable buffers const buffers = [];