From 9426e5eeeb949662d2d101c0e01422dd4cd30458 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 23 Nov 2020 23:14:39 +0000 Subject: [PATCH] Reduce memory churn (#165) Move frustum culling from rendering to pre-rendering. Use Float32Array for Polygon internals. Reduce pool Vector leaks. --- CHANGELOG.md | 4 + docs/architecture/typed_arrays.md | 3 +- docs/documentation/frustum-culling.md | 17 +- docs/reference/README.md | 1 - docs/reference/classes/frustumculler.md | 10 +- docs/reference/classes/gjkalgorithm.md | 15 + docs/reference/classes/pointer.md | 18 + docs/reference/classes/pointercamerainfo.md | 18 + docs/reference/classes/pointersystem.md | 74 +- docs/reference/classes/polygon.md | 6 +- docs/reference/classes/pooled.md | 4 +- docs/reference/classes/primitivesystem.md | 22 +- docs/reference/classes/renderable.md | 14 +- docs/reference/classes/rendersystem.md | 6 +- docs/reference/classes/spritesystem.md | 22 +- .../classes/testcollisionalgorithm.md | 1 - docs/reference/classes/testpointersystem.md | 64 +- docs/reference/classes/testpooledobject.md | 4 +- docs/reference/classes/testrendersystem.md | 6 +- docs/reference/classes/testwheelsystem.md | 252 ---- docs/reference/classes/textsystem.md | 10 +- docs/reference/classes/vector.md | 9 +- docs/reference/classes/webglsystem.md | 14 +- .../interfaces/icollisionalgorithm.md | 1 - docs/reference/interfaces/ifreeable.md | 2 + docs/reference/interfaces/ipoolable.md | 4 +- docs/reference/interfaces/irenderable.md | 4 +- docs/reference/interfaces/isubscriber.md | 1 - example/animation/src/index.ts | 3 +- example/shooter/src/index.ts | 6 +- package.json | 2 +- src/geometry/vector.ts | 8 +- src/pooling/ipoolable.ts | 2 +- src/pooling/pooled.test.ts | 2 +- src/pooling/pooled.ts | 4 +- src/rendering/renderable.ts | 21 +- src/shape/ishape.ts | 4 - src/shape/polygon.test.ts | 24 +- src/shape/polygon.ts | 241 ++-- .../collision/algorithm/aabb_algorithm.ts | 8 + .../collision/algorithm/gjk_algorithm.ts | 29 +- src/standard/collision/collision_system.ts | 11 +- src/standard/frustum_culler/frustum_culler.ts | 8 +- .../interpolation/interpolation_system.ts | 3 +- src/standard/pointer/pointer.ts | 12 +- src/standard/pointer/pointer_camera_info.ts | 10 +- src/standard/pointer/pointer_system.test.ts | 739 +++++++--- src/standard/pointer/pointer_system.ts | 63 +- .../primitive/primitive_system.test.ts | 249 +++- src/standard/primitive/primitive_system.ts | 129 +- src/standard/render/render_system.test.ts | 36 +- src/standard/render/render_system.ts | 19 +- src/standard/sprite/sprite_system.test.ts | 252 +++- src/standard/sprite/sprite_system.ts | 142 +- src/standard/text/text_system.test.ts | 793 +++++++---- src/standard/text/text_system.ts | 309 ++-- src/standard/webgl/webgl_system.test.ts | 514 +------ src/standard/webgl/webgl_system.ts | 35 +- yarn.lock | 1261 +++++++++-------- 59 files changed, 3233 insertions(+), 2312 deletions(-) delete mode 100644 docs/reference/classes/testwheelsystem.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 61aee6e..452ef75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,10 @@ must be implemented on a per `Component` basis by overriding this function. render logic. - `AABBAlgorithm` more efficient algorithm involving sweeping horizontal then vertical. - `AABB` method `FarthestPointInDirection` faster and using less `Vector` objects. +- Pointer, pointer move, and wheel events synced up and dispatched within the engine update loop. +- `Polygon` uses `Float32Array` internally. +- `Polygon` can now be initialised with a `Float32Array`. +- Frustum culling moved to preprocessing and removed from render pipeline. ## [v0.9.0] - 2020-09-05 ### Added diff --git a/docs/architecture/typed_arrays.md b/docs/architecture/typed_arrays.md index c157f74..b1c8c60 100644 --- a/docs/architecture/typed_arrays.md +++ b/docs/architecture/typed_arrays.md @@ -1,6 +1,6 @@ # Typed Arrays -Key JamJar geometry objects use typed arrays behind the scenes, such as [Vector], [Matrix3D] and [Matrix4D]. +Key JamJar geometry objects use typed arrays behind the scenes, such as [Vector], [Polygon], [Matrix3D] and [Matrix4D]. ## What are typed arrays? @@ -33,6 +33,7 @@ This ultimately doesn't affect the geometry objects, the typed arrays are wrappe by a more intuiative API, rather than direct array access. [Vector]:../../reference/classes/vector +[Polygon]:../../reference/classes/polygon [Matrix3D]:../../reference/classes/matrix3d [Matrix4D]:../../reference/classes/matrix4d [Float32Array]:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32array diff --git a/docs/documentation/frustum-culling.md b/docs/documentation/frustum-culling.md index deac36e..1d225a5 100644 --- a/docs/documentation/frustum-culling.md +++ b/docs/documentation/frustum-culling.md @@ -1,17 +1,14 @@ # Frustum Culling -*Frustum Culling* is the process of eliminating renderables that are outside of -the view that should be rendered. This process occurs with the use of Collision -Algorithms - which are abstracted out and can be swapped in and out for -performance/use cases in the [FrustumCuller]. +*Frustum Culling* is the process of eliminating renderables that are outside of the view that should be rendered. This +process occurs with the use of Collision Algorithms - which are abstracted out and can be swapped in and out for +performance/use cases in the [FrustumCuller]. -The [FrustumCuller] can be customised by providing it with different algorithms -to suit your need. +The [FrustumCuller] can be customised by providing it with different algorithms to suit your need. -The [FrustumCuller] can then be provided to a [RenderSystem] such as -[WebGLSystem] to provide culling logic. +The [FrustumCuller] can then be provided to a *pre-render* [System] such as [SpriteSystem] to provide culling logic. [FrustumCuller]:../../reference/classes/frustumculler -[RenderSystem]:../../reference/classes/rendersystem -[WebGLSystem]:../../reference/classes/webglsystem \ No newline at end of file +[System]:../../reference/classes/system +[SpriteSystem]:../../reference/classes/spritesystem diff --git a/docs/reference/README.md b/docs/reference/README.md index f4b35e1..bb96a11 100644 --- a/docs/reference/README.md +++ b/docs/reference/README.md @@ -113,7 +113,6 @@ * [TestScene](classes/testscene.md) * [TestShader](classes/testshader.md) * [TestSystem](classes/testsystem.md) -* [TestWheelSystem](classes/testwheelsystem.md) * [Text](classes/text.md) * [TextRender](classes/textrender.md) * [TextSystem](classes/textsystem.md) diff --git a/docs/reference/classes/frustumculler.md b/docs/reference/classes/frustumculler.md index 62c4809..db5d75e 100644 --- a/docs/reference/classes/frustumculler.md +++ b/docs/reference/classes/frustumculler.md @@ -20,7 +20,7 @@ colliding) - used in rendering to avoid unneccesary rendering. ### Properties -* [narrowAlgorithm](frustumculler.md#private-narrowalgorithm) +* [collisionAlgorithm](frustumculler.md#private-collisionalgorithm) ### Methods @@ -30,21 +30,21 @@ colliding) - used in rendering to avoid unneccesary rendering. ### constructor -\+ **new FrustumCuller**(`narrowAlgorithm`: [ICollisionAlgorithm](../interfaces/icollisionalgorithm.md)): *[FrustumCuller](frustumculler.md)* +\+ **new FrustumCuller**(`collisionAlgorithm`: [ICollisionAlgorithm](../interfaces/icollisionalgorithm.md)): *[FrustumCuller](frustumculler.md)* **Parameters:** Name | Type | Default | ------ | ------ | ------ | -`narrowAlgorithm` | [ICollisionAlgorithm](../interfaces/icollisionalgorithm.md) | new AABBAlgorithm() | +`collisionAlgorithm` | [ICollisionAlgorithm](../interfaces/icollisionalgorithm.md) | new AABBAlgorithm() | **Returns:** *[FrustumCuller](frustumculler.md)* ## Properties -### `Private` narrowAlgorithm +### `Private` collisionAlgorithm -• **narrowAlgorithm**: *[ICollisionAlgorithm](../interfaces/icollisionalgorithm.md)* +• **collisionAlgorithm**: *[ICollisionAlgorithm](../interfaces/icollisionalgorithm.md)* ## Methods diff --git a/docs/reference/classes/gjkalgorithm.md b/docs/reference/classes/gjkalgorithm.md index cf71b30..32cd17f 100644 --- a/docs/reference/classes/gjkalgorithm.md +++ b/docs/reference/classes/gjkalgorithm.md @@ -18,6 +18,7 @@ algorithm for collision detection. * [CalculateCollisions](gjkalgorithm.md#calculatecollisions) * [calculateDirection](gjkalgorithm.md#private-calculatedirection) +* [freeSimplex](gjkalgorithm.md#private-freesimplex) * [gjk](gjkalgorithm.md#private-gjk) * [support](gjkalgorithm.md#private-support) @@ -53,6 +54,20 @@ Name | Type | ___ +### `Private` freeSimplex + +▸ **freeSimplex**(`simplex`: [Vector](vector.md)[]): *void* + +**Parameters:** + +Name | Type | +------ | ------ | +`simplex` | [Vector](vector.md)[] | + +**Returns:** *void* + +___ + ### `Private` gjk ▸ **gjk**(`a`: [IShape](../interfaces/ishape.md), `b`: [IShape](../interfaces/ishape.md)): *[CollisionInfo](collisioninfo.md) | undefined* diff --git a/docs/reference/classes/pointer.md b/docs/reference/classes/pointer.md index 3e3fc43..5639c3f 100644 --- a/docs/reference/classes/pointer.md +++ b/docs/reference/classes/pointer.md @@ -8,6 +8,10 @@ the element the game is running in. * **Pointer** +## Implements + +* [IFreeable](../interfaces/ifreeable.md) + ## Index ### Constructors @@ -20,6 +24,10 @@ the element the game is running in. * [elementPosition](pointer.md#elementposition) * [event](pointer.md#event) +### Methods + +* [Free](pointer.md#free) + ## Constructors ### constructor @@ -59,3 +67,13 @@ ___ • **event**: *PointerEvent* Standard PointerEvent dispatched from JS. + +## Methods + +### Free + +▸ **Free**(): *void* + +*Implementation of [IFreeable](../interfaces/ifreeable.md)* + +**Returns:** *void* diff --git a/docs/reference/classes/pointercamerainfo.md b/docs/reference/classes/pointercamerainfo.md index 997f853..364da76 100644 --- a/docs/reference/classes/pointercamerainfo.md +++ b/docs/reference/classes/pointercamerainfo.md @@ -7,6 +7,10 @@ PointerCameraInfo pointer information relevant to a camera. * **PointerCameraInfo** +## Implements + +* [IFreeable](../interfaces/ifreeable.md) + ## Index ### Constructors @@ -20,6 +24,10 @@ PointerCameraInfo pointer information relevant to a camera. * [withinBounds](pointercamerainfo.md#withinbounds) * [worldPosition](pointercamerainfo.md#worldposition) +### Methods + +* [Free](pointercamerainfo.md#free) + ## Constructors ### constructor @@ -68,3 +76,13 @@ ___ • **worldPosition**: *[Vector](vector.md)* Position in the world of the pointer using this camera. + +## Methods + +### Free + +▸ **Free**(): *void* + +*Implementation of [IFreeable](../interfaces/ifreeable.md)* + +**Returns:** *void* diff --git a/docs/reference/classes/pointersystem.md b/docs/reference/classes/pointersystem.md index a5e3c9e..d478bfc 100644 --- a/docs/reference/classes/pointersystem.md +++ b/docs/reference/classes/pointersystem.md @@ -11,8 +11,6 @@ PointerSystem handles Pointer (mouse, touch etc.) input events, converting them ↳ [TestPointerSystem](testpointersystem.md) - ↳ [TestWheelSystem](testwheelsystem.md) - ## Implements * [ISubscriber](../interfaces/isubscriber.md) @@ -28,9 +26,12 @@ PointerSystem handles Pointer (mouse, touch etc.) input events, converting them * [entities](pointersystem.md#protected-entities) * [inputElement](pointersystem.md#private-inputelement) * [isFullscreen](pointersystem.md#private-isfullscreen) +* [lastMoveEvent](pointersystem.md#private-lastmoveevent) +* [lastPublishedPointers](pointersystem.md#private-lastpublishedpointers) * [lastWheelEvent](pointersystem.md#private-lastwheelevent) * [lockedPointerPosition](pointersystem.md#private-lockedpointerposition) * [messageBus](pointersystem.md#protected-messagebus) +* [pointerEventsToPublish](pointersystem.md#private-pointereventstopublish) * [scene](pointersystem.md#protected-optional-scene) * [subscriberID](pointersystem.md#subscriberid) * [MESSAGE_DEREGISTER](pointersystem.md#static-message_deregister) @@ -43,7 +44,9 @@ PointerSystem handles Pointer (mouse, touch etc.) input events, converting them * [OnDestroy](pointersystem.md#protected-ondestroy) * [OnMessage](pointersystem.md#onmessage) * [Update](pointersystem.md#update) +* [moveEvent](pointersystem.md#protected-moveevent) * [pointerEvent](pointersystem.md#protected-pointerevent) +* [processPointerEvent](pointersystem.md#private-processpointerevent) * [wheelEvent](pointersystem.md#protected-wheelevent) * [EVALUATOR](pointersystem.md#static-private-evaluator) @@ -51,7 +54,7 @@ PointerSystem handles Pointer (mouse, touch etc.) input events, converting them ### constructor -\+ **new PointerSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `inputElement`: HTMLElement, `scene?`: [IScene](../interfaces/iscene.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number, `isFullscreen`: boolean, `lockedPointerPosition?`: [Vector](vector.md), `lastWheelEvent?`: WheelEvent): *[PointerSystem](pointersystem.md)* +\+ **new PointerSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `inputElement`: HTMLElement, `scene?`: [IScene](../interfaces/iscene.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number, `isFullscreen`: boolean, `lockedPointerPosition?`: [Vector](vector.md), `lastWheelEvent?`: WheelEvent, `lastMoveEvent?`: PointerEvent, `pointersToPublish`: PointerEvent[], `lastPublishedPointers`: [Pointer](pointer.md)[]): *[PointerSystem](pointersystem.md)* *Overrides [System](system.md).[constructor](system.md#constructor)* @@ -67,6 +70,9 @@ Name | Type | Default | `isFullscreen` | boolean | false | `lockedPointerPosition?` | [Vector](vector.md) | - | `lastWheelEvent?` | WheelEvent | - | +`lastMoveEvent?` | PointerEvent | - | +`pointersToPublish` | PointerEvent[] | [] | +`lastPublishedPointers` | [Pointer](pointer.md)[] | [] | **Returns:** *[PointerSystem](pointersystem.md)* @@ -103,12 +109,28 @@ true = in fullscreen, false = not in fullscreen ___ +### `Private` lastMoveEvent + +• **lastMoveEvent**: *PointerEvent | undefined* + +Last pointer move event captured, stored here to throttle a potentially frequently firing event. + +___ + +### `Private` lastPublishedPointers + +• **lastPublishedPointers**: *[Pointer](pointer.md)[]* + +The pointers published in the last update. +Used to free up objects back into pools. + +___ + ### `Private` lastWheelEvent • **lastWheelEvent**: *WheelEvent | undefined* -Last wheel event captured, stored here to throttle a potentially -frequently firing event +Last wheel event captured, stored here to throttle a potentially frequently firing event. ___ @@ -116,8 +138,8 @@ ___ • **lockedPointerPosition**: *[Vector](vector.md) | undefined* -Position of the pointer if it is locked, used with the PointerAPI to -keep track of pointer position using movementX and movementY. +Position of the pointer if it is locked, used with the PointerAPI to keep track of pointer position using +movementX and movementY. If it is undefined there is no pointer lock. ___ @@ -133,6 +155,14 @@ for communicating with other parts of the engine. ___ +### `Private` pointerEventsToPublish + +• **pointerEventsToPublish**: *PointerEvent[]* + +The pointer events recieved since the last update that should be published. + +___ + ### `Protected` `Optional` scene • **scene**? : *[IScene](../interfaces/iscene.md)* @@ -234,10 +264,38 @@ ___ ___ +### `Protected` moveEvent + +▸ **moveEvent**(`event`: PointerEvent): *void* + +**Parameters:** + +Name | Type | +------ | ------ | +`event` | PointerEvent | + +**Returns:** *void* + +___ + ### `Protected` pointerEvent ▸ **pointerEvent**(`event`: PointerEvent): *void* +**Parameters:** + +Name | Type | +------ | ------ | +`event` | PointerEvent | + +**Returns:** *void* + +___ + +### `Private` processPointerEvent + +▸ **processPointerEvent**(`event`: PointerEvent): *[Pointer](pointer.md)* + When a Pointer Event occurs; dispatches the pointer event with extra info through the JamJar messaging system as a Pointer. Adds in useful information, such as pointer position within camera @@ -250,7 +308,7 @@ Name | Type | Description | ------ | ------ | ------ | `event` | PointerEvent | Pointer Event | -**Returns:** *void* +**Returns:** *[Pointer](pointer.md)* ___ diff --git a/docs/reference/classes/polygon.md b/docs/reference/classes/polygon.md index 37a949d..ec287a8 100644 --- a/docs/reference/classes/polygon.md +++ b/docs/reference/classes/polygon.md @@ -42,13 +42,13 @@ Can be used in collision detection and rendering. ### constructor -\+ **new Polygon**(`points`: [Vector](vector.md)[], `wrap`: boolean): *[Polygon](polygon.md)* +\+ **new Polygon**(`points`: [Vector](vector.md)[] | Float32Array, `wrap`: boolean): *[Polygon](polygon.md)* **Parameters:** Name | Type | Default | ------ | ------ | ------ | -`points` | [Vector](vector.md)[] | - | +`points` | [Vector](vector.md)[] | Float32Array | - | `wrap` | boolean | false | **Returns:** *[Polygon](polygon.md)* @@ -57,7 +57,7 @@ Name | Type | Default | ### points -• **points**: *[Vector](vector.md)[]* +• **points**: *Float32Array* ## Methods diff --git a/docs/reference/classes/pooled.md b/docs/reference/classes/pooled.md index 79c95e7..ec8db0b 100644 --- a/docs/reference/classes/pooled.md +++ b/docs/reference/classes/pooled.md @@ -97,7 +97,7 @@ ___ ### `Static` `Protected` new -▸ **new**<**T**>(`poolKey`: string, `type`: object, ...`args`: any): *T* +▸ **new**<**T**>(`poolKey`: string, `type`: object, `args`: any[]): *T* new is used to request a new object from the pool specified, if the pool is unavailable or empty it will use the type to provision a new object through a constructor. @@ -122,7 +122,7 @@ Name | Type | ------ | ------ | `constructor` | | -▪... **args**: *any* +▪ **args**: *any[]* The args to use when creating/recycling the object. diff --git a/docs/reference/classes/primitivesystem.md b/docs/reference/classes/primitivesystem.md index de4cbb1..3acad64 100644 --- a/docs/reference/classes/primitivesystem.md +++ b/docs/reference/classes/primitivesystem.md @@ -23,6 +23,7 @@ primitives and generating renderables from them. ### Properties * [entities](primitivesystem.md#protected-entities) +* [frustumCuller](primitivesystem.md#private-frustumculler) * [messageBus](primitivesystem.md#protected-messagebus) * [scene](primitivesystem.md#protected-optional-scene) * [subscriberID](primitivesystem.md#subscriberid) @@ -43,18 +44,19 @@ primitives and generating renderables from them. ### constructor -\+ **new PrimitiveSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[PrimitiveSystem](primitivesystem.md)* +\+ **new PrimitiveSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `frustumCuller`: [IFrustumCuller](../interfaces/ifrustumculler.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[PrimitiveSystem](primitivesystem.md)* *Overrides [System](system.md).[constructor](system.md#constructor)* **Parameters:** -Name | Type | ------- | ------ | -`messageBus` | [IMessageBus](../interfaces/imessagebus.md) | -`scene?` | [IScene](../interfaces/iscene.md) | -`entities?` | Map‹number, [SystemEntity](systementity.md)› | -`subscriberID?` | undefined | number | +Name | Type | Default | +------ | ------ | ------ | +`messageBus` | [IMessageBus](../interfaces/imessagebus.md) | - | +`scene?` | [IScene](../interfaces/iscene.md) | - | +`frustumCuller` | [IFrustumCuller](../interfaces/ifrustumculler.md) | new FrustumCuller() | +`entities?` | Map‹number, [SystemEntity](systementity.md)› | - | +`subscriberID?` | undefined | number | - | **Returns:** *[PrimitiveSystem](primitivesystem.md)* @@ -74,6 +76,12 @@ etc. ___ +### `Private` frustumCuller + +• **frustumCuller**: *[IFrustumCuller](../interfaces/ifrustumculler.md)* + +___ + ### `Protected` messageBus • **messageBus**: *[IMessageBus](../interfaces/imessagebus.md)* diff --git a/docs/reference/classes/renderable.md b/docs/reference/classes/renderable.md index faebb00..4c7aed8 100644 --- a/docs/reference/classes/renderable.md +++ b/docs/reference/classes/renderable.md @@ -187,19 +187,13 @@ ___ ### Recycle -▸ **Recycle**(`zOrder`: number, `vertices`: [Polygon](polygon.md), `modelMatrix`: [Matrix4D](matrix4d.md), `material`: [Material](material.md), `drawMode`: [DrawMode](../enums/drawmode.md), `payload?`: T, `camera?`: [IEntity](../interfaces/ientity.md)): *[Renderable](renderable.md)‹T›* +▸ **Recycle**(`args`: [number, [Polygon](polygon.md), [Matrix4D](matrix4d.md), [Material](material.md), [DrawMode](../enums/drawmode.md), T, [IEntity](../interfaces/ientity.md)]): *[Renderable](renderable.md)‹T›* **Parameters:** Name | Type | ------ | ------ | -`zOrder` | number | -`vertices` | [Polygon](polygon.md) | -`modelMatrix` | [Matrix4D](matrix4d.md) | -`material` | [Material](material.md) | -`drawMode` | [DrawMode](../enums/drawmode.md) | -`payload?` | T | -`camera?` | [IEntity](../interfaces/ientity.md) | +`args` | [number, [Polygon](polygon.md), [Matrix4D](matrix4d.md), [Material](material.md), [DrawMode](../enums/drawmode.md), T, [IEntity](../interfaces/ientity.md)] | **Returns:** *[Renderable](renderable.md)‹T›* @@ -308,7 +302,7 @@ ___ ### `Static` `Protected` new -▸ **new**<**T**>(`poolKey`: string, `type`: object, ...`args`: any): *T* +▸ **new**<**T**>(`poolKey`: string, `type`: object, `args`: any[]): *T* *Inherited from [Pooled](pooled.md).[new](pooled.md#static-protected-new)* @@ -335,7 +329,7 @@ Name | Type | ------ | ------ | `constructor` | | -▪... **args**: *any* +▪ **args**: *any[]* The args to use when creating/recycling the object. diff --git a/docs/reference/classes/rendersystem.md b/docs/reference/classes/rendersystem.md index 3fa457f..31b8886 100644 --- a/docs/reference/classes/rendersystem.md +++ b/docs/reference/classes/rendersystem.md @@ -48,7 +48,7 @@ Contains the message constant for loading renderables. ### constructor -\+ **new RenderSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `evaluator?`: [Evaluator](../README.md#evaluator), `renderables`: [IRenderable](../interfaces/irenderable.md)[], `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[RenderSystem](rendersystem.md)* +\+ **new RenderSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `evaluator?`: [Evaluator](../README.md#evaluator), `renderables`: Map‹number, [IRenderable](../interfaces/irenderable.md)[]›, `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[RenderSystem](rendersystem.md)* *Overrides [System](system.md).[constructor](system.md#constructor)* @@ -59,7 +59,7 @@ Name | Type | Default | `messageBus` | [IMessageBus](../interfaces/imessagebus.md) | - | `scene?` | [IScene](../interfaces/iscene.md) | - | `evaluator?` | [Evaluator](../README.md#evaluator) | - | -`renderables` | [IRenderable](../interfaces/irenderable.md)[] | [] | +`renderables` | Map‹number, [IRenderable](../interfaces/irenderable.md)[]› | new Map() | `entities?` | Map‹number, [SystemEntity](systementity.md)› | - | `subscriberID?` | undefined | number | - | @@ -94,7 +94,7 @@ ___ ### `Protected` renderables -• **renderables**: *[IRenderable](../interfaces/irenderable.md)[]* +• **renderables**: *Map‹number, [IRenderable](../interfaces/irenderable.md)[]›* A list of things to be rendered. diff --git a/docs/reference/classes/spritesystem.md b/docs/reference/classes/spritesystem.md index 8d1b169..3c29d5a 100644 --- a/docs/reference/classes/spritesystem.md +++ b/docs/reference/classes/spritesystem.md @@ -23,6 +23,7 @@ a rendering system. ### Properties * [entities](spritesystem.md#protected-entities) +* [frustumCuller](spritesystem.md#private-frustumculler) * [messageBus](spritesystem.md#protected-messagebus) * [scene](spritesystem.md#protected-optional-scene) * [subscriberID](spritesystem.md#subscriberid) @@ -43,18 +44,19 @@ a rendering system. ### constructor -\+ **new SpriteSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[SpriteSystem](spritesystem.md)* +\+ **new SpriteSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `frustumCuller`: [IFrustumCuller](../interfaces/ifrustumculler.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[SpriteSystem](spritesystem.md)* *Overrides [System](system.md).[constructor](system.md#constructor)* **Parameters:** -Name | Type | ------- | ------ | -`messageBus` | [IMessageBus](../interfaces/imessagebus.md) | -`scene?` | [IScene](../interfaces/iscene.md) | -`entities?` | Map‹number, [SystemEntity](systementity.md)› | -`subscriberID?` | undefined | number | +Name | Type | Default | +------ | ------ | ------ | +`messageBus` | [IMessageBus](../interfaces/imessagebus.md) | - | +`scene?` | [IScene](../interfaces/iscene.md) | - | +`frustumCuller` | [IFrustumCuller](../interfaces/ifrustumculler.md) | new FrustumCuller() | +`entities?` | Map‹number, [SystemEntity](systementity.md)› | - | +`subscriberID?` | undefined | number | - | **Returns:** *[SpriteSystem](spritesystem.md)* @@ -74,6 +76,12 @@ etc. ___ +### `Private` frustumCuller + +• **frustumCuller**: *[IFrustumCuller](../interfaces/ifrustumculler.md)* + +___ + ### `Protected` messageBus • **messageBus**: *[IMessageBus](../interfaces/imessagebus.md)* diff --git a/docs/reference/classes/testcollisionalgorithm.md b/docs/reference/classes/testcollisionalgorithm.md index d955856..b08cca6 100644 --- a/docs/reference/classes/testcollisionalgorithm.md +++ b/docs/reference/classes/testcollisionalgorithm.md @@ -7,7 +7,6 @@ ## Implements -* [ICollisionAlgorithm](../interfaces/icollisionalgorithm.md) * [ICollisionAlgorithm](../interfaces/icollisionalgorithm.md) ## Index diff --git a/docs/reference/classes/testpointersystem.md b/docs/reference/classes/testpointersystem.md index 5461bef..538baa9 100644 --- a/docs/reference/classes/testpointersystem.md +++ b/docs/reference/classes/testpointersystem.md @@ -35,8 +35,11 @@ allows testing them without having to use JS event listeners * [Destroy](testpointersystem.md#destroy) * [OnDestroy](testpointersystem.md#protected-ondestroy) * [OnMessage](testpointersystem.md#onmessage) +* [SimulateMoveEvent](testpointersystem.md#simulatemoveevent) * [SimulatePointerEvent](testpointersystem.md#simulatepointerevent) +* [SimulateWheelEvent](testpointersystem.md#simulatewheelevent) * [Update](testpointersystem.md#update) +* [moveEvent](testpointersystem.md#protected-moveevent) * [pointerEvent](testpointersystem.md#protected-pointerevent) * [wheelEvent](testpointersystem.md#protected-wheelevent) @@ -44,7 +47,7 @@ allows testing them without having to use JS event listeners ### constructor -\+ **new TestPointerSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `inputElement`: HTMLElement, `scene?`: [IScene](../interfaces/iscene.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number, `isFullscreen`: boolean, `lockedPointerPosition?`: [Vector](vector.md), `lastWheelEvent?`: WheelEvent): *[TestPointerSystem](testpointersystem.md)* +\+ **new TestPointerSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `inputElement`: HTMLElement, `scene?`: [IScene](../interfaces/iscene.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number, `isFullscreen`: boolean, `lockedPointerPosition?`: [Vector](vector.md), `lastWheelEvent?`: WheelEvent, `lastMoveEvent?`: PointerEvent, `pointersToPublish`: PointerEvent[], `lastPublishedPointers`: [Pointer](pointer.md)[]): *[TestPointerSystem](testpointersystem.md)* *Inherited from [PointerSystem](pointersystem.md).[constructor](pointersystem.md#constructor)* @@ -62,6 +65,9 @@ Name | Type | Default | `isFullscreen` | boolean | false | `lockedPointerPosition?` | [Vector](vector.md) | - | `lastWheelEvent?` | WheelEvent | - | +`lastMoveEvent?` | PointerEvent | - | +`pointersToPublish` | PointerEvent[] | [] | +`lastPublishedPointers` | [Pointer](pointer.md)[] | [] | **Returns:** *[TestPointerSystem](testpointersystem.md)* @@ -185,6 +191,20 @@ Name | Type | ___ +### SimulateMoveEvent + +▸ **SimulateMoveEvent**(`event`: PointerEvent): *void* + +**Parameters:** + +Name | Type | +------ | ------ | +`event` | PointerEvent | + +**Returns:** *void* + +___ + ### SimulatePointerEvent ▸ **SimulatePointerEvent**(`event`: PointerEvent): *void* @@ -199,6 +219,20 @@ Name | Type | ___ +### SimulateWheelEvent + +▸ **SimulateWheelEvent**(`event`: WheelEvent): *void* + +**Parameters:** + +Name | Type | +------ | ------ | +`event` | WheelEvent | + +**Returns:** *void* + +___ + ### Update ▸ **Update**(): *void* @@ -211,23 +245,33 @@ ___ ___ +### `Protected` moveEvent + +▸ **moveEvent**(`event`: PointerEvent): *void* + +*Inherited from [PointerSystem](pointersystem.md).[moveEvent](pointersystem.md#protected-moveevent)* + +**Parameters:** + +Name | Type | +------ | ------ | +`event` | PointerEvent | + +**Returns:** *void* + +___ + ### `Protected` pointerEvent ▸ **pointerEvent**(`event`: PointerEvent): *void* *Inherited from [PointerSystem](pointersystem.md).[pointerEvent](pointersystem.md#protected-pointerevent)* -When a Pointer Event occurs; dispatches the pointer event with extra info -through the JamJar messaging system as a Pointer. -Adds in useful information, such as pointer position within camera -bounds, pointer world position for each camera and if the pointer is -within a camera's bounds. - **Parameters:** -Name | Type | Description | ------- | ------ | ------ | -`event` | PointerEvent | Pointer Event | +Name | Type | +------ | ------ | +`event` | PointerEvent | **Returns:** *void* diff --git a/docs/reference/classes/testpooledobject.md b/docs/reference/classes/testpooledobject.md index 32b9db3..68e5d62 100644 --- a/docs/reference/classes/testpooledobject.md +++ b/docs/reference/classes/testpooledobject.md @@ -215,7 +215,7 @@ ___ ### `Static` `Protected` new -▸ **new**<**T**>(`poolKey`: string, `type`: object, ...`args`: any): *T* +▸ **new**<**T**>(`poolKey`: string, `type`: object, `args`: any[]): *T* *Inherited from [Pooled](pooled.md).[new](pooled.md#static-protected-new)* @@ -242,7 +242,7 @@ Name | Type | ------ | ------ | `constructor` | | -▪... **args**: *any* +▪ **args**: *any[]* The args to use when creating/recycling the object. diff --git a/docs/reference/classes/testrendersystem.md b/docs/reference/classes/testrendersystem.md index 17cb807..1cd177d 100644 --- a/docs/reference/classes/testrendersystem.md +++ b/docs/reference/classes/testrendersystem.md @@ -43,7 +43,7 @@ only for testing ### constructor -\+ **new TestRenderSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `evaluator?`: [Evaluator](../README.md#evaluator), `renderables`: [IRenderable](../interfaces/irenderable.md)[], `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[TestRenderSystem](testrendersystem.md)* +\+ **new TestRenderSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `evaluator?`: [Evaluator](../README.md#evaluator), `renderables`: Map‹number, [IRenderable](../interfaces/irenderable.md)[]›, `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[TestRenderSystem](testrendersystem.md)* *Inherited from [RenderSystem](rendersystem.md).[constructor](rendersystem.md#constructor)* @@ -56,7 +56,7 @@ Name | Type | Default | `messageBus` | [IMessageBus](../interfaces/imessagebus.md) | - | `scene?` | [IScene](../interfaces/iscene.md) | - | `evaluator?` | [Evaluator](../README.md#evaluator) | - | -`renderables` | [IRenderable](../interfaces/irenderable.md)[] | [] | +`renderables` | Map‹number, [IRenderable](../interfaces/irenderable.md)[]› | new Map() | `entities?` | Map‹number, [SystemEntity](systementity.md)› | - | `subscriberID?` | undefined | number | - | @@ -91,7 +91,7 @@ ___ ### `Protected` renderables -• **renderables**: *[IRenderable](../interfaces/irenderable.md)[]* +• **renderables**: *Map‹number, [IRenderable](../interfaces/irenderable.md)[]›* *Inherited from [RenderSystem](rendersystem.md).[renderables](rendersystem.md#protected-renderables)* diff --git a/docs/reference/classes/testwheelsystem.md b/docs/reference/classes/testwheelsystem.md deleted file mode 100644 index 1b8dca1..0000000 --- a/docs/reference/classes/testwheelsystem.md +++ /dev/null @@ -1,252 +0,0 @@ - -# Class: TestWheelSystem - -TestWheelSystem is an extension of the PointerSystem that exposes the wheel event functions, -allows testing them without having to use JS event listeners - -## Hierarchy - - ↳ [PointerSystem](pointersystem.md) - - ↳ **TestWheelSystem** - -## Implements - -* [ISubscriber](../interfaces/isubscriber.md) - -## Index - -### Constructors - -* [constructor](testwheelsystem.md#constructor) - -### Properties - -* [entities](testwheelsystem.md#protected-entities) -* [messageBus](testwheelsystem.md#protected-messagebus) -* [scene](testwheelsystem.md#protected-optional-scene) -* [subscriberID](testwheelsystem.md#subscriberid) -* [MESSAGE_DEREGISTER](testwheelsystem.md#static-message_deregister) -* [MESSAGE_REGISTER](testwheelsystem.md#static-message_register) -* [MESSAGE_UPDATE](testwheelsystem.md#static-message_update) - -### Methods - -* [Destroy](testwheelsystem.md#destroy) -* [OnDestroy](testwheelsystem.md#protected-ondestroy) -* [OnMessage](testwheelsystem.md#onmessage) -* [SimulateWheelEvent](testwheelsystem.md#simulatewheelevent) -* [Update](testwheelsystem.md#update) -* [pointerEvent](testwheelsystem.md#protected-pointerevent) -* [wheelEvent](testwheelsystem.md#protected-wheelevent) - -## Constructors - -### constructor - -\+ **new TestWheelSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `inputElement`: HTMLElement, `scene?`: [IScene](../interfaces/iscene.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number, `isFullscreen`: boolean, `lockedPointerPosition?`: [Vector](vector.md), `lastWheelEvent?`: WheelEvent): *[TestWheelSystem](testwheelsystem.md)* - -*Inherited from [PointerSystem](pointersystem.md).[constructor](pointersystem.md#constructor)* - -*Overrides [System](system.md).[constructor](system.md#constructor)* - -**Parameters:** - -Name | Type | Default | ------- | ------ | ------ | -`messageBus` | [IMessageBus](../interfaces/imessagebus.md) | - | -`inputElement` | HTMLElement | - | -`scene?` | [IScene](../interfaces/iscene.md) | - | -`entities?` | Map‹number, [SystemEntity](systementity.md)› | - | -`subscriberID?` | undefined | number | - | -`isFullscreen` | boolean | false | -`lockedPointerPosition?` | [Vector](vector.md) | - | -`lastWheelEvent?` | WheelEvent | - | - -**Returns:** *[TestWheelSystem](testwheelsystem.md)* - -## Properties - -### `Protected` entities - -• **entities**: *Map‹number, [SystemEntity](systementity.md)›* - -*Inherited from [System](system.md).[entities](system.md#protected-entities)* - -A map of entities, mapped by their entity ID. -ID: Entity -0: PlayerEntity -1: ObstacleEntity -etc. - -___ - -### `Protected` messageBus - -• **messageBus**: *[IMessageBus](../interfaces/imessagebus.md)* - -*Inherited from [System](system.md).[messageBus](system.md#protected-messagebus)* - -Reference to the message bus, the fundamental piece of JamJar -for communicating with other parts of the engine. - -___ - -### `Protected` `Optional` scene - -• **scene**? : *[IScene](../interfaces/iscene.md)* - -*Inherited from [System](system.md).[scene](system.md#protected-optional-scene)* - -Any scene this system is part of, will change the lifecycle of the -system to be part of the scene's lifecycle - it will be destroyed -when the scene is destroyed. - -___ - -### subscriberID - -• **subscriberID**: *number* - -*Implementation of [ISubscriber](../interfaces/isubscriber.md).[subscriberID](../interfaces/isubscriber.md#subscriberid)* - -*Inherited from [Subscriber](subscriber.md).[subscriberID](subscriber.md#subscriberid)* - -___ - -### `Static` MESSAGE_DEREGISTER - -▪ **MESSAGE_DEREGISTER**: *"system_deregister"* = "system_deregister" - -*Inherited from [System](system.md).[MESSAGE_DEREGISTER](system.md#static-message_deregister)* - -___ - -### `Static` MESSAGE_REGISTER - -▪ **MESSAGE_REGISTER**: *"system_register"* = "system_register" - -*Inherited from [System](system.md).[MESSAGE_REGISTER](system.md#static-message_register)* - -___ - -### `Static` MESSAGE_UPDATE - -▪ **MESSAGE_UPDATE**: *"system_update"* = "system_update" - -*Inherited from [System](system.md).[MESSAGE_UPDATE](system.md#static-message_update)* - -## Methods - -### Destroy - -▸ **Destroy**(): *void* - -*Inherited from [System](system.md).[Destroy](system.md#destroy)* - -Destroy destroys the System and unsubscribes it from all messages. -The System should be garbage collected after this, unless a direct -reference to it exists somewhere. Therefore direct references to -systems are discouraged; communication should all be through the -message bus. - -**Returns:** *void* - -___ - -### `Protected` OnDestroy - -▸ **OnDestroy**(): *void* - -*Inherited from [System](system.md).[OnDestroy](system.md#protected-ondestroy)* - -Custom Destroy logic should go here to facilitate garbage collection, for example -removing listeners. - -**Returns:** *void* - -___ - -### OnMessage - -▸ **OnMessage**(`message`: [IMessage](../interfaces/imessage.md)): *void* - -*Inherited from [PointerSystem](pointersystem.md).[OnMessage](pointersystem.md#onmessage)* - -*Overrides [System](system.md).[OnMessage](system.md#onmessage)* - -**Parameters:** - -Name | Type | ------- | ------ | -`message` | [IMessage](../interfaces/imessage.md) | - -**Returns:** *void* - -___ - -### SimulateWheelEvent - -▸ **SimulateWheelEvent**(`event`: WheelEvent): *void* - -**Parameters:** - -Name | Type | ------- | ------ | -`event` | WheelEvent | - -**Returns:** *void* - -___ - -### Update - -▸ **Update**(): *void* - -*Inherited from [PointerSystem](pointersystem.md).[Update](pointersystem.md#update)* - -*Overrides [System](system.md).[Update](system.md#protected-update)* - -**Returns:** *void* - -___ - -### `Protected` pointerEvent - -▸ **pointerEvent**(`event`: PointerEvent): *void* - -*Inherited from [PointerSystem](pointersystem.md).[pointerEvent](pointersystem.md#protected-pointerevent)* - -When a Pointer Event occurs; dispatches the pointer event with extra info -through the JamJar messaging system as a Pointer. -Adds in useful information, such as pointer position within camera -bounds, pointer world position for each camera and if the pointer is -within a camera's bounds. - -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`event` | PointerEvent | Pointer Event | - -**Returns:** *void* - -___ - -### `Protected` wheelEvent - -▸ **wheelEvent**(`event`: WheelEvent): *void* - -*Inherited from [PointerSystem](pointersystem.md).[wheelEvent](pointersystem.md#protected-wheelevent)* - -When a Wheel Event occurs; used to store the last wheel event to be -dispatched at the next update. This is to throttle this event which can -be fired many times. - -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`event` | WheelEvent | Fired wheel event | - -**Returns:** *void* diff --git a/docs/reference/classes/textsystem.md b/docs/reference/classes/textsystem.md index 4ff17b4..876a8ee 100644 --- a/docs/reference/classes/textsystem.md +++ b/docs/reference/classes/textsystem.md @@ -25,6 +25,7 @@ be loaded as textures by rendering systems. ### Properties * [entities](textsystem.md#protected-entities) +* [frustumCuller](textsystem.md#private-frustumculler) * [mappings](textsystem.md#private-mappings) * [messageBus](textsystem.md#protected-messagebus) * [scene](textsystem.md#protected-optional-scene) @@ -49,7 +50,7 @@ be loaded as textures by rendering systems. ### constructor -\+ **new TextSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `mappings`: Map‹string, [FontMapping](fontmapping.md)›, `sdfGeneratorFactory`: SDFGeneratorFactory, `subscriberID?`: undefined | number): *[TextSystem](textsystem.md)* +\+ **new TextSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `scene?`: [IScene](../interfaces/iscene.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `frustumCuller`: [IFrustumCuller](../interfaces/ifrustumculler.md), `mappings`: Map‹string, [FontMapping](fontmapping.md)›, `sdfGeneratorFactory`: SDFGeneratorFactory, `subscriberID?`: undefined | number): *[TextSystem](textsystem.md)* *Overrides [System](system.md).[constructor](system.md#constructor)* @@ -60,6 +61,7 @@ Name | Type | Default | `messageBus` | [IMessageBus](../interfaces/imessagebus.md) | - | `scene?` | [IScene](../interfaces/iscene.md) | - | `entities?` | Map‹number, [SystemEntity](systementity.md)› | - | +`frustumCuller` | [IFrustumCuller](../interfaces/ifrustumculler.md) | new FrustumCuller() | `mappings` | Map‹string, [FontMapping](fontmapping.md)› | new Map() | `sdfGeneratorFactory` | SDFGeneratorFactory | TextSystem.DEFAULT_SDF_GENERATOR_FACTORY | `subscriberID?` | undefined | number | - | @@ -82,6 +84,12 @@ etc. ___ +### `Private` frustumCuller + +• **frustumCuller**: *[IFrustumCuller](../interfaces/ifrustumculler.md)* + +___ + ### `Private` mappings • **mappings**: *Map‹string, [FontMapping](fontmapping.md)›* diff --git a/docs/reference/classes/vector.md b/docs/reference/classes/vector.md index 1fb0bc1..bb2de27 100644 --- a/docs/reference/classes/vector.md +++ b/docs/reference/classes/vector.md @@ -318,14 +318,13 @@ ___ ### Recycle -▸ **Recycle**(`x`: number, `y`: number): *[Vector](vector.md)* +▸ **Recycle**(`args`: [number, number]): *[Vector](vector.md)* **Parameters:** Name | Type | ------ | ------ | -`x` | number | -`y` | number | +`args` | [number, number] | **Returns:** *[Vector](vector.md)* @@ -503,7 +502,7 @@ ___ ### `Static` `Protected` new -▸ **new**<**T**>(`poolKey`: string, `type`: object, ...`args`: any): *T* +▸ **new**<**T**>(`poolKey`: string, `type`: object, `args`: any[]): *T* *Inherited from [Pooled](pooled.md).[new](pooled.md#static-protected-new)* @@ -530,7 +529,7 @@ Name | Type | ------ | ------ | `constructor` | | -▪... **args**: *any* +▪ **args**: *any[]* The args to use when creating/recycling the object. diff --git a/docs/reference/classes/webglsystem.md b/docs/reference/classes/webglsystem.md index ead32dc..cbb7b0f 100644 --- a/docs/reference/classes/webglsystem.md +++ b/docs/reference/classes/webglsystem.md @@ -24,7 +24,6 @@ renders them onto a canvas. ### Properties * [entities](webglsystem.md#protected-entities) -* [frustumCuller](webglsystem.md#private-frustumculler) * [gl](webglsystem.md#private-gl) * [messageBus](webglsystem.md#protected-messagebus) * [programs](webglsystem.md#private-programs) @@ -56,7 +55,7 @@ renders them onto a canvas. ### constructor -\+ **new WebGLSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `gl`: WebGL2RenderingContext, `scene?`: [IScene](../interfaces/iscene.md), `renderables`: [IRenderable](../interfaces/irenderable.md)[], `defaultShaderAssets`: [ShaderAsset](shaderasset.md)[], `shaders`: Map‹string, [WebGLShader, [GLSLShader](glslshader.md)]›, `textures`: Map‹string, WebGLTexture›, `programs`: Map‹string, WebGLProgram›, `frustumCuller`: [IFrustumCuller](../interfaces/ifrustumculler.md), `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[WebGLSystem](webglsystem.md)* +\+ **new WebGLSystem**(`messageBus`: [IMessageBus](../interfaces/imessagebus.md), `gl`: WebGL2RenderingContext, `scene?`: [IScene](../interfaces/iscene.md), `renderables`: Map‹number, [IRenderable](../interfaces/irenderable.md)[]›, `defaultShaderAssets`: [ShaderAsset](shaderasset.md)[], `shaders`: Map‹string, [WebGLShader, [GLSLShader](glslshader.md)]›, `textures`: Map‹string, WebGLTexture›, `programs`: Map‹string, WebGLProgram›, `entities?`: Map‹number, [SystemEntity](systementity.md)›, `subscriberID?`: undefined | number): *[WebGLSystem](webglsystem.md)* *Overrides [RenderSystem](rendersystem.md).[constructor](rendersystem.md#constructor)* @@ -67,7 +66,7 @@ Name | Type | Default | `messageBus` | [IMessageBus](../interfaces/imessagebus.md) | - | `gl` | WebGL2RenderingContext | - | `scene?` | [IScene](../interfaces/iscene.md) | - | -`renderables` | [IRenderable](../interfaces/irenderable.md)[] | [] | +`renderables` | Map‹number, [IRenderable](../interfaces/irenderable.md)[]› | new Map() | `defaultShaderAssets` | [ShaderAsset](shaderasset.md)[] | [ new ShaderAsset(ShaderAsset.DEFAULT_TEXTURE_FRAGMENT_SHADER_NAME, new DefaultTextureFragmentShader()), new ShaderAsset(ShaderAsset.DEFAULT_TEXTURE_VERTEX_SHADER_NAME, new DefaultTextureVertexShader()), @@ -78,7 +77,6 @@ Name | Type | Default | `shaders` | Map‹string, [WebGLShader, [GLSLShader](glslshader.md)]› | new Map() | `textures` | Map‹string, WebGLTexture› | new Map() | `programs` | Map‹string, WebGLProgram› | new Map() | -`frustumCuller` | [IFrustumCuller](../interfaces/ifrustumculler.md) | new FrustumCuller() | `entities?` | Map‹number, [SystemEntity](systementity.md)› | - | `subscriberID?` | undefined | number | - | @@ -100,12 +98,6 @@ etc. ___ -### `Private` frustumCuller - -• **frustumCuller**: *[IFrustumCuller](../interfaces/ifrustumculler.md)* - -___ - ### `Private` gl • **gl**: *WebGL2RenderingContext* @@ -131,7 +123,7 @@ ___ ### `Protected` renderables -• **renderables**: *[IRenderable](../interfaces/irenderable.md)[]* +• **renderables**: *Map‹number, [IRenderable](../interfaces/irenderable.md)[]›* *Inherited from [RenderSystem](rendersystem.md).[renderables](rendersystem.md#protected-renderables)* diff --git a/docs/reference/interfaces/icollisionalgorithm.md b/docs/reference/interfaces/icollisionalgorithm.md index 2ff29cd..dde66dc 100644 --- a/docs/reference/interfaces/icollisionalgorithm.md +++ b/docs/reference/interfaces/icollisionalgorithm.md @@ -14,7 +14,6 @@ ICollisionAlgorithm represents a collision detection algorithm. * [GJKAlgorithm](../classes/gjkalgorithm.md) * [NoneCollideAlgorithm](../classes/nonecollidealgorithm.md) * [TestCollisionAlgorithm](../classes/testcollisionalgorithm.md) -* [TestCollisionAlgorithm](../classes/testcollisionalgorithm.md) ## Index diff --git a/docs/reference/interfaces/ifreeable.md b/docs/reference/interfaces/ifreeable.md index ec06382..3d54004 100644 --- a/docs/reference/interfaces/ifreeable.md +++ b/docs/reference/interfaces/ifreeable.md @@ -21,6 +21,8 @@ object to be freed/it's constituent parts freed back to object pools. * [FakeComponent](../classes/fakecomponent.md) * [Material](../classes/material.md) * [Motion](../classes/motion.md) +* [Pointer](../classes/pointer.md) +* [PointerCameraInfo](../classes/pointercamerainfo.md) * [Primitive](../classes/primitive.md) * [Script](../classes/script.md) * [Sprite](../classes/sprite.md) diff --git a/docs/reference/interfaces/ipoolable.md b/docs/reference/interfaces/ipoolable.md index d1a859a..9142eb2 100644 --- a/docs/reference/interfaces/ipoolable.md +++ b/docs/reference/interfaces/ipoolable.md @@ -50,7 +50,7 @@ ___ ### Recycle -▸ **Recycle**(...`args`: any): *[IPoolable](ipoolable.md)* +▸ **Recycle**(`args`: any[]): *[IPoolable](ipoolable.md)* Recycle is used to reuse an existing object instance, using the arguments provided - similar to a constructor, but must be repeatable. @@ -59,6 +59,6 @@ but must be repeatable. Name | Type | Description | ------ | ------ | ------ | -`...args` | any | The arguments to use when recycling the object instance | +`args` | any[] | The arguments to use when recycling the object instance | **Returns:** *[IPoolable](ipoolable.md)* diff --git a/docs/reference/interfaces/irenderable.md b/docs/reference/interfaces/irenderable.md index e6f2360..8cac674 100644 --- a/docs/reference/interfaces/irenderable.md +++ b/docs/reference/interfaces/irenderable.md @@ -109,7 +109,7 @@ ___ ### Recycle -▸ **Recycle**(...`args`: any): *[IPoolable](ipoolable.md)* +▸ **Recycle**(`args`: any[]): *[IPoolable](ipoolable.md)* *Inherited from [IPoolable](ipoolable.md).[Recycle](ipoolable.md#recycle)* @@ -120,6 +120,6 @@ but must be repeatable. Name | Type | Description | ------ | ------ | ------ | -`...args` | any | The arguments to use when recycling the object instance | +`args` | any[] | The arguments to use when recycling the object instance | **Returns:** *[IPoolable](ipoolable.md)* diff --git a/docs/reference/interfaces/isubscriber.md b/docs/reference/interfaces/isubscriber.md index 9b1a1e9..e5c20dc 100644 --- a/docs/reference/interfaces/isubscriber.md +++ b/docs/reference/interfaces/isubscriber.md @@ -37,7 +37,6 @@ * [TestRenderSystem](../classes/testrendersystem.md) * [TestScene](../classes/testscene.md) * [TestSystem](../classes/testsystem.md) -* [TestWheelSystem](../classes/testwheelsystem.md) * [TextSystem](../classes/textsystem.md) * [WebGLSystem](../classes/webglsystem.md) diff --git a/example/animation/src/index.ts b/example/animation/src/index.ts index 90990ae..d1dc66f 100644 --- a/example/animation/src/index.ts +++ b/example/animation/src/index.ts @@ -46,7 +46,8 @@ import { SystemEntity, Motion, MotionSystem, - InterpolationSystem,, Renderable + InterpolationSystem, + Renderable } from "jamjar"; class TextureGame extends Game { diff --git a/example/shooter/src/index.ts b/example/shooter/src/index.ts index 8f37225..5d4a230 100644 --- a/example/shooter/src/index.ts +++ b/example/shooter/src/index.ts @@ -340,7 +340,7 @@ class CrosshairSystem extends System { if (cameraInfo.camera.id != ui.camera.id) { continue; } - transform.position = cameraInfo.cameraPosition; + transform.position = cameraInfo.cameraPosition.Copy(); } } break; @@ -394,7 +394,7 @@ class PlayerSystem extends System { if (!cameraInfo.withinBounds) { continue; } - this.targetedPosition = cameraInfo.worldPosition; + this.targetedPosition = cameraInfo.worldPosition.Copy(); } break; } @@ -408,7 +408,7 @@ class PlayerSystem extends System { if (!cameraInfo.withinBounds) { continue; } - this.targetedPosition = cameraInfo.worldPosition; + this.targetedPosition = cameraInfo.worldPosition.Copy(); } const transform = player.Get(Transform.KEY) as Transform; diff --git a/package.json b/package.json index b300790..819ec34 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "@typescript-eslint/eslint-plugin": "^2.18.0", "@typescript-eslint/parser": "^2.18.0", "eslint": "^6.5.1", - "jest": "^25.1.0", + "jest": "^26.6.3", "ts-jest": "^25.1.0", "ts-loader": "^6.2.0", "typedoc": "^0.16.9", diff --git a/src/geometry/vector.ts b/src/geometry/vector.ts index 78cf0ea..84073d2 100644 --- a/src/geometry/vector.ts +++ b/src/geometry/vector.ts @@ -34,7 +34,7 @@ class Vector extends Pooled implements IPoolable { * Create a Vector.New, using pooling if available. */ public static New(x: number, y: number): Vector { - return this.new(Vector.POOL_KEY, Vector, x, y); + return this.new(Vector.POOL_KEY, Vector, [x, y]); } /** @@ -238,9 +238,9 @@ class Vector extends Pooled implements IPoolable { ); } - public Recycle(x: number, y: number): Vector { - this.x = x; - this.y = y; + public Recycle(args: [number, number]): Vector { + this.x = args[0]; + this.y = args[1]; return this; } diff --git a/src/pooling/ipoolable.ts b/src/pooling/ipoolable.ts index da9f8e7..99bcfa0 100644 --- a/src/pooling/ipoolable.ts +++ b/src/pooling/ipoolable.ts @@ -30,7 +30,7 @@ interface IPoolable extends IFreeable { * @param args The arguments to use when recycling the object instance */ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ - Recycle(...args: any): IPoolable; + Recycle(args: any[]): IPoolable; } export default IPoolable; diff --git a/src/pooling/pooled.test.ts b/src/pooling/pooled.test.ts index 1118193..15d3f63 100644 --- a/src/pooling/pooled.test.ts +++ b/src/pooling/pooled.test.ts @@ -24,7 +24,7 @@ class TestPooledObject extends Pooled { public id: number; public static SimulateNew(): TestPooledObject { - return this.new(TestPooledObject.POOL_KEY, TestPooledObject); + return this.new(TestPooledObject.POOL_KEY, TestPooledObject, []); } public static SimulateFree(obj: TestPooledObject): void { diff --git a/src/pooling/pooled.ts b/src/pooling/pooled.ts index 9048583..9d93c1c 100644 --- a/src/pooling/pooled.ts +++ b/src/pooling/pooled.ts @@ -50,7 +50,7 @@ abstract class Pooled { * @param args The args to use when creating/recycling the object. */ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ - protected static new(poolKey: string, type: { new(...args: any): T }, ...args: any): T { + protected static new(poolKey: string, type: { new(...args: any): T }, args: any[]): T { // Get any object pool with matching key, if no pool just create unpooled object const pool = Pooled.pools.get(poolKey); @@ -63,7 +63,7 @@ abstract class Pooled { if (pool[1].length > 0) { // Will always be non-undefined as the length is > 0 /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */ - const recycled = pool[1].shift()!.Recycle(...args) as T; + const recycled = pool[1].shift()!.Recycle(args) as T; recycled.objectInPool = false; return recycled; } diff --git a/src/rendering/renderable.ts b/src/rendering/renderable.ts index 2f660ab..e7df023 100644 --- a/src/rendering/renderable.ts +++ b/src/rendering/renderable.ts @@ -30,8 +30,8 @@ class Renderable extends Pooled implements IRenderable { public static New(zOrder: number, vertices: Polygon, modelMatrix: Matrix4D, material: Material, drawMode: DrawMode, payload?: T, camera?: IEntity): Renderable { - return this.new>(Renderable.POOL_KEY, Renderable, zOrder, vertices, modelMatrix, material, - drawMode, payload, camera); + return this.new>(Renderable.POOL_KEY, Renderable, [ zOrder, vertices, modelMatrix, material, + drawMode, payload, camera ]); } public static Free(obj: Renderable): void { @@ -90,15 +90,14 @@ class Renderable extends Pooled implements IRenderable { this.camera = camera; } - public Recycle(zOrder: number, vertices: Polygon, modelMatrix: Matrix4D, material: Material, drawMode: DrawMode, - payload?: T, camera?: IEntity): Renderable { - this.zOrder = zOrder; - this.vertices = vertices; - this.modelMatrix = modelMatrix; - this.material = material; - this.drawMode = drawMode; - this.payload = payload; - this.camera = camera; + public Recycle(args: [number, Polygon, Matrix4D, Material, DrawMode, T, IEntity]): Renderable { + this.zOrder = args[0]; + this.vertices = args[1]; + this.modelMatrix = args[2]; + this.material = args[3]; + this.drawMode = args[4]; + this.payload = args[5]; + this.camera = args[6]; return this; } diff --git a/src/shape/ishape.ts b/src/shape/ishape.ts index 14bfd3c..871e55c 100644 --- a/src/shape/ishape.ts +++ b/src/shape/ishape.ts @@ -23,10 +23,6 @@ import Transform from "../standard/transform/transform"; * for the shape to be used with collision detection. */ interface IShape extends IFreeable { - /** - * Center calculates/retrieves the center of a shape. - * @returns {Vector} The center point of the shape - */ /** * Center calculates/retrieves the center of a shape. * @returns {Vector} The center point of the shape diff --git a/src/shape/polygon.test.ts b/src/shape/polygon.test.ts index afa981f..ff9c29d 100644 --- a/src/shape/polygon.test.ts +++ b/src/shape/polygon.test.ts @@ -305,10 +305,10 @@ describe("Polygon - RectangleByPoints", () => { [ "0,0 to 1,1 rectangle", new Polygon([ - new Vector(0,0), - new Vector(1,0), - new Vector(1,1), new Vector(0,1), + new Vector(1,1), + new Vector(1,0), + new Vector(0,0), ]), new Vector(0,0), new Vector(1,1), @@ -317,10 +317,10 @@ describe("Polygon - RectangleByPoints", () => { [ "0,0 to 5,5 rectangle", new Polygon([ - new Vector(0,0), - new Vector(5,0), - new Vector(5,5), new Vector(0,5), + new Vector(5,5), + new Vector(5,0), + new Vector(0,0), ]), new Vector(0,0), new Vector(5,5), @@ -329,10 +329,10 @@ describe("Polygon - RectangleByPoints", () => { [ "2,3 to 10,9 rectangle", new Polygon([ - new Vector(2,3), - new Vector(10,3), - new Vector(10,9), new Vector(2,9), + new Vector(10,9), + new Vector(10,3), + new Vector(2,3), ]), new Vector(2,3), new Vector(10,9), @@ -341,11 +341,11 @@ describe("Polygon - RectangleByPoints", () => { [ "2,3 to 10,9 rectangle wrapped", new Polygon([ - new Vector(2,3), - new Vector(10,3), - new Vector(10,9), new Vector(2,9), + new Vector(10,9), + new Vector(10,3), new Vector(2,3), + new Vector(2,9), ]), new Vector(2,3), new Vector(10,9), diff --git a/src/shape/polygon.ts b/src/shape/polygon.ts index 2ade60f..c49d48a 100644 --- a/src/shape/polygon.ts +++ b/src/shape/polygon.ts @@ -24,12 +24,31 @@ import Matrix4D from "../geometry/matrix_4d"; * Can be used in collision detection and rendering. */ class Polygon implements IShape { - public points: Vector[]; + public points: Float32Array; - constructor(points: Vector[], wrap = false) { - this.points = points; - if (wrap && points.length > 0) { - this.points.push(points[0].Copy()); + constructor(points: Vector[] | Float32Array, wrap = false) { + if (points instanceof Float32Array) { + this.points = points; + } else { + if (wrap) { + this.points = new Float32Array(points.length * 2 + 2); + } else { + this.points = new Float32Array(points.length * 2); + } + for (let i = 0; i < points.length; i++) { + this.points[i * 2] = points[i].x; + this.points[i * 2 + 1] = points[i].y; + if (i !== points.length - 1) { + points[i].Free(); + } + } + if (points.length > 0) { + if (wrap) { + this.points[points.length * 2] = points[0].x; + this.points[points.length * 2 + 1] = points[0].y; + } + points[points.length - 1].Free(); + } } } @@ -37,58 +56,60 @@ class Polygon implements IShape { * Make a value copy of the Polygon. */ public Copy(): Polygon { - const points: Vector[] = []; - for (const point of this.points) { - points.push(point.Copy()); - } - return new Polygon( - points, - ); + return new Polygon(this.points.subarray()); } public Apply4D(matrix: Matrix4D): Polygon { - const appliedPoints: Vector[] = []; - for (const point of this.points) { - appliedPoints.push(point.Copy().Apply4D(matrix)); + const points = this.points.subarray(); + for (let i = 0; i < this.points.length; i += 2) { + const x = points[i]; + const y = points[i + 1]; + points[i] = matrix.values[0] * x + matrix.values[4] * y + matrix.values[12]; + points[i + 1]= matrix.values[1] * x + matrix.values[5] * y + matrix.values[13]; } - return new Polygon(appliedPoints); + return new Polygon(points); } public FarthestPointInDirection(direction: Vector): Vector { let farthestDistance = -Infinity; // If there are no points, just return point 0,0 - let farthestPoint: Vector = Vector.New(0, 0); - for (const point of this.points) { - const distanceInDirection = point.Dot(direction); + let farthestPoint: [number, number] = [0, 0]; + for (let i = 0; i < this.points.length; i += 2) { + const x = this.points[i]; + const y = this.points[i + 1]; + const distanceInDirection = x * direction.x + y * direction.y; if (distanceInDirection > farthestDistance) { - farthestPoint = point; + farthestPoint = [x, y]; farthestDistance = distanceInDirection; } } - return farthestPoint.Copy(); + return Vector.New(farthestPoint[0], farthestPoint[1]); } public Center(): Vector { let xSum = 0; let ySum = 0; - for (const point of this.points) { - xSum += point.x; - ySum += point.y; + for (let i = 0; i < this.points.length; i += 2) { + xSum += this.points[i]; + ySum += this.points[i + 1]; } return Vector.New( - xSum / this.points.length, - ySum / this.points.length + xSum / (this.points.length / 2), + ySum / (this.points.length / 2) ); } public Transform(transform: Transform): Polygon { const matrix = transform.Matrix3D(); - const transformedPoints = []; - for (const point of this.points) { - transformedPoints.push(point.Copy().Apply3D(matrix)); + const points = this.points.slice(); + for (let i = 0; i < points.length; i += 2) { + const x = points[i]; + const y = points[i + 1]; + points[i] = matrix.values[0] * x + matrix.values[3] * y + matrix.values[6]; + points[i + 1] = matrix.values[1] * x + matrix.values[4] * y + matrix.values[7]; } - return new Polygon(transformedPoints); + return new Polygon(points); } public PointInside(point: Vector): boolean { @@ -98,15 +119,17 @@ class Polygon implements IShape { * Based on description here: * http://alienryderflex.com/polygon/ */ - let j = this.points.length - 1; + let j = this.points.length - 2; let inPolygon = false; - for (let i = 0; i < this.points.length; i++) { - const cornerA = this.points[i]; - const cornerB = this.points[j]; - if ((cornerA.y < point.y && cornerB.y >= point.y || - cornerB.y < point.y && cornerA.y >= point.y) && - (cornerA.x <= point.x || cornerB.x <= point.x)) { - if (cornerA.x + (point.y - cornerA.y) / (cornerB.y - cornerA.y) * (cornerB.x - cornerA.x) < point.x) { + for (let i = 0; i < this.points.length; i += 2) { + const cornerAX = this.points[i]; + const cornerAY = this.points[i + 1]; + const cornerBX = this.points[j]; + const cornerBY = this.points[j + 1]; + if ((cornerAY < point.y && cornerBY >= point.y || + cornerBY < point.y && cornerAY >= point.y) && + (cornerAX <= point.x || cornerBX <= point.x)) { + if (cornerAX + (point.y - cornerAY) / (cornerBY - cornerAY) * (cornerBX - cornerAX) < point.x) { inPolygon = !inPolygon; } } @@ -116,9 +139,7 @@ class Polygon implements IShape { } public Free(): void { - for (const point of this.points) { - point.Free(); - } + // Nothing to return to the pool } /** @@ -126,12 +147,7 @@ class Polygon implements IShape { * @returns {Float32Array} The array representation of the polygon */ public GetFloat32Array(): Float32Array { - const arr = new Float32Array(this.points.length * 2); - for (let i = 0; i < this.points.length; i++) { - arr[i * 2] = this.points[i].x; - arr[i * 2 + 1] = this.points[i].y; - } - return arr; + return this.points; } /** @@ -144,12 +160,36 @@ class Polygon implements IShape { public static RectangleByDimensions(width: number, height: number, originX = 0, originY = 0, wrap = false): Polygon { const halfWidth = width / 2; const halfHeight = height / 2; - return new Polygon([ - Vector.New(originX - halfWidth, originY + halfHeight), // top left - Vector.New(originX + halfWidth, originY + halfHeight), // top right - Vector.New(originX + halfWidth, originY - halfHeight), // bottom right - Vector.New(originX - halfWidth, originY - halfHeight), // bottom left - ], wrap); + + let typedArraySize = 8; + if (wrap) { + typedArraySize += 2; + } + + const points = new Float32Array(typedArraySize); + + // Top left + points[0] = originX - halfWidth; + points[1] = originY + halfHeight; + + // Top right + points[2] = originX + halfWidth; + points[3] = originY + halfHeight; + + // Bottom right + points[4] = originX + halfWidth; + points[5] = originY - halfHeight; + + // Bottom left + points[6] = originX - halfWidth; + points[7] = originY - halfHeight; + + if (wrap) { + points[typedArraySize - 2] = points[0]; + points[typedArraySize - 1] = points[1]; + } + + return new Polygon(points); } /** @@ -159,16 +199,13 @@ class Polygon implements IShape { * @param {Vector} topRight Top right of the rectangle */ public static RectangleByPoints(bottomLeft: Vector, topRight: Vector, wrap = false): Polygon { - const bottomRight = bottomLeft.Copy(); - bottomRight.x += topRight.x - bottomLeft.x; - const topLeft = topRight.Copy(); - topLeft.x -= topRight.x - bottomLeft.x; - return new Polygon([ - bottomLeft.Copy(), - bottomRight, - topRight.Copy(), - topLeft - ], wrap); + + const width = topRight.x - bottomLeft.x; + const height = topRight.y - bottomLeft.y; + const originX = (topRight.x + bottomLeft.x) / 2; + const originY = (topRight.y + bottomLeft.y) / 2; + + return Polygon.RectangleByDimensions(width, height, originX, originY, wrap); } /** @@ -182,20 +219,33 @@ class Polygon implements IShape { const halfWidth = width / 2; const halfHeight = height / 2; - const bottomRight = Vector.New(originX + halfWidth, originY - halfHeight); - const bottomLeft = Vector.New(originX - halfWidth, originY - halfHeight); - const topLeft = Vector.New(originX - halfWidth, originY + halfHeight); - const topRight = Vector.New(originX + halfWidth, originY + halfHeight); + const points = new Float32Array(12); + + // Bottom right + points[0] = originX + halfWidth; + points[1] = originY - halfHeight; + + // Bottom left + points[2] = originX - halfWidth; + points[3] = originY - halfHeight; + + // Top left + points[4] = originX - halfWidth; + points[5] = originY + halfHeight; + + // Top left + points[6] = originX - halfWidth; + points[7] = originY + halfHeight; + + // Top right + points[8] = originX + halfWidth; + points[9] = originY + halfHeight; - return new Polygon([ - bottomRight, - bottomLeft, - topLeft, + // Bottom right + points[10] = originX + halfWidth; + points[11] = originY - halfHeight; - topLeft.Copy(), - topRight, - bottomRight.Copy(), - ]); + return new Polygon(points); } /** @@ -205,18 +255,13 @@ class Polygon implements IShape { * @param {Vector} topRight Top right of the quad */ public static QuadByPoints(bottomLeft: Vector, topRight: Vector): Polygon { - const bottomRight = bottomLeft.Copy(); - bottomRight.x += topRight.x - bottomLeft.x; - const topLeft = topRight.Copy(); - topLeft.x -= topRight.x - bottomLeft.x; - return new Polygon([ - bottomRight, - bottomLeft.Copy(), - topLeft, - topLeft.Copy(), - topRight.Copy(), - bottomRight.Copy() - ]); + + const width = topRight.x - bottomLeft.x; + const height = topRight.y - bottomLeft.y; + const originX = (topRight.x + bottomLeft.x) / 2; + const originY = (topRight.y + bottomLeft.y) / 2; + + return Polygon.QuadByDimensions(width, height, originX, originY); } /** @@ -228,16 +273,26 @@ class Polygon implements IShape { */ public static EllipseEstimation(numOfPoints: number, dimensions: Vector, centerX = 0, centerY = 0, wrap = false): Polygon { - const points: Vector[] = []; + + let typedArraySize = numOfPoints * 2; + if (wrap && numOfPoints > 0) { + typedArraySize += 2; + } + + const points: Float32Array = new Float32Array(typedArraySize); for (let i = 0; i < numOfPoints; i++) { const done = i / numOfPoints; const angle = done * 2 * Math.PI; - points.push(Vector.New( - dimensions.x * Math.cos(angle) + centerX, - dimensions.y * Math.sin(angle) + centerY, - )); + points[i * 2] = dimensions.x * Math.cos(angle) + centerX; + points[i * 2 + 1] = dimensions.y * Math.sin(angle) + centerY; + } + + if (wrap && numOfPoints > 0) { + points[typedArraySize - 2] = points[0]; + points[typedArraySize - 1] = points[1]; } - return new Polygon(points, wrap); + + return new Polygon(points); } } diff --git a/src/standard/collision/algorithm/aabb_algorithm.ts b/src/standard/collision/algorithm/aabb_algorithm.ts index 9c76649..783217a 100644 --- a/src/standard/collision/algorithm/aabb_algorithm.ts +++ b/src/standard/collision/algorithm/aabb_algorithm.ts @@ -44,7 +44,11 @@ class AABBAlgorithm implements ICollisionAlgorithm { aRight.x > bLeft.x) { horizontalOverlap.push([a, b]); } + bLeft.Free(); + bRight.Free(); } + aLeft.Free(); + aRight.Free(); } leftDir.Free(); @@ -66,6 +70,10 @@ class AABBAlgorithm implements ICollisionAlgorithm { aUp.y > bDown.y) { collisions.push(new CollisionInfo(a, b)); } + aUp.Free(); + aDown.Free(); + bUp.Free(); + bDown.Free(); } upDir.Free(); diff --git a/src/standard/collision/algorithm/gjk_algorithm.ts b/src/standard/collision/algorithm/gjk_algorithm.ts index f130a9a..a63220a 100644 --- a/src/standard/collision/algorithm/gjk_algorithm.ts +++ b/src/standard/collision/algorithm/gjk_algorithm.ts @@ -49,6 +49,7 @@ class GJKAlgorithm implements ICollisionAlgorithm { // Get the first support point and add it to the simplex const initSupportPoint = this.support(a, b, direction); simplex.push(initSupportPoint); + direction.Free(); // First support point was calculated from the origin, so the next search direction // should be its inverse to get a point on the opposite side of the Minkowski Difference @@ -65,21 +66,33 @@ class GJKAlgorithm implements ICollisionAlgorithm { // intersection if (supportPoint.Dot(direction) <= 0) { // No intersection + direction.Free(); + this.freeSimplex(simplex); return; } // Add the simplex and determine a new direction simplex.push(supportPoint); + direction.Free(); direction = this.calculateDirection(simplex); } // No direction calculated, intersection detected + this.freeSimplex(simplex); return new CollisionInfo(a, b); } + private freeSimplex(simplex: Vector[]): void { + for (const point of simplex) { + point.Free(); + } + } + private support(a: IShape, b: IShape, direction: Vector): Vector { const aFar = a.FarthestPointInDirection(direction); const bFar = b.FarthestPointInDirection(direction.Invert()); - return aFar.Sub(bFar); + const support = aFar.Sub(bFar); + bFar.Free(); + return support; } private calculateDirection(points: Vector[]): Vector | undefined { @@ -113,17 +126,21 @@ class GJKAlgorithm implements ICollisionAlgorithm { // of the perpendicular; aiming to try to encapsulate // the origin that lies outside if (abPerp.Dot(ao) > 0) { + ao.Free(); + points[0].Free(); points.splice(0, 1); return abPerp; } + abPerp.Free(); + // Determine perpendicular of the a->c line let acPerp = Vector.New(ac.y, -ac.x); // Check the handedness of the perpendicular, it should // face AWAY from the simplex if (acPerp.Dot(b) >= 0) { - acPerp = acPerp.Copy().Invert(); + acPerp = acPerp.Invert(); } // If the origin lies outside of the simplex. remove the @@ -131,9 +148,13 @@ class GJKAlgorithm implements ICollisionAlgorithm { // of the perpendicular; aiming to try to encapsulate // the origin that lies outside if (acPerp.Dot(ao) > 0) { + ao.Free(); + points[1].Free(); points.splice(1, 1); return acPerp; } + ao.Free(); + acPerp.Free(); return undefined; } // Otherwise the simplex is just a line @@ -146,10 +167,12 @@ class GJKAlgorithm implements ICollisionAlgorithm { // Get the perpendicular of the a->b line let abPerp = Vector.New(ab.y, -ab.x); + ab.Free(); + // Check the handedness of the perpendicular, it should // face TOWARDS the origin if (abPerp.Dot(ao) <= 0) { - abPerp = abPerp.Copy().Invert(); + abPerp = abPerp.Invert(); } return abPerp; } diff --git a/src/standard/collision/collision_system.ts b/src/standard/collision/collision_system.ts index 508ebf2..411bd51 100644 --- a/src/standard/collision/collision_system.ts +++ b/src/standard/collision/collision_system.ts @@ -180,6 +180,11 @@ class CollisionSystem extends System { } } + for (const shape of shapes.keys()) { + shape.Free(); + } + shapes.clear(); + // Clear out expired (exited) collisions for (const expired of expiredCollisions) { this.messageBus.Publish(new Message(CollisionSystem.MESSAGE_COLLISION_EXIT, expired)); @@ -210,7 +215,11 @@ class CollisionSystem extends System { } } - this.colliding = [...collisions]; + this.colliding = []; + + for (const collision of collisions) { + this.colliding.push(collision); + } // Publish collision triggers for (const trigger of triggers) { diff --git a/src/standard/frustum_culler/frustum_culler.ts b/src/standard/frustum_culler/frustum_culler.ts index e17c5cf..98ebcaa 100644 --- a/src/standard/frustum_culler/frustum_culler.ts +++ b/src/standard/frustum_culler/frustum_culler.ts @@ -25,10 +25,10 @@ import AABBAlgorithm from "../collision/algorithm/aabb_algorithm"; */ class FrustumCuller implements IFrustumCuller { - private narrowAlgorithm: ICollisionAlgorithm; + private collisionAlgorithm: ICollisionAlgorithm; - constructor(narrowAlgorithm: ICollisionAlgorithm = new AABBAlgorithm()) { - this.narrowAlgorithm = narrowAlgorithm; + constructor(collisionAlgorithm: ICollisionAlgorithm = new AABBAlgorithm()) { + this.collisionAlgorithm = collisionAlgorithm; } /** @@ -40,7 +40,7 @@ class FrustumCuller implements IFrustumCuller { * @param shape Shape to check if it is within the frustum */ public Cull(frustumPlaneShape: IShape, shape: IShape): boolean { - const narrow = this.narrowAlgorithm.CalculateCollisions([frustumPlaneShape, shape]); + const narrow = this.collisionAlgorithm.CalculateCollisions([frustumPlaneShape, shape]); if (narrow.length === 0) { return true; } diff --git a/src/standard/interpolation/interpolation_system.ts b/src/standard/interpolation/interpolation_system.ts index c45d57f..e539134 100644 --- a/src/standard/interpolation/interpolation_system.ts +++ b/src/standard/interpolation/interpolation_system.ts @@ -66,7 +66,8 @@ class InterpolationSystem extends System { private interpolateTransforms(): void { for (const entity of this.entities.values()) { const transform = entity.Get(Transform.KEY) as Transform; - transform.previous = transform.previous.Recycle(transform.position.x, transform.position.y); + transform.previous.x = transform.position.x; + transform.previous.y = transform.position.y; } } } diff --git a/src/standard/pointer/pointer.ts b/src/standard/pointer/pointer.ts index 010b707..8a8b67e 100644 --- a/src/standard/pointer/pointer.ts +++ b/src/standard/pointer/pointer.ts @@ -15,13 +15,14 @@ limitations under the License. */ import Vector from "../../geometry/vector"; +import IFreeable from "../../pooling/ifreeable"; import PointerCameraInfo from "./pointer_camera_info"; /** * Pointer describes a pointer event with additional information around cameras and position within * the element the game is running in. */ -class Pointer { +class Pointer implements IFreeable { /** * Standard PointerEvent dispatched from JS. */ @@ -40,6 +41,13 @@ class Pointer { this.elementPosition = elementPosition; this.cameraInfos = cameraInfos; } + + public Free(): void { + this.elementPosition.Free(); + for (const cameraInfo of this.cameraInfos) { + cameraInfo.Free(); + } + } } -export default Pointer; \ No newline at end of file +export default Pointer; diff --git a/src/standard/pointer/pointer_camera_info.ts b/src/standard/pointer/pointer_camera_info.ts index 189f5f0..0d1b516 100644 --- a/src/standard/pointer/pointer_camera_info.ts +++ b/src/standard/pointer/pointer_camera_info.ts @@ -16,11 +16,12 @@ limitations under the License. import IEntity from "../../entity/ientity"; import Vector from "../../geometry/vector"; +import IFreeable from "../../pooling/ifreeable"; /** * PointerCameraInfo pointer information relevant to a camera. */ -class PointerCameraInfo { +class PointerCameraInfo implements IFreeable { /** * Entity of the camera. */ @@ -44,6 +45,11 @@ class PointerCameraInfo { this.worldPosition = worldPosition; this.withinBounds = withinBounds; } + + public Free(): void { + this.cameraPosition.Free(); + this.worldPosition.Free(); + } } -export default PointerCameraInfo; \ No newline at end of file +export default PointerCameraInfo; diff --git a/src/standard/pointer/pointer_system.test.ts b/src/standard/pointer/pointer_system.test.ts index 9f24542..6eae13f 100644 --- a/src/standard/pointer/pointer_system.test.ts +++ b/src/standard/pointer/pointer_system.test.ts @@ -19,17 +19,17 @@ import IMessage from "../../message/imessage"; import System from "../../system/system"; import Message from "../../message/message"; import FakeMessageBus from "../../fake/message_bus"; -import Vector from "../../geometry/vector"; import FakeEntity from "../../fake/entity"; import IEntity from "../../entity/ientity"; import Component from "../../component/component"; import Camera from "../camera/camera"; import Transform from "../transform/transform"; import SystemEntity from "../../system/system_entity"; -import Color from "../../rendering/color"; import FullscreenSystem from "../fullscreen/fullscreen_system"; import Reactor from "../../fake/reactor"; import Pointer from "./pointer"; +import Vector from "../../geometry/vector"; +import Color from "../../rendering/color"; import PointerCameraInfo from "./pointer_camera_info"; describe("PointerSystem - OnMessage", () => { @@ -174,104 +174,172 @@ describe("PointerSystem - OnMessage", () => { ), new Message(System.MESSAGE_UPDATE, 1.0) ], - ])("%p", (description: string, expected: Error | undefined, expectedState: PointerSystem, system: PointerSystem, message: IMessage) => { - if (expected instanceof Error) { - expect(() => { - system.OnMessage(message); - }).toThrow(expected); - } else { - expect(system.OnMessage(message)).toEqual(expected); - } - expect(system).toEqual(expectedState); - window.close(); - }); -}); - - -/** - * TestPointerSystem is an extension of the PointerSystem that exposes the pointer event functions, - * allows testing them without having to use JS event listeners - */ -class TestPointerSystem extends PointerSystem { - public SimulatePointerEvent(event: PointerEvent): void { - this.pointerEvent(event); - } -} - -describe("PointerSystem - pointer input", () => { - type TestTuple = [string, Error | undefined, PointerSystem, TestPointerSystem, PointerEvent]; - test.each([ [ - "Pointer move, not fullscreen, no camera, publish fail", - new Error("publish fail"), - new TestPointerSystem(new FakeMessageBus(), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + "Update, move message, not fullscreen, no cameras", + undefined, + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), undefined, undefined, - 0 + 0, + false, + undefined, + undefined, + undefined, + undefined, + [ + new Pointer( + new PointerEvent("pointermove", { clientX: 3, clientY: 2 }), + new Vector(0.6000000238418579, 1.600000023841858), + [] + ) + ] ), - new TestPointerSystem(new FakeMessageBus([new Reactor("Publish", (message: Message) => { - throw("publish fail"); - })]), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), undefined, undefined, - 0 + 0, + false, + undefined, + undefined, + new PointerEvent("pointermove", { clientX: 3, clientY: 2 }) ), - new PointerEvent("pointermove", { clientX: 3, clientY: 2 }) + new Message(System.MESSAGE_UPDATE, 1.0) ], [ - "Pointer move, not fullscreen, no cameras", + "Update, move message, not fullscreen, one camera", undefined, - new TestPointerSystem(new FakeMessageBus(), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), + undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(10, 10)) + ])] + ]), + 0, + false, undefined, undefined, - 0 + undefined, + undefined, + [ + new Pointer( + new PointerEvent("pointermove", { clientX: 3, clientY: 2 }), + new Vector(0.6000000238418579, 1.600000023841858), + [ + new PointerCameraInfo( + new FakeEntity(0), + new Vector(0.6000000238418579, 1.600000023841858), + new Vector(3, 8), + false + ) + ] + ) + ] ), - new TestPointerSystem(new FakeMessageBus([new Reactor("Publish", (message: Message) => { - expect(message).toEqual(new Message( - "pointermove", - new Pointer(new PointerEvent("pointermove", { clientX: 3, clientY: 2 }), new Vector(0.6, 1.6), []) - )); - })]), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(10, 10)) + ])] + ]), + 0, + false, undefined, - 0 + undefined, + new PointerEvent("pointermove", { clientX: 3, clientY: 2 }) ), - new PointerEvent("pointermove", { clientX: 3, clientY: 2 }) + new Message(System.MESSAGE_UPDATE, 1.0) ], [ - "Pointer move, not fullscreen, two cameras", + "Update, pointer message, not fullscreen, no cameras", undefined, - new TestPointerSystem(new FakeMessageBus(), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), + undefined, + undefined, + 0, + false, + undefined, + undefined, + undefined, + undefined, + [ + new Pointer( + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }), + new Vector(0.6000000238418579, 1.600000023841858), + [] + ) + ] + ), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), + undefined, + undefined, + 0, + false, + undefined, + undefined, + undefined, + [ + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }) + ] + ), + new Message(System.MESSAGE_UPDATE, 1.0) + ], + [ + "Update, pointer message (pointerdown), not fullscreen, two cameras", + undefined, + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ @@ -283,23 +351,41 @@ describe("PointerSystem - pointer input", () => { new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(100, 100)) ])] ]), - 0 + 0, + false, + undefined, + undefined, + undefined, + undefined, + [ + new Pointer( + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }), + new Vector(0.6000000238418579, 1.600000023841858), + [ + new PointerCameraInfo( + new FakeEntity(0), + new Vector(0.6000000238418579, 1.600000023841858), + new Vector(3, 8), + false + ), + new PointerCameraInfo( + new FakeEntity(1), + new Vector(0.6000000238418579, 1.600000023841858), + new Vector(30.000001907348633, 80), + false + ) + ] + ) + ] ), - new TestPointerSystem(new FakeMessageBus([new Reactor("Publish", (message: Message) => { - expect(message).toEqual(new Message( - "pointermove", - new Pointer(new PointerEvent("pointermove", { clientX: 3, clientY: 2 }), new Vector(0.6, 1.6), [ - new PointerCameraInfo(new FakeEntity(0), new Vector(0.6, 1.6), new Vector(3, 8), false), - new PointerCameraInfo(new FakeEntity(1), new Vector(0.6, 1.6), new Vector(30.000001907348633, 80), false) - ]) - )); - })]), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ @@ -311,20 +397,107 @@ describe("PointerSystem - pointer input", () => { new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(100, 100)) ])] ]), - 0 + 0, + false, + undefined, + undefined, + undefined, + [ + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }) + ] ), - new PointerEvent("pointermove", { clientX: 3, clientY: 2 }) + new Message(System.MESSAGE_UPDATE, 1.0) ], [ - "Pointer move, fullscreen, no locked pointer position set, one camera", + "Update, pointer message (pointerdown), not fullscreen, two cameras", undefined, - new TestPointerSystem(new FakeMessageBus(), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), + undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(10, 10)) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(100, 100)) + ])] + ]), + 0, + false, + undefined, + undefined, + undefined, + undefined, + [ + new Pointer( + new PointerEvent("pointerdown", { clientX: 3, clientY: 2 }), + new Vector(0.6000000238418579, 1.600000023841858), + [ + new PointerCameraInfo( + new FakeEntity(0), + new Vector(0.6000000238418579, 1.600000023841858), + new Vector(3, 8), + false + ), + new PointerCameraInfo( + new FakeEntity(1), + new Vector(0.6000000238418579, 1.600000023841858), + new Vector(30.000001907348633, 80), + false + ) + ] + ) + ] + ), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), + undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(10, 10)) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(100, 100)) + ])] + ]), + 0, + false, + undefined, + undefined, + undefined, + [ + new PointerEvent("pointerdown", { clientX: 3, clientY: 2 }) + ] + ), + new Message(System.MESSAGE_UPDATE, 1.0) + ], + [ + "Update, pointer event, fullscreen, no locked pointer position set, one camera", + undefined, + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ @@ -334,22 +507,33 @@ describe("PointerSystem - pointer input", () => { ]), 0, true, - new Vector(3, 2) + new Vector(3, 2), + undefined, + undefined, + undefined, + [ + new Pointer( + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }), + new Vector(0.6000000238418579, 1.600000023841858), + [ + new PointerCameraInfo( + new FakeEntity(0), + new Vector(0.6000000238418579, 1.600000023841858), + new Vector(3, 8), + false + ) + ] + ) + ] ), - new TestPointerSystem(new FakeMessageBus([new Reactor("Publish", (message: Message) => { - expect(message).toEqual(new Message( - "pointermove", - new Pointer(new PointerEvent("pointermove", { clientX: 3, clientY: 2 }), new Vector(0.6, 1.6), [ - new PointerCameraInfo(new FakeEntity(0), new Vector(0.6, 1.6), new Vector(3, 8), false), - ]) - )); - })]), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ @@ -359,20 +543,26 @@ describe("PointerSystem - pointer input", () => { ]), 0, true, - undefined + undefined, + undefined, + undefined, + [ + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }) + ] ), - new PointerEvent("pointermove", { clientX: 3, clientY: 2 }) + new Message(System.MESSAGE_UPDATE, 1.0) ], [ - "Pointer move, fullscreen, locked pointer position set, one camera", + "Update, pointer event, fullscreen, locked pointer position set, one camera", undefined, - new TestPointerSystem(new FakeMessageBus(), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ @@ -382,22 +572,33 @@ describe("PointerSystem - pointer input", () => { ]), 0, true, - new Vector(12, 5) + new Vector(12, 5), + undefined, + undefined, + undefined, + [ + new Pointer( + new PointerEvent("pointerup", { clientX: 3, clientY: 2, movementX: 10, movementY: 3 }), + new Vector(2.4000000953674316, 1), + [ + new PointerCameraInfo( + new FakeEntity(0), + new Vector(2.4000000953674316, 1), + new Vector(12, 5), + false + ) + ] + ) + ] ), - new TestPointerSystem(new FakeMessageBus([new Reactor("Publish", (message: Message) => { - expect(message).toEqual(new Message( - "pointermove", - new Pointer(new PointerEvent("pointermove", { clientX: 3, clientY: 2, movementX: 10, movementY: 3 }), new Vector(2.4, 1), [ - new PointerCameraInfo(new FakeEntity(0), new Vector(2.4, 1), new Vector(12, 5), false), - ]) - )); - })]), ((): HTMLElement => { - const element = document.createElement("canvas"); - element.getBoundingClientRect = (): DOMRect => { - return new DOMRect(0, 0, 10, 10); - }; - return element; - })(), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ @@ -407,12 +608,147 @@ describe("PointerSystem - pointer input", () => { ]), 0, true, - new Vector(2, 2) + new Vector(2, 2), + undefined, + undefined, + [ + new PointerEvent("pointerup", { clientX: 3, clientY: 2, movementX: 10, movementY: 3 }) + ] ), - new PointerEvent("pointermove", { clientX: 3, clientY: 2, movementX: 10, movementY: 3 }) + new Message(System.MESSAGE_UPDATE, 1.0) ], [ - "Pointer up, one camera", + "Update, pointer message, not fullscreen, one camera, 3 stored pointer events, clear 2 previously published", + undefined, + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), + undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(10, 10)) + ])], + ]), + 0, + false, + undefined, + undefined, + undefined, + undefined, + [ + new Pointer( + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }), + new Vector(0.6000000238418579, 1.600000023841858), + [ + new PointerCameraInfo( + new FakeEntity(0), + new Vector(0.6000000238418579, 1.600000023841858), + new Vector(3, 8), + false + ) + ] + ), + new Pointer( + new PointerEvent("pointerdown", { clientX: 6, clientY: 4 }), + new Vector(1.2000000476837158, 1.2000000476837158), + [ + new PointerCameraInfo( + new FakeEntity(0), + new Vector(1.2000000476837158, 1.2000000476837158), + new Vector(6, 6), + false + ) + ] + ), + new Pointer( + new PointerEvent("pointerup", { clientX: 15, clientY: 3 }), + new Vector(3, 1.399999976158142), + [ + new PointerCameraInfo( + new FakeEntity(0), + new Vector(3, 1.399999976158142), + new Vector(15, 7), + false + ) + ] + ) + ], + ), + new PointerSystem(new FakeMessageBus(), + ((): HTMLElement => { + const element = document.createElement("canvas"); + element.getBoundingClientRect = (): DOMRect => { + return new DOMRect(0, 0, 10, 10); + }; + return element; + })(), + undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(1, 1), new Vector(10, 10)) + ])], + ]), + 0, + false, + undefined, + undefined, + undefined, + [ + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }), + new PointerEvent("pointerdown", { clientX: 6, clientY: 4 }), + new PointerEvent("pointerup", { clientX: 15, clientY: 3 }) + ], + [ + new Pointer(new PointerEvent("pointermove"), new Vector(0,0), []), + new Pointer(new PointerEvent("pointerdown"), new Vector(3,2), []), + ] + ), + new Message(System.MESSAGE_UPDATE, 1.0) + ], + ])("%p", (description: string, expected: Error | undefined, expectedState: PointerSystem, system: PointerSystem, message: IMessage) => { + if (expected instanceof Error) { + expect(() => { + system.OnMessage(message); + }).toThrow(expected); + } else { + expect(system.OnMessage(message)).toEqual(expected); + } + expect(system).toEqual(expectedState); + window.close(); + }); +}); + + +/** + * TestPointerSystem is an extension of the PointerSystem that exposes the pointer event functions, + * allows testing them without having to use JS event listeners + */ +class TestPointerSystem extends PointerSystem { + public SimulatePointerEvent(event: PointerEvent): void { + this.pointerEvent(event); + } + + public SimulateWheelEvent(event: WheelEvent): void { + this.wheelEvent(event); + } + + public SimulateMoveEvent(event: PointerEvent): void { + this.moveEvent(event); + } +} + +describe("PointerSystem - pointer event", () => { + type TestTuple = [string, Error | undefined, PointerSystem, TestPointerSystem, PointerEvent]; + test.each([ + [ + "Pointer up, add to events to be published", undefined, new TestPointerSystem(new FakeMessageBus(), ((): HTMLElement => { const element = document.createElement("canvas"); @@ -422,21 +758,19 @@ describe("PointerSystem - pointer input", () => { return element; })(), undefined, - new Map([ - [0, new SystemEntity(new FakeEntity(0), [ - new Transform(), - new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(5, 5), new Vector(10, 10)) - ])] - ]), + undefined, 0, + undefined, + undefined, + undefined, + undefined, + [ + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }) + ], + undefined ), new TestPointerSystem(new FakeMessageBus([new Reactor("Publish", (message: Message) => { - expect(message).toEqual(new Message( - "pointerup", - new Pointer(new PointerEvent("pointerup", { clientX: 0, clientY: 0 }), new Vector(0, 2), [ - new PointerCameraInfo(new FakeEntity(0), new Vector(0, 0.4), new Vector(0, 2), true), - ]) - )); + throw("publish fail"); })]), ((): HTMLElement => { const element = document.createElement("canvas"); element.getBoundingClientRect = (): DOMRect => { @@ -445,19 +779,33 @@ describe("PointerSystem - pointer input", () => { return element; })(), undefined, - new Map([ - [0, new SystemEntity(new FakeEntity(0), [ - new Transform(), - new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(5, 5), new Vector(10, 10)) - ])] - ]), + undefined, 0, undefined, + undefined, + undefined, + undefined, + [], + undefined ), - new PointerEvent("pointerup", { clientX: 0, clientY: 0 }) + new PointerEvent("pointerup", { clientX: 3, clientY: 2 }) ], + ])("%p", (description: string, expected: Error | undefined, expectedState: PointerSystem, system: TestPointerSystem, + event: PointerEvent) => { + if (expected instanceof Error) { + expect(() => { system.SimulatePointerEvent(event); }).toThrow(expected); + } else { + system.SimulatePointerEvent(event); + } + expect(system).toEqual(expectedState); + }); +}); + +describe("PointerSystem - pointer move", () => { + type TestTuple = [string, Error | undefined, PointerSystem, TestPointerSystem, PointerEvent]; + test.each([ [ - "Pointer down, one camera", + "Pointer move, add to events to be published", undefined, new TestPointerSystem(new FakeMessageBus(), ((): HTMLElement => { const element = document.createElement("canvas"); @@ -467,21 +815,15 @@ describe("PointerSystem - pointer input", () => { return element; })(), undefined, - new Map([ - [0, new SystemEntity(new FakeEntity(0), [ - new Transform(), - new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(5, 5), new Vector(10, 10)) - ])] - ]), + undefined, 0, + undefined, + undefined, + undefined, + new PointerEvent("pointermove", { clientX: 3, clientY: 2 }) ), new TestPointerSystem(new FakeMessageBus([new Reactor("Publish", (message: Message) => { - expect(message).toEqual(new Message( - "pointerdown", - new Pointer(new PointerEvent("pointerdown", { clientX: 0, clientY: 0 }), new Vector(0, 2), [ - new PointerCameraInfo(new FakeEntity(0), new Vector(0, 0.4), new Vector(0, 2), true), - ]) - )); + throw("publish fail"); })]), ((): HTMLElement => { const element = document.createElement("canvas"); element.getBoundingClientRect = (): DOMRect => { @@ -490,43 +832,33 @@ describe("PointerSystem - pointer input", () => { return element; })(), undefined, - new Map([ - [0, new SystemEntity(new FakeEntity(0), [ - new Transform(), - new Camera(new Color(1, 0, 0), new Vector(0, 0), new Vector(5, 5), new Vector(10, 10)) - ])] - ]), + undefined, 0, + undefined, + undefined, + undefined, + undefined, ), - new PointerEvent("pointerdown", { clientX: 0, clientY: 0 }) + new PointerEvent("pointermove", { clientX: 3, clientY: 2 }) ], ])("%p", (description: string, expected: Error | undefined, expectedState: PointerSystem, system: TestPointerSystem, event: PointerEvent) => { if (expected instanceof Error) { expect(() => { system.SimulatePointerEvent(event); }).toThrow(expected); } else { - system.SimulatePointerEvent(event); + system.SimulateMoveEvent(event); } expect(system).toEqual(expectedState); }); }); -/** - * TestWheelSystem is an extension of the PointerSystem that exposes the wheel event functions, - * allows testing them without having to use JS event listeners - */ -class TestWheelSystem extends PointerSystem { - public SimulateWheelEvent(event: WheelEvent): void { - this.wheelEvent(event); - } -} describe("PointerSystem - pointer input", () => { - type TestTuple = [string, Error | undefined, PointerSystem, TestWheelSystem, WheelEvent]; + type TestTuple = [string, Error | undefined, PointerSystem, TestPointerSystem, WheelEvent]; test.each([ [ "Wheel event triggered", undefined, - new TestWheelSystem(new FakeMessageBus(), ((): HTMLElement => { + new TestPointerSystem(new FakeMessageBus(), ((): HTMLElement => { const element = document.createElement("canvas"); element.getBoundingClientRect = (): DOMRect => { return new DOMRect(0, 0, 10, 10); @@ -540,7 +872,7 @@ describe("PointerSystem - pointer input", () => { undefined, new WheelEvent("test"), ), - new TestWheelSystem(new FakeMessageBus([new Reactor("Publish", (message: Message) => { + new TestPointerSystem(new FakeMessageBus([new Reactor("Publish", (message: Message) => { throw("publish fail"); })]), ((): HTMLElement => { const element = document.createElement("canvas"); @@ -558,7 +890,8 @@ describe("PointerSystem - pointer input", () => { ), new WheelEvent("test") ], - ])("%p", (description: string, expected: Error | undefined, expectedState: PointerSystem, system: TestWheelSystem, event: WheelEvent) => { + ])("%p", (description: string, expected: Error | undefined, expectedState: PointerSystem, system: TestPointerSystem, + event: WheelEvent) => { if (expected instanceof Error) { expect(() => { system.SimulateWheelEvent(event); }).toThrow(expected); } else { diff --git a/src/standard/pointer/pointer_system.ts b/src/standard/pointer/pointer_system.ts index 8585404..288efb0 100644 --- a/src/standard/pointer/pointer_system.ts +++ b/src/standard/pointer/pointer_system.ts @@ -52,16 +52,28 @@ class PointerSystem extends System { */ private isFullscreen: boolean; /** - * Position of the pointer if it is locked, used with the PointerAPI to - * keep track of pointer position using movementX and movementY. + * Position of the pointer if it is locked, used with the PointerAPI to keep track of pointer position using + * movementX and movementY. * If it is undefined there is no pointer lock. */ private lockedPointerPosition: Vector | undefined; /** - * Last wheel event captured, stored here to throttle a potentially - * frequently firing event + * Last wheel event captured, stored here to throttle a potentially frequently firing event. */ private lastWheelEvent: WheelEvent | undefined; + /** + * Last pointer move event captured, stored here to throttle a potentially frequently firing event. + */ + private lastMoveEvent: PointerEvent | undefined; + /** + * The pointers published in the last update. + * Used to free up objects back into pools. + */ + private lastPublishedPointers: Pointer[]; + /** + * The pointer events recieved since the last update that should be published. + */ + private pointerEventsToPublish: PointerEvent[]; constructor(messageBus: IMessageBus, inputElement: HTMLElement, scene?: IScene, @@ -69,15 +81,21 @@ class PointerSystem extends System { subscriberID?: number, isFullscreen = false, lockedPointerPosition?: Vector, - lastWheelEvent?: WheelEvent) { + lastWheelEvent?: WheelEvent, + lastMoveEvent?: PointerEvent, + pointersToPublish: PointerEvent[] = [], + lastPublishedPointers: Pointer[] = []) { super(messageBus, scene, PointerSystem.EVALUATOR, entities, subscriberID); this.messageBus.Subscribe(this, [FullscreenSystem.MESSAGE_ENTER_FULLSCREEN, FullscreenSystem.MESSAGE_EXIT_FULLSCREEN]); this.inputElement = inputElement; + this.pointerEventsToPublish = pointersToPublish; this.isFullscreen = isFullscreen; this.lockedPointerPosition = lockedPointerPosition; this.lastWheelEvent = lastWheelEvent; + this.lastMoveEvent = lastMoveEvent; + this.lastPublishedPointers = lastPublishedPointers; // Set up listeners - this.inputElement.addEventListener("pointermove", this.pointerEvent.bind(this)); + this.inputElement.addEventListener("pointermove", this.moveEvent.bind(this)); this.inputElement.addEventListener("pointerdown", this.pointerEvent.bind(this)); this.inputElement.addEventListener("pointerup", this.pointerEvent.bind(this)); this.inputElement.addEventListener("wheel", this.wheelEvent.bind(this)); @@ -99,11 +117,28 @@ class PointerSystem extends System { } public Update(): void { + // If move event waiting, process it before publishing it + if (this.lastMoveEvent !== undefined) { + this.pointerEventsToPublish.push(this.lastMoveEvent); + this.lastMoveEvent = undefined; + } // If wheel event waiting, publish it - in a throttled way if (this.lastWheelEvent !== undefined) { this.messageBus.Publish(new Message("wheel", this.lastWheelEvent)); this.lastWheelEvent = undefined; } + // Free any previously published pointers + for (const freePointer of this.lastPublishedPointers) { + freePointer.Free(); + } + this.lastPublishedPointers = []; + // Publish any stored pointer events + for (const pointerEvent of this.pointerEventsToPublish) { + const pointer = this.processPointerEvent(pointerEvent); + this.messageBus.Publish(new Message(pointer.event.type, pointer)); + this.lastPublishedPointers.push(pointer); + } + this.pointerEventsToPublish = []; } /** @@ -116,6 +151,14 @@ class PointerSystem extends System { this.lastWheelEvent = event; } + protected moveEvent(event: PointerEvent): void { + this.lastMoveEvent = event; + } + + protected pointerEvent(event: PointerEvent): void { + this.pointerEventsToPublish.push(event); + } + /** * When a Pointer Event occurs; dispatches the pointer event with extra info * through the JamJar messaging system as a Pointer. @@ -124,7 +167,7 @@ class PointerSystem extends System { * within a camera's bounds. * @param {PointerEvent} event Pointer Event */ - protected pointerEvent(event: PointerEvent): void { + private processPointerEvent(event: PointerEvent): Pointer { // Get HTML element dimensions, calculate relative position within element const rect = this.inputElement.getBoundingClientRect(); let pointerX = event.clientX; @@ -137,13 +180,15 @@ class PointerSystem extends System { // lockedPointerPosition is undefined when not fullscreen, when fullscreen it is used to // keep track of the last pointer position if (this.lockedPointerPosition !== undefined) { - this.lockedPointerPosition = this.lockedPointerPosition.Add(Vector.New(event.movementX, event.movementY)); + this.lockedPointerPosition.x += event.movementX; + this.lockedPointerPosition.y += event.movementY; pointerX = this.lockedPointerPosition.x; pointerY = this.lockedPointerPosition.y; } else { this.lockedPointerPosition = Vector.New(event.clientX, event.clientY); } } + const elementPosition = Vector.New( ((pointerX - rect.left) - (rect.width / 2)) / (rect.width / 2), -((pointerY - rect.top) - (rect.height / 2)) / (rect.height / 2) @@ -186,7 +231,7 @@ class PointerSystem extends System { withinBounds )); } - this.messageBus.Publish(new Message(event.type, new Pointer(event, elementPosition, pointerCameraInfos))); + return new Pointer(event, elementPosition, pointerCameraInfos); } } diff --git a/src/standard/primitive/primitive_system.test.ts b/src/standard/primitive/primitive_system.test.ts index 320ce21..e37106e 100644 --- a/src/standard/primitive/primitive_system.test.ts +++ b/src/standard/primitive/primitive_system.test.ts @@ -32,6 +32,10 @@ import UI from "../ui/ui"; import Camera from "../camera/camera"; import PrimitiveSystem from "./primitive_system"; import Primitive from "./primitive"; +import FrustumCuller from "../frustum_culler/frustum_culler"; +import AllCollideAlgorithm from "../collision/algorithm/all_collide_algorithm"; +import IRenderable from "../../rendering/irenderable"; +import NoneCollideAlgorithm from "../collision/algorithm/none_collide_algorithm"; describe("PrimitiveSystem - OnMessage", () => { type TestTuple = [string, Error | undefined, PrimitiveSystem, PrimitiveSystem, IMessage]; @@ -39,15 +43,15 @@ describe("PrimitiveSystem - OnMessage", () => { [ "Unknown message type", undefined, - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new PrimitiveSystem(new FakeMessageBus()), new Message("unknown") ], [ "Pre render no payload", undefined, - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message(Game.MESSAGE_PRE_RENDER) ], [ @@ -55,6 +59,7 @@ describe("PrimitiveSystem - OnMessage", () => { new Error("fail to publish"), new PrimitiveSystem(new FakeMessageBus([new Reactor("Publish", () => { throw ("fail to publish"); })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -65,6 +70,7 @@ describe("PrimitiveSystem - OnMessage", () => { ), new PrimitiveSystem(new FakeMessageBus([new Reactor("Publish", () => { throw ("fail to publish"); })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -76,10 +82,12 @@ describe("PrimitiveSystem - OnMessage", () => { new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render render 3 primitives", + "Pre render, skip 3 primitives, no camera", undefined, - new PrimitiveSystem(new FakeMessageBus(), + new PrimitiveSystem( + new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -96,8 +104,120 @@ describe("PrimitiveSystem - OnMessage", () => { ]), 0 ), - new PrimitiveSystem(new FakeMessageBus(), + new PrimitiveSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(0); + })]), + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])] + ]), + 0 + ), + new Message(Game.MESSAGE_PRE_RENDER, 1.0) + ], + [ + "Pre render, skip 3 primitives, one camera, cull", + undefined, + new PrimitiveSystem( + new FakeMessageBus(), + undefined, + new FrustumCuller(new NoneCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Transform(), + new Camera() + ])] + ]), + 0 + ), + new PrimitiveSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(3)?.length).toEqual(0); + })]), + undefined, + new FrustumCuller(new NoneCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Transform(), + new Camera() + ])] + ]), + 0 + ), + new Message(Game.MESSAGE_PRE_RENDER, 1.0) + ], + [ + "Pre render, render 3 primitives, one camera", + undefined, + new PrimitiveSystem( + new FakeMessageBus(), + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Transform(), + new Camera() + ])] + ]), + 0 + ), + new PrimitiveSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(3)?.length).toEqual(3); + })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -110,6 +230,10 @@ describe("PrimitiveSystem - OnMessage", () => { [2, new SystemEntity(new FakeEntity(2), [ new Transform(), new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Transform(), + new Camera() ])] ]), 0 @@ -119,8 +243,10 @@ describe("PrimitiveSystem - OnMessage", () => { [ "Pre render, UI, render 2, skip 1 no camera", undefined, - new PrimitiveSystem(new FakeMessageBus(), + new PrimitiveSystem( + new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -144,8 +270,13 @@ describe("PrimitiveSystem - OnMessage", () => { ]), 0 ), - new PrimitiveSystem(new FakeMessageBus(), + new PrimitiveSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(2)?.length).toEqual(2); + })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -171,11 +302,75 @@ describe("PrimitiveSystem - OnMessage", () => { ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], + [ + "Pre render, UI, skip 3, one camera, cull", + undefined, + new PrimitiveSystem( + new FakeMessageBus(), + undefined, + new FrustumCuller(new NoneCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new UI(new FakeEntity(2)), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new UI(new FakeEntity(2)), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Camera() + ])], + [3, new SystemEntity(new FakeEntity(4), [ + new Transform(), + new UI(new FakeEntity(2)), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])] + ]), + 0 + ), + new PrimitiveSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(2)?.length).toEqual(0); + })]), + undefined, + new FrustumCuller(new NoneCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new UI(new FakeEntity(2)), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new UI(new FakeEntity(2)), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Camera() + ])], + [3, new SystemEntity(new FakeEntity(4), [ + new Transform(), + new UI(new FakeEntity(2)), + new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) + ])] + ]), + 0 + ), + new Message(Game.MESSAGE_PRE_RENDER, 1.0) + ], [ "Pre render, UI, render 2, skip 1 invalid camera", undefined, - new PrimitiveSystem(new FakeMessageBus(), + new PrimitiveSystem( + new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -199,8 +394,13 @@ describe("PrimitiveSystem - OnMessage", () => { ]), 0 ), - new PrimitiveSystem(new FakeMessageBus(), + new PrimitiveSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(2)?.length).toEqual(2); + })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -231,6 +431,7 @@ describe("PrimitiveSystem - OnMessage", () => { undefined, new PrimitiveSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -239,7 +440,7 @@ describe("PrimitiveSystem - OnMessage", () => { ]), 0 ), - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Transform(), new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) @@ -250,6 +451,7 @@ describe("PrimitiveSystem - OnMessage", () => { undefined, new PrimitiveSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -259,7 +461,7 @@ describe("PrimitiveSystem - OnMessage", () => { ]), 0 ), - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Transform(), new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)), @@ -271,6 +473,7 @@ describe("PrimitiveSystem - OnMessage", () => { undefined, new PrimitiveSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -279,7 +482,7 @@ describe("PrimitiveSystem - OnMessage", () => { ]), 0 ), - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Transform(), new Camera() @@ -290,6 +493,7 @@ describe("PrimitiveSystem - OnMessage", () => { undefined, new PrimitiveSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -312,6 +516,7 @@ describe("PrimitiveSystem - OnMessage", () => { ), new PrimitiveSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -336,8 +541,8 @@ describe("PrimitiveSystem - OnMessage", () => { [ "Correctly reject non-ui primitive new entity, missing transform", undefined, - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Primitive(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0, Polygon.RectangleByDimensions(2, 2)) ]]) @@ -345,15 +550,15 @@ describe("PrimitiveSystem - OnMessage", () => { [ "Correctly reject non-ui primitive new entity, missing primitive", undefined, - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [new Transform()]]) ], [ "Correctly reject camera new entity, missing transform", undefined, - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Camera() ]]) @@ -361,8 +566,8 @@ describe("PrimitiveSystem - OnMessage", () => { [ "Correctly reject camera new entity, missing camera", undefined, - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), - new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new PrimitiveSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [new Transform()]]) ], ])("%p", (description: string, expected: Error | undefined, expectedState: PrimitiveSystem, PrimitiveSystem: PrimitiveSystem, message: IMessage) => { @@ -375,4 +580,4 @@ describe("PrimitiveSystem - OnMessage", () => { } expect(PrimitiveSystem).toEqual(expectedState); }); -}); \ No newline at end of file +}); diff --git a/src/standard/primitive/primitive_system.ts b/src/standard/primitive/primitive_system.ts index c2f548e..e0a22e1 100644 --- a/src/standard/primitive/primitive_system.ts +++ b/src/standard/primitive/primitive_system.ts @@ -30,6 +30,10 @@ import RenderSystem from "../render/render_system"; import IRenderable from "../../rendering/irenderable"; import Camera from "../camera/camera"; import Primitive from "./primitive"; +import IFrustumCuller from "../frustum_culler/ifrustum_culler"; +import FrustumCuller from "../frustum_culler/frustum_culler"; +import Vector from "../../geometry/vector"; +import AABB from "../../shape/aabb"; /** * PrimitiveSystem handles processing primitives for render systems, tracking @@ -47,11 +51,15 @@ class PrimitiveSystem extends System { )); }; + private frustumCuller: IFrustumCuller; + constructor(messageBus: IMessageBus, scene?: IScene, + frustumCuller: IFrustumCuller = new FrustumCuller(), entities?: Map, subscriberID?: number) { super(messageBus, scene, PrimitiveSystem.EVALUATOR, entities, subscriberID); + this.frustumCuller = frustumCuller; this.messageBus.Subscribe(this, Game.MESSAGE_PRE_RENDER); } @@ -70,64 +78,83 @@ class PrimitiveSystem extends System { } private preparePrimitives(alpha: number): void { - const renderables: IRenderable[] = []; - // Get primitive entities + const renderables: Map = new Map(); + + const cameraEntities = [...this.entities.values()].filter((entity) => { + return entity.Get(Camera.KEY); + }); + const primitiveEntities = [...this.entities.values()].filter((entity) => { return entity.Get(Primitive.KEY); }); - for (const entity of primitiveEntities) { - const primitive = entity.Get(Primitive.KEY) as Primitive; - const transform = entity.Get(Transform.KEY) as Transform; - const ui = entity.Get(UI.KEY) as UI | undefined; - - if (ui === undefined) { - // Not UI - renderables.push(Renderable.New( - primitive.zOrder, - primitive.points.Copy(), - transform.InterpolatedMatrix4D(alpha), - primitive.material, - primitive.drawMode, - undefined, - )); - } else { - // UI - // Get the camera the UI component is targeting - const cameraEntity = this.entities.get(ui.camera.id); - if (cameraEntity === undefined) { - // If no camera found, skip this entity - continue; - } - // Get components of the camera entity - const camera = cameraEntity.Get(Camera.KEY) as Camera | undefined; - const cameraTransform = cameraEntity.Get(Transform.KEY) as Transform | undefined; - if (camera === undefined || cameraTransform === undefined) { - // If the components are not found, must not be a valid camera, skip this entity - continue; - } + const viewportAABB = new AABB(Vector.New(2,2)); + + for (const cameraEntity of cameraEntities) { + const camera = cameraEntity.Get(Camera.KEY) as Camera; + const cameraTransform = cameraEntity.Get(Transform.KEY) as Transform; + + const cameraViewShape = new AABB(camera.virtualScale.Copy()).Transform(cameraTransform); - const relativeTransform = new Transform( - // camera position + UI element position * camera virtual scale - cameraTransform.position.Copy() - .Add(transform.position.Copy().Multiply(camera.virtualScale.Copy().Scale(0.5))), - // element scale * camera virtual scale - transform.scale.Copy().Multiply(camera.virtualScale), - transform.angle - ); - - // Create the renderable for use by rendering systems - renderables.push(Renderable.New( - primitive.zOrder, - primitive.points.Copy(), - relativeTransform.InterpolatedMatrix4D(alpha), - primitive.material, - primitive.drawMode, - ui.camera, - )); + const cameraRenderables: IRenderable[] = []; + + for (const entity of primitiveEntities) { + const primitive = entity.Get(Primitive.KEY) as Primitive; + const transform = entity.Get(Transform.KEY) as Transform; + const ui = entity.Get(UI.KEY) as UI | undefined; + + if (ui === undefined) { + // Not UI + + if (this.frustumCuller.Cull(cameraViewShape, primitive.points.Transform(transform))) { + // Not in camera view, skip rendering + continue; + } + + cameraRenderables.push(Renderable.New( + primitive.zOrder, + primitive.points.Copy(), + transform.InterpolatedMatrix4D(alpha), + primitive.material, + primitive.drawMode, + undefined, + )); + } else { + // UI + if (cameraEntity.entity.id !== ui.camera.id) { + // If camera is not the one targeted, skip + continue; + } + + if (this.frustumCuller.Cull(viewportAABB, primitive.points.Transform(transform))) { + // Not in camera view, skip rendering + continue; + } + + const relativeTransform = new Transform( + // camera position + UI element position * camera virtual scale + cameraTransform.position.Copy() + .Add(transform.position.Copy().Multiply(camera.virtualScale.Copy().Scale(0.5))), + // element scale * camera virtual scale + transform.scale.Copy().Multiply(camera.virtualScale), + transform.angle + ); + + // Create the renderable for use by rendering systems + cameraRenderables.push(Renderable.New( + primitive.zOrder, + primitive.points.Copy(), + relativeTransform.InterpolatedMatrix4D(alpha), + primitive.material, + primitive.drawMode, + ui.camera, + )); + } } + renderables.set(cameraEntity.entity.id, cameraRenderables); } - this.messageBus.Publish(new Message(RenderSystem.MESSAGE_LOAD_RENDERABLES, renderables)); + viewportAABB.Free(); + this.messageBus.Publish(new Message>(RenderSystem.MESSAGE_LOAD_RENDERABLES, renderables)); } } diff --git a/src/standard/render/render_system.test.ts b/src/standard/render/render_system.test.ts index 2adedcf..02b9096 100644 --- a/src/standard/render/render_system.test.ts +++ b/src/standard/render/render_system.test.ts @@ -84,13 +84,13 @@ describe("WebGLSystem - OnMessage", () => { new FakeMessageBus(), undefined, undefined, - [ + new Map([[0,[ new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test1", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test2", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test3", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test4", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test5", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP) - ], + ]]]), undefined, 0 ), @@ -98,20 +98,20 @@ describe("WebGLSystem - OnMessage", () => { new FakeMessageBus(), undefined, undefined, - [ + new Map([[0,[ new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test1", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test2", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test3", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP) - ], + ]]]), undefined, 0 ), - new Message( + new Message>( RenderSystem.MESSAGE_LOAD_RENDERABLES, - [ + new Map([[0,[ new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test4", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test5", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP) - ] + ]]]) ) ], [ @@ -121,11 +121,11 @@ describe("WebGLSystem - OnMessage", () => { new FakeMessageBus(), undefined, undefined, - [ + new Map([[0,[ new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test1", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test2", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test3", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), - ], + ]]]), undefined, 0 ), @@ -137,13 +137,13 @@ describe("WebGLSystem - OnMessage", () => { undefined, 0 ), - new Message( + new Message>( RenderSystem.MESSAGE_LOAD_RENDERABLES, - [ + new Map([[0,[ new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test1", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test2", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test3", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), - ] + ]]]) ) ], [ @@ -153,9 +153,9 @@ describe("WebGLSystem - OnMessage", () => { new FakeMessageBus(), undefined, undefined, - [ + new Map([[0,[ new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test1", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), - ], + ]]]), undefined, 0 ), @@ -167,11 +167,11 @@ describe("WebGLSystem - OnMessage", () => { undefined, 0 ), - new Message( + new Message>( RenderSystem.MESSAGE_LOAD_RENDERABLES, - [ + new Map([[0,[ new Renderable(0, Polygon.RectangleByDimensions(1,1), new Matrix4D(), new Material({ texture: new Texture("test1", Polygon.RectangleByDimensions(1,1))}), DrawMode.TRIANGLE_STRIP), - ] + ]]]) ) ], ])("%p", (description: string, expected: Error | undefined, expectedState: RenderSystem, system: RenderSystem, message: IMessage) => { @@ -184,4 +184,4 @@ describe("WebGLSystem - OnMessage", () => { } expect(system).toEqual(expectedState); }); -}); \ No newline at end of file +}); diff --git a/src/standard/render/render_system.ts b/src/standard/render/render_system.ts index 0539c20..074f986 100644 --- a/src/standard/render/render_system.ts +++ b/src/standard/render/render_system.ts @@ -37,12 +37,12 @@ abstract class RenderSystem extends System { /** * A list of things to be rendered. */ - protected renderables: IRenderable[]; + protected renderables: Map; constructor(messageBus: IMessageBus, scene?: IScene, evaluator?: Evaluator, - renderables: IRenderable[] = [], + renderables: Map = new Map(), entities?: Map, subscriberID?: number) { super(messageBus, scene, evaluator, entities, subscriberID); @@ -53,15 +53,24 @@ abstract class RenderSystem extends System { super.OnMessage(message); switch (message.type) { case RenderSystem.MESSAGE_LOAD_RENDERABLES: { - const renderMessage = message as Message; + const renderMessage = message as Message<[number, IRenderable[]][]>; if (renderMessage.payload === undefined) { return; } - this.renderables.push(...renderMessage.payload); + for (const cameraRenderGroup of renderMessage.payload) { + const existing = this.renderables.get(cameraRenderGroup[0]); + if (existing === undefined) { + this.renderables.set(cameraRenderGroup[0], cameraRenderGroup[1]); + continue; + } + + existing.push(...cameraRenderGroup[1]); + this.renderables.set(cameraRenderGroup[0], existing); + } break; } } } } -export default RenderSystem; \ No newline at end of file +export default RenderSystem; diff --git a/src/standard/sprite/sprite_system.test.ts b/src/standard/sprite/sprite_system.test.ts index ff87ee0..bc77f7d 100644 --- a/src/standard/sprite/sprite_system.test.ts +++ b/src/standard/sprite/sprite_system.test.ts @@ -32,6 +32,10 @@ import Material from "../../rendering/material/material"; import Texture from "../../rendering/texture/texture"; import UI from "../ui/ui"; import Camera from "../camera/camera"; +import FrustumCuller from "../frustum_culler/frustum_culler"; +import AllCollideAlgorithm from "../collision/algorithm/all_collide_algorithm"; +import IRenderable from "../../rendering/irenderable"; +import NoneCollideAlgorithm from "../collision/algorithm/none_collide_algorithm"; describe("SpriteSystem - OnMessage", () => { type TestTuple = [string, Error | undefined, SpriteSystem, SpriteSystem, IMessage]; @@ -39,15 +43,15 @@ describe("SpriteSystem - OnMessage", () => { [ "Unknown message type", undefined, - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new SpriteSystem(new FakeMessageBus()), new Message("unknown") ], [ "Pre render no payload", undefined, - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message(Game.MESSAGE_PRE_RENDER) ], [ @@ -55,6 +59,7 @@ describe("SpriteSystem - OnMessage", () => { new Error("fail to publish"), new SpriteSystem(new FakeMessageBus([new Reactor("Publish", () => { throw ("fail to publish"); })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -65,6 +70,7 @@ describe("SpriteSystem - OnMessage", () => { ), new SpriteSystem(new FakeMessageBus([new Reactor("Publish", () => { throw ("fail to publish"); })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -76,10 +82,12 @@ describe("SpriteSystem - OnMessage", () => { new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render render 3 sprites", + "Pre render, skip 3 sprites, no camera", undefined, - new SpriteSystem(new FakeMessageBus(), + new SpriteSystem( + new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -96,8 +104,12 @@ describe("SpriteSystem - OnMessage", () => { ]), 0 ), - new SpriteSystem(new FakeMessageBus(), + new SpriteSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(0); + })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -117,10 +129,123 @@ describe("SpriteSystem - OnMessage", () => { new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, UI, render 2, skip 1 no camera", + "Pre render, skip 3 sprites, cull", + undefined, + new SpriteSystem( + new FakeMessageBus(), + undefined, + new FrustumCuller(new NoneCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Camera(), + new Transform() + ])] + ]), + 0 + ), + new SpriteSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(3)?.length).toEqual(0); + })]), + undefined, + new FrustumCuller(new NoneCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Camera(), + new Transform() + ])] + ]), + 0 + ), + new Message(Game.MESSAGE_PRE_RENDER, 1.0) + ], + [ + "Pre render, render 3 sprites, one camera", + undefined, + new SpriteSystem( + new FakeMessageBus(), + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Camera(), + new Transform() + ])] + ]), + 0 + ), + new SpriteSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(3)?.length).toEqual(3); + })]), + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Camera(), + new Transform() + ])] + ]), + 0 + ), + new Message(Game.MESSAGE_PRE_RENDER, 1.0) + ], + [ + "Pre render, UI, render 2, skip 1, no camera", undefined, new SpriteSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -144,8 +269,13 @@ describe("SpriteSystem - OnMessage", () => { ]), 0 ), - new SpriteSystem(new FakeMessageBus(), + new SpriteSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(2)?.length).toEqual(2); + })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -171,11 +301,75 @@ describe("SpriteSystem - OnMessage", () => { ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], + [ + "Pre render, UI, skip 3, one camera, culled", + undefined, + new SpriteSystem( + new FakeMessageBus(), + undefined, + new FrustumCuller(new NoneCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new UI(new FakeEntity(3)), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new UI(new FakeEntity(3)), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new UI(new FakeEntity(3)), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Transform(), + new Camera() + ])] + ]), + 0 + ), + new SpriteSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(3)?.length).toEqual(0); + })]), + undefined, + new FrustumCuller(new NoneCollideAlgorithm()), + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new UI(new FakeEntity(3)), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new UI(new FakeEntity(3)), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [2, new SystemEntity(new FakeEntity(2), [ + new Transform(), + new UI(new FakeEntity(3)), + new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) + ])], + [3, new SystemEntity(new FakeEntity(3), [ + new Transform(), + new Camera() + ])] + ]), + 0 + ), + new Message(Game.MESSAGE_PRE_RENDER, 1.0) + ], [ "Pre render, UI, render 2, skip 1 invalid camera", undefined, - new SpriteSystem(new FakeMessageBus(), + new SpriteSystem( + new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -191,7 +385,7 @@ describe("SpriteSystem - OnMessage", () => { new Transform(), new Camera() ])], - [3, new SystemEntity(new FakeEntity(4), [ + [3, new SystemEntity(new FakeEntity(3), [ new Transform(), new UI(new FakeEntity(1)), new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) @@ -199,8 +393,13 @@ describe("SpriteSystem - OnMessage", () => { ]), 0 ), - new SpriteSystem(new FakeMessageBus(), + new SpriteSystem( + new FakeMessageBus([new Reactor("Publish", (message: Message>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(2)?.length).toEqual(2); + })]), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -216,7 +415,7 @@ describe("SpriteSystem - OnMessage", () => { new Transform(), new Camera() ])], - [3, new SystemEntity(new FakeEntity(4), [ + [3, new SystemEntity(new FakeEntity(3), [ new Transform(), new UI(new FakeEntity(1)), new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) @@ -231,6 +430,7 @@ describe("SpriteSystem - OnMessage", () => { undefined, new SpriteSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -239,7 +439,7 @@ describe("SpriteSystem - OnMessage", () => { ]), 0 ), - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Transform(), new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) @@ -250,6 +450,7 @@ describe("SpriteSystem - OnMessage", () => { undefined, new SpriteSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -259,7 +460,7 @@ describe("SpriteSystem - OnMessage", () => { ]), 0 ), - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Transform(), new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0), @@ -271,6 +472,7 @@ describe("SpriteSystem - OnMessage", () => { undefined, new SpriteSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -279,7 +481,7 @@ describe("SpriteSystem - OnMessage", () => { ]), 0 ), - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Transform(), new Camera() @@ -290,6 +492,7 @@ describe("SpriteSystem - OnMessage", () => { undefined, new SpriteSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -312,6 +515,7 @@ describe("SpriteSystem - OnMessage", () => { ), new SpriteSystem(new FakeMessageBus(), undefined, + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -336,8 +540,8 @@ describe("SpriteSystem - OnMessage", () => { [ "Correctly reject non-ui sprite new entity, missing transform", undefined, - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Sprite(new Material({ texture: new Texture("test", Polygon.RectangleByDimensions(1,1)) }), 0) ]]) @@ -345,15 +549,15 @@ describe("SpriteSystem - OnMessage", () => { [ "Correctly reject non-ui sprite new entity, missing sprite", undefined, - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [new Transform()]]) ], [ "Correctly reject camera new entity, missing transform", undefined, - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [ new Camera() ]]) @@ -361,8 +565,8 @@ describe("SpriteSystem - OnMessage", () => { [ "Correctly reject camera new entity, missing camera", undefined, - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), - new SpriteSystem(new FakeMessageBus(), undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), + new SpriteSystem(new FakeMessageBus(), undefined, undefined, undefined, 0), new Message<[IEntity, Component[]]>(System.MESSAGE_REGISTER, [new FakeEntity(0), [new Transform()]]) ], ])("%p", (description: string, expected: Error | undefined, expectedState: SpriteSystem, spriteSystem: SpriteSystem, message: IMessage) => { @@ -375,4 +579,4 @@ describe("SpriteSystem - OnMessage", () => { } expect(spriteSystem).toEqual(expectedState); }); -}); \ No newline at end of file +}); diff --git a/src/standard/sprite/sprite_system.ts b/src/standard/sprite/sprite_system.ts index 2be54c6..5873f72 100644 --- a/src/standard/sprite/sprite_system.ts +++ b/src/standard/sprite/sprite_system.ts @@ -32,6 +32,10 @@ import IRenderable from "../../rendering/irenderable"; import Camera from "../camera/camera"; import DrawMode from "../../rendering/draw_mode"; import Polygon from "../../shape/polygon"; +import IFrustumCuller from "../frustum_culler/ifrustum_culler"; +import FrustumCuller from "../frustum_culler/frustum_culler"; +import AABB from "../../shape/aabb"; +import Vector from "../../geometry/vector"; /** * SpriteSystem handles converting sprites into renderable objects that are fed into @@ -50,11 +54,15 @@ class SpriteSystem extends System { )); }; + private frustumCuller: IFrustumCuller; + constructor(messageBus: IMessageBus, scene?: IScene, + frustumCuller: IFrustumCuller = new FrustumCuller(), entities?: Map, subscriberID?: number) { super(messageBus, scene, SpriteSystem.EVALUATOR, entities, subscriberID); + this.frustumCuller = frustumCuller; this.messageBus.Subscribe(this, Game.MESSAGE_PRE_RENDER); } @@ -73,69 +81,93 @@ class SpriteSystem extends System { } private prepareSprites(alpha: number): void { - const renderables: IRenderable[] = []; + const renderables: Map = new Map(); + // Get camera entities + const cameraEntities = [...this.entities.values()].filter((entity) => { + return entity.Get(Camera.KEY); + }); // Get sprite entities const spriteEntities = [...this.entities.values()].filter((entity) => { return entity.Get(Sprite.KEY); }); - for (const entity of spriteEntities) { - const sprite = entity.Get(Sprite.KEY) as Sprite; - const transform = entity.Get(Transform.KEY) as Transform; - const ui = entity.Get(UI.KEY) as UI | undefined; - - if (ui === undefined) { - // Not UI - renderables.push(Renderable.New( - sprite.zOrder, - Polygon.QuadByDimensions(1, 1, 0, 0), - transform.InterpolatedMatrix4D(alpha), - sprite.material.Copy(), - DrawMode.TRIANGLES, - undefined, - )); - } else { - // UI - // Get the camera the UI component is targeting - const cameraEntity = this.entities.get(ui.camera.id); - if (cameraEntity === undefined) { - // If no camera found, skip this entity - continue; - } - // Get components of the camera entity - const camera = cameraEntity.Get(Camera.KEY) as Camera | undefined; - const cameraTransform = cameraEntity.Get(Transform.KEY) as Transform | undefined; - if (camera === undefined || cameraTransform === undefined) { - // If the components are not found, must not be a valid camera, skip this entity - continue; + const viewportAABB = new AABB(Vector.New(2,2)); + + for (const cameraEntity of cameraEntities) { + const camera = cameraEntity.Get(Camera.KEY) as Camera; + const cameraTransform = cameraEntity.Get(Transform.KEY) as Transform; + + const cameraViewShape = new AABB(camera.virtualScale.Copy()).Transform(cameraTransform); + + const cameraRenderables: IRenderable[] = []; + + for (const spriteEntity of spriteEntities) { + const sprite = spriteEntity.Get(Sprite.KEY) as Sprite; + const transform = spriteEntity.Get(Transform.KEY) as Transform; + const ui = spriteEntity.Get(UI.KEY) as UI | undefined; + + if (ui === undefined) { + // Not UI + if (this.frustumCuller.Cull(cameraViewShape, new AABB(Vector.New(1,1)).Transform(transform))) { + // Not in camera view, skip rendering + continue; + } + + cameraRenderables.push(Renderable.New( + sprite.zOrder, + Polygon.QuadByDimensions(1, 1, 0, 0), + transform.InterpolatedMatrix4D(alpha), + sprite.material.Copy(), + DrawMode.TRIANGLES, + undefined, + )); + } else { + // UI + if (cameraEntity.entity.id !== ui.camera.id) { + // If camera is not the one targeted, skip + continue; + } + + if (this.frustumCuller.Cull(viewportAABB, new AABB(Vector.New(1,1)).Transform(transform))) { + // Not in camera view, skip rendering + continue; + } + + const cameraVirtualScaleHalf = camera.virtualScale.Copy().Scale(0.5); + const cameraRelativePosition = transform.position.Copy().Multiply(cameraVirtualScaleHalf); + + cameraVirtualScaleHalf.Free(); + + const relativeTransform = new Transform( + // camera position + UI element position * camera virtual scale + cameraTransform.position.Copy().Add(cameraRelativePosition), + // element scale * camera virtual scale + transform.scale.Copy().Multiply(camera.virtualScale), + transform.angle + ); + + cameraRelativePosition.Free(); + + const matrix = relativeTransform.InterpolatedMatrix4D(alpha); + + relativeTransform.Free(); + + // Create the renderable for use by rendering systems + cameraRenderables.push(Renderable.New( + sprite.zOrder, + Polygon.QuadByDimensions(1, 1, 0, 0), + matrix, + sprite.material.Copy(), + DrawMode.TRIANGLES, + ui.camera, + )); } - - - const relativeTransform = new Transform( - // camera position + UI element position * camera virtual scale - cameraTransform.position.Copy() - .Add(transform.position.Copy().Multiply(camera.virtualScale.Copy().Scale(0.5))), - // element scale * camera virtual scale - transform.scale.Copy().Multiply(camera.virtualScale), - transform.angle - ); - - const matrix = relativeTransform.InterpolatedMatrix4D(alpha); - - relativeTransform.Free(); - - // Create the renderable for use by rendering systems - renderables.push(Renderable.New( - sprite.zOrder, - Polygon.QuadByDimensions(1, 1, 0, 0), - matrix, - sprite.material.Copy(), - DrawMode.TRIANGLES, - ui.camera, - )); } + renderables.set(cameraEntity.entity.id, cameraRenderables); + cameraViewShape.Free(); } - this.messageBus.Publish(new Message(RenderSystem.MESSAGE_LOAD_RENDERABLES, renderables)); + viewportAABB.Free(); + this.messageBus.Publish(new Message>(RenderSystem.MESSAGE_LOAD_RENDERABLES, renderables)); } } diff --git a/src/standard/text/text_system.test.ts b/src/standard/text/text_system.test.ts index 0373e6f..951d3ee 100644 --- a/src/standard/text/text_system.test.ts +++ b/src/standard/text/text_system.test.ts @@ -37,6 +37,9 @@ import System from "../../system/system"; import IEntity from "../../entity/ientity"; import Component from "../../component/component"; import FontRequest from "../../rendering/font/font_request"; +import AllCollideAlgorithm from "../collision/algorithm/all_collide_algorithm"; +import FrustumCuller from "../frustum_culler/frustum_culler"; +import NoneCollideAlgorithm from "../collision/algorithm/none_collide_algorithm"; /** * FakeSDFGenerator is used to stub SDFGenerators. @@ -53,23 +56,23 @@ describe("TextSystem - OnMessage", () => { [ "Unknown message type", undefined, - new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, undefined, 0), + new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, undefined, undefined, 0), new TextSystem(new FakeMessageBus()), new Message("unknown") ], [ "Load font no payload", undefined, - new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, undefined, 0), - new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, undefined, 0), + new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, undefined, undefined, 0), + new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, undefined, undefined, 0), new Message(FontRequest.MESSAGE_REQUEST_LOAD) ], [ "Load font, SDF factory error", new Error("sdf factory error"), - new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, () => { throw("sdf factory error");}, 0), - new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, () => { throw("sdf factory error");}, 0), - new Message(FontRequest.MESSAGE_REQUEST_LOAD, + new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, undefined, () => { throw("sdf factory error");}, 0), + new TextSystem(new FakeMessageBus(), undefined, undefined, undefined, undefined, () => { throw("sdf factory error");}, 0), + new Message(FontRequest.MESSAGE_REQUEST_LOAD, new FontRequest( "test", "test", @@ -84,9 +87,10 @@ describe("TextSystem - OnMessage", () => { new TextSystem( new FakeMessageBus([ new Reactor("Publish", () => { throw("publish fail");}) - ]), - undefined, - undefined, + ]), + undefined, + undefined, + undefined, new Map([ ["test", new FontMapping( 3, @@ -110,21 +114,22 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]) )] - ]), - () => new FakeSDFGenerator(), + ]), + () => new FakeSDFGenerator(), 0 ), new TextSystem( new FakeMessageBus([ new Reactor("Publish", () => { throw("publish fail");}) - ]), - undefined, - undefined, - undefined, - () => new FakeSDFGenerator(), + ]), + undefined, + undefined, + undefined, + undefined, + () => new FakeSDFGenerator(), 0 ), - new Message(FontRequest.MESSAGE_REQUEST_LOAD, + new Message(FontRequest.MESSAGE_REQUEST_LOAD, new FontRequest( "test", "test", @@ -140,9 +145,10 @@ describe("TextSystem - OnMessage", () => { "Load font, 5 characters, 3*3 atlas, success", undefined, new TextSystem( - new FakeMessageBus(), - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + undefined, new Map([ ["test", new FontMapping( 3, @@ -166,19 +172,20 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]) )] - ]), - () => new FakeSDFGenerator(), + ]), + () => new FakeSDFGenerator(), 0 ), new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, - () => new FakeSDFGenerator(), + new FakeMessageBus(), + undefined, + undefined, + undefined, + undefined, + () => new FakeSDFGenerator(), 0 ), - new Message(FontRequest.MESSAGE_REQUEST_LOAD, + new Message(FontRequest.MESSAGE_REQUEST_LOAD, new FontRequest( "test", "test", @@ -194,128 +201,200 @@ describe("TextSystem - OnMessage", () => { "Pre render, no payload", undefined, new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + undefined, + undefined, + undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + undefined, + undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER) ], + [ + "Pre render, no camera entities", + undefined, + new TextSystem( + new FakeMessageBus(), + undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Text(0, "test", "test") + ])] + ]), + undefined, + undefined, + undefined, + 0 + ), + new TextSystem( + new FakeMessageBus(), + undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Text(0, "test", "test") + ])] + ]), + undefined, + undefined, + undefined, + 0 + ), + new Message(Game.MESSAGE_PRE_RENDER, 1.0) + ], [ "Pre render, no text entities", undefined, new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + new Map([ + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() + ])] + ]), + undefined, + undefined, + undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + new Map([ + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() + ])] + ]), + undefined, + undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, no font mapping", + "Pre render, one camera, no font mapping", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "test", "test") + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] ]), - undefined, - undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, + undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "test", "test") + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] - ]), - undefined, - undefined, + ]), + new FrustumCuller(new AllCollideAlgorithm()), + undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, no character mapping", + "Pre render, one camera, 5 characters, no character mapping", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test") + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["p", 0] ]))] ]), - undefined, + undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test") + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["p", 0] ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, fail to publish", + "Pre render, one camera, 5 characters, fail to publish", new Error("fail to publish"), new TextSystem( new FakeMessageBus([ new Reactor("Publish", () => { throw("fail to publish"); }) - ]), - undefined, + ]), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test") + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -325,20 +404,25 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ new Reactor("Publish", () => { throw("fail to publish"); }) - ]), - undefined, + ]), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test") + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -348,23 +432,28 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, 2 no mapping", + "Pre render, one camera, 5 characters, 2 no mapping", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test") + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["c", 2], @@ -372,22 +461,28 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(3); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(3); }) - ]), - undefined, + ]), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test") + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["c", 2], @@ -395,28 +490,33 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, invalid alignment", + "Pre render, one camera, 5 characters, invalid alignment", new Error("Invalid text alignment: 3"), new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test", 3) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, - new FontAsset("test", new FontRequest("test", "test", "test", 3)), + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], ["b", 1], @@ -426,22 +526,95 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(5); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(5); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test", 3) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() + ])] + ]), + new FrustumCuller(new AllCollideAlgorithm()), + new Map([ + ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ + ["a", 0], + ["b", 1], + ["c", 2], + ["d", 3], + ["e", 4], + ]))] + ]), + undefined, + 0 + ), + new Message(Game.MESSAGE_PRE_RENDER, 1.0) + ], + [ + "Pre render, one camera, 5 characters, left align, not UI, cull characters", + undefined, + new TextSystem( + new FakeMessageBus(), + undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Text(0, "abcde", "test", TextAlignment.Left) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] - ]), + ]), + new FrustumCuller(new NoneCollideAlgorithm()), + new Map([ + [ + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), + new Map([ + ["a", 0], + ["b", 1], + ["c", 2], + ["d", 3], + ["e", 4], + ])) + ] + ]), + undefined, + 0 + ), + new TextSystem( + new FakeMessageBus([ + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(0); + }) + ]), + undefined, + new Map([ + [0, new SystemEntity(new FakeEntity(0), [ + new Transform(), + new Text(0, "abcde", "test", TextAlignment.Left) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() + ])] + ]), + new FrustumCuller(new NoneCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -451,28 +624,33 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, left align, not UI", + "Pre render, one camera, 5 characters, left align, not UI", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test", TextAlignment.Left) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, - new FontAsset("test", new FontRequest("test", "test", "test", 3)), + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], ["b", 1], @@ -482,22 +660,28 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(5); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(5); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test", TextAlignment.Left) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -507,28 +691,33 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, center align, not UI", + "Pre render, one camera, 5 characters, center align, not UI", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test", TextAlignment.Center) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, - new FontAsset("test", new FontRequest("test", "test", "test", 3)), + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], ["b", 1], @@ -538,22 +727,28 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(5); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(5); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test", TextAlignment.Center) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -563,28 +758,33 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, right align, not UI", + "Pre render, one camera, 5 characters, right align, not UI", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test", TextAlignment.Right) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, - new FontAsset("test", new FontRequest("test", "test", "test", 3)), + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], ["b", 1], @@ -594,22 +794,28 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(5); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(5); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test", TextAlignment.Right) + ])], + [1, new SystemEntity(new FakeEntity(1), [ + new Transform(), + new Camera() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -619,7 +825,7 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) @@ -628,8 +834,8 @@ describe("TextSystem - OnMessage", () => { "Pre render, 5 characters, UI, no camera entity", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -637,10 +843,11 @@ describe("TextSystem - OnMessage", () => { new UI(new FakeEntity(1)) ])] ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, + "test", + new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -651,23 +858,24 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(0); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(0); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "abcde", "test"), new UI(new FakeEntity(1)) ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -677,32 +885,34 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, UI, no camera component", + "Pre render, one camera, 5 characters, left align, UI, cull", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), - new Text(0, "abcde", "test"), + new Text(0, "abcde", "test", TextAlignment.Left), new UI(new FakeEntity(1)) ])], [1, new SystemEntity(new FakeEntity(1), [ - new Transform(), + new Camera(), + new Transform() ])], ]), + new FrustumCuller(new NoneCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, - new FontAsset("test", new FontRequest("test", "test", "test", 3)), + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], ["b", 1], @@ -712,26 +922,29 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(0); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(0); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), - new Text(0, "abcde", "test"), + new Text(0, "abcde", "test", TextAlignment.Left), new UI(new FakeEntity(1)) ])], [1, new SystemEntity(new FakeEntity(1), [ - new Transform(), + new Camera(), + new Transform() ])] - ]), + ]), + new FrustumCuller(new NoneCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -741,32 +954,34 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, UI, no camera transform component", + "Pre render, one camera, 5 characters, left align, UI, targeting different camera", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), - new Text(0, "abcde", "test"), - new UI(new FakeEntity(1)) + new Text(0, "abcde", "test", TextAlignment.Left), + new UI(new FakeEntity(2)) ])], [1, new SystemEntity(new FakeEntity(1), [ new Camera(), + new Transform() ])], ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, - new FontAsset("test", new FontRequest("test", "test", "test", 3)), + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], ["b", 1], @@ -776,26 +991,29 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(0); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(0); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), - new Text(0, "abcde", "test"), - new UI(new FakeEntity(1)) + new Text(0, "abcde", "test", TextAlignment.Left), + new UI(new FakeEntity(2)) ])], [1, new SystemEntity(new FakeEntity(1), [ new Camera(), + new Transform() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -805,17 +1023,17 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, left align, UI", + "Pre render, one camera, 5 characters, left align, UI", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -827,11 +1045,12 @@ describe("TextSystem - OnMessage", () => { new Transform() ])], ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, - new FontAsset("test", new FontRequest("test", "test", "test", 3)), + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], ["b", 1], @@ -841,16 +1060,17 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(5); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(5); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -861,7 +1081,8 @@ describe("TextSystem - OnMessage", () => { new Camera(), new Transform() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -871,17 +1092,17 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, center align, UI", + "Pre render, one camera, 5 characters, center align, UI", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -893,11 +1114,12 @@ describe("TextSystem - OnMessage", () => { new Transform() ])], ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, - new FontAsset("test", new FontRequest("test", "test", "test", 3)), + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], ["b", 1], @@ -907,16 +1129,17 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(5); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(5); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -927,7 +1150,8 @@ describe("TextSystem - OnMessage", () => { new Camera(), new Transform() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -937,17 +1161,17 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) ], [ - "Pre render, 5 characters, center align, UI", + "Pre render, one camera, 5 characters, center align, UI", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -959,11 +1183,12 @@ describe("TextSystem - OnMessage", () => { new Transform() ])], ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ [ - "test", - new FontMapping(10, - new FontAsset("test", new FontRequest("test", "test", "test", 3)), + "test", + new FontMapping(10, + new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], ["b", 1], @@ -973,16 +1198,17 @@ describe("TextSystem - OnMessage", () => { ])) ] ]), - undefined, + undefined, 0 ), new TextSystem( new FakeMessageBus([ - new Reactor("Publish", (message: Message[]>) => { - expect(message.payload?.length).toEqual(5); + new Reactor("Publish", (message: Message[]>>) => { + expect(message.payload?.size).toEqual(1); + expect(message.payload?.get(1)?.length).toEqual(5); }) ]), - undefined, + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -993,7 +1219,8 @@ describe("TextSystem - OnMessage", () => { new Camera(), new Transform() ])] - ]), + ]), + new FrustumCuller(new AllCollideAlgorithm()), new Map([ ["test", new FontMapping(10, new FontAsset("test", new FontRequest("test", "test", "test", 3)), new Map([ ["a", 0], @@ -1003,7 +1230,7 @@ describe("TextSystem - OnMessage", () => { ["e", 4], ]))] ]), - undefined, + undefined, 0 ), new Message(Game.MESSAGE_PRE_RENDER, 1.0) @@ -1012,23 +1239,25 @@ describe("TextSystem - OnMessage", () => { "Correctly register new text entity, none existing", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Text(0, "test", "test") ])] - ]), - undefined, + ]), + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), @@ -1041,8 +1270,8 @@ describe("TextSystem - OnMessage", () => { "Correctly register new text entity, 3 existing", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1060,14 +1289,15 @@ describe("TextSystem - OnMessage", () => { new Transform(), new Text(0, "test", "test") ])] - ]), - undefined, + ]), + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1081,8 +1311,9 @@ describe("TextSystem - OnMessage", () => { new Transform(), new Camera() ])], - ]), - undefined, + ]), + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), @@ -1095,23 +1326,25 @@ describe("TextSystem - OnMessage", () => { "Correctly register new camera entity, none existing", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), new Camera() ])] - ]), - undefined, + ]), + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), @@ -1124,8 +1357,8 @@ describe("TextSystem - OnMessage", () => { "Correctly register new camera entity, 3 existing", undefined, new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1143,14 +1376,15 @@ describe("TextSystem - OnMessage", () => { new Transform(), new Camera() ])] - ]), - undefined, + ]), + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, + new FakeMessageBus(), + undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1164,8 +1398,9 @@ describe("TextSystem - OnMessage", () => { new Transform(), new Camera() ])], - ]), - undefined, + ]), + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), @@ -1178,18 +1413,20 @@ describe("TextSystem - OnMessage", () => { "Correctly reject text entity, no transform", undefined, new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), @@ -1201,18 +1438,20 @@ describe("TextSystem - OnMessage", () => { "Correctly reject text entity, no text", undefined, new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), @@ -1224,18 +1463,20 @@ describe("TextSystem - OnMessage", () => { "Correctly reject camera entity, no transform", undefined, new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), @@ -1247,18 +1488,20 @@ describe("TextSystem - OnMessage", () => { "Correctly reject camera entity, no camera", undefined, new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), new TextSystem( - new FakeMessageBus(), - undefined, - undefined, - undefined, + new FakeMessageBus(), + undefined, + undefined, + new FrustumCuller(new AllCollideAlgorithm()), + undefined, undefined, 0 ), @@ -1277,4 +1520,4 @@ describe("TextSystem - OnMessage", () => { // Workaround for comparing anonymous functions expect(JSON.stringify(system)).toEqual(JSON.stringify(expectedState)); }); -}); \ No newline at end of file +}); diff --git a/src/standard/text/text_system.ts b/src/standard/text/text_system.ts index 267bc64..64a56bb 100644 --- a/src/standard/text/text_system.ts +++ b/src/standard/text/text_system.ts @@ -43,6 +43,9 @@ import FontRequest from "../../rendering/font/font_request"; import FontAsset from "../../rendering/font/font_asset"; import DrawMode from "../../rendering/draw_mode"; import Matrix4D from "../../geometry/matrix_4d"; +import IFrustumCuller from "../frustum_culler/ifrustum_culler"; +import FrustumCuller from "../frustum_culler/frustum_culler"; +import AABB from "../../shape/aabb"; /** * TextSystem is a pre-rendering system, taking in text components and @@ -70,14 +73,17 @@ class TextSystem extends System { private mappings: Map; private sdfGeneratorFactory: SDFGeneratorFactory; + private frustumCuller: IFrustumCuller; constructor(messageBus: IMessageBus, scene?: IScene, entities?: Map, + frustumCuller: IFrustumCuller = new FrustumCuller(), mappings: Map = new Map(), sdfGeneratorFactory: SDFGeneratorFactory = TextSystem.DEFAULT_SDF_GENERATOR_FACTORY, subscriberID?: number) { super(messageBus, scene, TextSystem.EVALUATOR, entities, subscriberID); + this.frustumCuller = frustumCuller; this.mappings = mappings; this.sdfGeneratorFactory = sdfGeneratorFactory; this.messageBus.Subscribe(this, [ @@ -110,7 +116,8 @@ class TextSystem extends System { private loadFont(request: FontRequest): void { // Set up SDF generator - const generator = this.sdfGeneratorFactory(request.size, request.buffer, request.radius, request.cutoff, request.family, request.weight); + const generator = this.sdfGeneratorFactory(request.size, request.buffer, request.radius, request.cutoff, + request.family, request.weight); // Calculate size of each character glyph in pixels const glyphSize = request.size + request.buffer * 2; @@ -214,159 +221,195 @@ class TextSystem extends System { } private prepareText(alpha: number): void { - const renderables: Renderable[] = []; + const renderables: Map[]> = new Map(); + + const cameraEntities = [...this.entities.values()].filter((entity) => { + return entity.Get(Camera.KEY); + }); - // Get text entities const textEntities = [...this.entities.values()].filter((entity) => { return entity.Get(Text.KEY) && entity.Get(Transform.KEY); }); - // Iterate over each entity that has text to be rendered - for (const entity of textEntities) { - const text = entity.Get(Text.KEY) as Text; - const transform = entity.Get(Transform.KEY) as Transform; + const characterScale = Vector.New(1, 1); - // Get font mapping, if it doesn't exist, skip rendering - // this text - const mapping = this.mappings.get(text.font); - if (mapping === undefined) { - continue; - } + const viewportAABB = new AABB(Vector.New(2, 2)); + + for (const cameraEntity of cameraEntities) { + const camera = cameraEntity.Get(Camera.KEY) as Camera; + const cameraTransform = cameraEntity.Get(Transform.KEY) as Transform; - // Get a UI element if it is attached to the entity - const ui = entity.Get(UI.KEY) as UI | undefined; + const cameraViewShape = new AABB(camera.virtualScale.Copy()).Transform(cameraTransform); - // Iterate over each character to be rendered - for (let i = 0; i < text.value.length; i++) { - const char = text.value[i]; + const cameraVirtualScaleHalf = camera.virtualScale.Copy().Scale(0.5); - // Get the character's mapping value, if it doesn't - // exist skip rendering this character - const position = mapping.characters.get(char); - if (position === undefined) { + const cameraRenderables: Renderable[] = []; + for (const entity of textEntities) { + const text = entity.Get(Text.KEY) as Text; + const transform = entity.Get(Transform.KEY) as Transform; + + // Get font mapping, if it doesn't exist, skip rendering + // this text + const mapping = this.mappings.get(text.font); + if (mapping === undefined) { continue; } - // Determine the x alignment of the text, based - // on the text alignment options provided - let xAlign; - switch (text.align) { - case TextAlignment.Left: { - // +0.5 to shift first character from being centered on - // transform position to the right of it - xAlign = i + 0.5; - break; - } - case TextAlignment.Center: { - xAlign = i - (text.value.length - 1) / 2; - break; - } - case TextAlignment.Right: { - // Inverse of left align, with transform position set to - // right of the last character - xAlign = i - (text.value.length - 1) - 0.5; - break; - } - default: { - throw (`Invalid text alignment: ${text.align}`); - } - } + const transformVirtualPosition = transform.position.Copy().Multiply(cameraVirtualScaleHalf); + const offsetVirtualPosition = text.offset.Copy().Multiply(cameraVirtualScaleHalf); - // Transform for character - const interpolatedMatrix = new Matrix4D(); - if (ui === undefined) { - // Not part of the UI - /** - * (xAlign * transform.scale.x/2) -> determines alignment - * left, center, right - * (xAlign * text.spacing * transform.scale.x/2) -> - * determines spacing between characters - */ - const translation = transform.position.Copy(); - translation.x += text.offset.x + (xAlign * transform.scale.x / 2) + (xAlign * text.spacing * transform.scale.x / 2); - translation.y += text.offset.y; - interpolatedMatrix.Translate(translation).Scale(transform.scale).Rotate(transform.angle); - } else { - // Part of the UI - // Get the camera entity this is assigned to, if no camera - // found, skip this entity - const cameraEntity = this.entities.get(ui.camera.id); - if (cameraEntity === undefined) { - break; + // Get a UI element if it is attached to the entity + const ui = entity.Get(UI.KEY) as UI | undefined; + + // Iterate over each character to be rendered + for (let i = 0; i < text.value.length; i++) { + const char = text.value[i]; + + // Get the character's mapping value, if it doesn't + // exist skip rendering this character + const position = mapping.characters.get(char); + if (position === undefined) { + continue; } - // Get components of the camera entity, if the components - // are not found, must not be a valid camera, skip this - // entity - const camera = cameraEntity.Get(Camera.KEY) as Camera | undefined; - const cameraTransform = cameraEntity.Get(Transform.KEY) as Transform | undefined; - if (camera === undefined || cameraTransform === undefined) { - break; + + // Determine the x alignment of the text, based + // on the text alignment options provided + let xAlign; + switch (text.align) { + case TextAlignment.Left: { + // +0.5 to shift first character from being centered on + // transform position to the right of it + xAlign = i + 0.5; + break; + } + case TextAlignment.Center: { + xAlign = i - (text.value.length - 1) / 2; + break; + } + case TextAlignment.Right: { + // Inverse of left align, with transform position set to + // right of the last character + xAlign = i - (text.value.length - 1) - 0.5; + break; + } + default: { + throw (`Invalid text alignment: ${text.align}`); + } } - // Convert the transform.position to be relative to the camera - const textPosition = cameraTransform.position.Copy() - .Add(transform.position.Copy().Multiply(camera.virtualScale.Copy().Scale(0.5))) - .Add(text.offset.Copy().Multiply(camera.virtualScale.Copy().Scale(0.5))); - - - // Convert the scale to be relative to the camera - const charScale = transform.scale.Copy().Multiply(camera.virtualScale); - /** - * (xAlign * charScale.x / 2) -> determines alignment - * left, center, right - * (xAlign * text.spacing * charScale.x/2) -> - * determines spacing between characters - */ - const translation = textPosition.Copy(); - translation.x += (xAlign * charScale.x / 2) + (xAlign * text.spacing * charScale.x / 2); - interpolatedMatrix.Translate(translation).Scale(charScale).Rotate(transform.angle); - } + // Transform for character + const interpolatedMatrix = new Matrix4D(); + if (ui === undefined) { + // Not part of the UI + + /** + * (xAlign * transform.scale.x/2) -> determines alignment + * left, center, right + * (xAlign * text.spacing * transform.scale.x/2) -> + * determines spacing between characters + */ + const translation = transform.position.Copy(); + translation.x += text.offset.x + (xAlign * transform.scale.x / 2) + (xAlign * text.spacing * transform.scale.x / 2); + translation.y += text.offset.y; + + const textTransform = new Transform( + translation, + transform.scale.Copy(), + transform.angle + ); + + interpolatedMatrix.Translate(translation).Scale(transform.scale).Rotate(transform.angle); + + translation.Free(); + + if (this.frustumCuller.Cull(cameraViewShape, new AABB(characterScale).Transform(textTransform))) { + // Not in camera view, skip rendering + textTransform.Free(); + continue; + } + textTransform.Free(); + } else { + // Part of the UI + if (cameraEntity.entity.id !== ui.camera.id) { + // If camera is not the one targeted, skip + continue; + } - // Determine the position in the glyph to extract the text glyph - // from - const x = position % mapping.width; - const y = Math.floor(position / mapping.width); - // Determine how wide and tall each glyph is in the texture - // (which goes from 0 -> 1, so a glyph atlas with 10*10 - // dimensions - 100 characters - would have a character size of - // 0.1) - const charSize = 1 / mapping.width; - // Create renderable for the character, include extra TextRender - // information for shaders to use - renderables.push(Renderable.New( - text.zOrder, - Polygon.QuadByDimensions(1, 1, 0, 0), - interpolatedMatrix, - new Material( - { - texture: new Texture( - `font_${text.font}`, - Polygon.QuadByPoints( - Vector.New(x * charSize, y * charSize), - Vector.New(x * charSize + charSize, y * charSize + charSize) - ) - ), - shaders: text.shaders, - color: text.color + if (this.frustumCuller.Cull(viewportAABB, new AABB(characterScale).Transform(transform))) { + // Not in camera view, skip rendering + continue; } - ), - DrawMode.TRIANGLES, - new TextRender( - mapping.asset.request.family, - mapping.asset.request.weight, - mapping.asset.request.buffer, - mapping.asset.request.radius, - mapping.asset.request.cutoff, - mapping.asset.request.size, - text.color, + + // Convert the transform.position to be relative to the camera + const textPosition = cameraTransform.position.Copy() + .Add(transformVirtualPosition) + .Add(offsetVirtualPosition); + + // Convert the scale to be relative to the camera + const charScale = transform.scale.Copy().Multiply(camera.virtualScale); + /** + * (xAlign * charScale.x / 2) -> determines alignment + * left, center, right + * (xAlign * text.spacing * charScale.x/2) -> + * determines spacing between characters + */ + textPosition.x += (xAlign * charScale.x / 2) + (xAlign * text.spacing * charScale.x / 2); + interpolatedMatrix.Translate(textPosition).Scale(charScale).Rotate(transform.angle); + textPosition.Free(); + charScale.Free(); + } + + // Determine the position in the glyph to extract the text glyph + // from + const x = position % mapping.width; + const y = Math.floor(position / mapping.width); + // Determine how wide and tall each glyph is in the texture + // (which goes from 0 -> 1, so a glyph atlas with 10*10 + // dimensions - 100 characters - would have a character size of + // 0.1) + const charSize = 1 / mapping.width; + // Create renderable for the character, include extra TextRender + // information for shaders to use + cameraRenderables.push(Renderable.New( text.zOrder, - text.align - ) - )); + Polygon.QuadByDimensions(1, 1, 0, 0), + interpolatedMatrix, + new Material( + { + texture: new Texture( + `font_${text.font}`, + Polygon.QuadByPoints( + Vector.New(x * charSize, y * charSize), + Vector.New(x * charSize + charSize, y * charSize + charSize) + ) + ), + shaders: text.shaders, + color: text.color + } + ), + DrawMode.TRIANGLES, + new TextRender( + mapping.asset.request.family, + mapping.asset.request.weight, + mapping.asset.request.buffer, + mapping.asset.request.radius, + mapping.asset.request.cutoff, + mapping.asset.request.size, + text.color, + text.zOrder, + text.align + ) + )); + } + transformVirtualPosition.Free(); + offsetVirtualPosition.Free(); } - + renderables.set(cameraEntity.entity.id, cameraRenderables); + cameraViewShape.Free(); + cameraVirtualScaleHalf.Free(); } - this.messageBus.Publish(new Message[]>(RenderSystem.MESSAGE_LOAD_RENDERABLES, renderables)); + viewportAABB.Free(); + this.messageBus.Publish(new Message[]>>(RenderSystem.MESSAGE_LOAD_RENDERABLES, renderables)); } } diff --git a/src/standard/webgl/webgl_system.test.ts b/src/standard/webgl/webgl_system.test.ts index 6ea2d91..b9874ce 100644 --- a/src/standard/webgl/webgl_system.test.ts +++ b/src/standard/webgl/webgl_system.test.ts @@ -37,61 +37,11 @@ import Polygon from "../../shape/polygon"; import Matrix4D from "../../geometry/matrix_4d"; import Material from "../../rendering/material/material"; import Texture from "../../rendering/texture/texture"; -import FrustumCuller from "../frustum_culler/frustum_culler"; -import NoneCollideAlgorithm from "../collision/algorithm/none_collide_algorithm"; -import AllCollideAlgorithm from "../collision/algorithm/all_collide_algorithm"; -import ICollisionAlgorithm from "../collision/algorithm/icollision_algorithm"; import Vector from "../../geometry/vector"; -import CollisionInfo from "../collision/collision_info"; -import IShape from "../../shape/ishape"; import TextureFiltering from "../../rendering/texture/texture_filtering"; import TextureWrapping from "../../rendering/texture/texture_wrapping"; import DrawMode from "../../rendering/draw_mode"; -class TestCollisionAlgorithm implements ICollisionAlgorithm { - private centerPairs: [Vector, Vector][]; - constructor(centerPairs: [Vector, Vector][]) { - this.centerPairs = centerPairs; - } - - public CalculateCollisions(shapes: IShape[]): CollisionInfo[] { - const alreadyChecked: [number,number][] = []; - const collisions: CollisionInfo[] = []; - for (let i = 0; i < shapes.length; i++) { - for (let j = shapes.length - 1; j >= 0; j--) { - if (i === j) { - continue; - } - const checked = alreadyChecked.some((pair) => { - return pair[0] === i && pair[1] === j || - pair[0] === j && pair[1] === i; - }); - if (checked) { - // Don't check the same collision twice - continue; - } - - const a = shapes[i]; - const b = shapes[j]; - - const aCenter = a.Center(); - const bCenter = b.Center(); - for (const pair of this.centerPairs) { - if (aCenter.x === pair[0].x && aCenter.y === pair[0].y && bCenter.x === pair[1].x && bCenter.y === pair[1].y || - aCenter.x === pair[1].x && aCenter.y === pair[1].y && bCenter.x === pair[0].x && bCenter.y === pair[0].y) { - collisions.push(new CollisionInfo( - a, - b - )); - } - } - alreadyChecked.push([i,j]); - } - } - return collisions; - } -} - class TestShader implements IShader { public source: string; public type: string; @@ -118,7 +68,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -131,7 +80,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message("unknown") @@ -149,7 +97,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -162,7 +109,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message<[IEntity, Component[]]>( @@ -186,7 +132,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -199,7 +144,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message<[IEntity, Component[]]>( @@ -222,7 +166,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, new Map([[ 0, new SystemEntity( @@ -242,7 +185,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message<[IEntity, Component[]]>( @@ -266,7 +208,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -279,7 +220,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD) @@ -297,7 +237,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -310,7 +249,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -338,7 +276,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -351,7 +288,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -379,7 +315,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -392,7 +327,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -420,7 +354,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -433,7 +366,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -461,7 +393,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -474,7 +405,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -502,7 +432,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -515,7 +444,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -549,7 +477,6 @@ describe("WebGLSystem - OnMessage", () => { ]), undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -566,7 +493,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -600,7 +526,6 @@ describe("WebGLSystem - OnMessage", () => { ]), undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -617,7 +542,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -651,7 +575,6 @@ describe("WebGLSystem - OnMessage", () => { ]), undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -670,7 +593,6 @@ describe("WebGLSystem - OnMessage", () => { ]), undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -704,7 +626,6 @@ describe("WebGLSystem - OnMessage", () => { ]), undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -721,7 +642,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -755,7 +675,6 @@ describe("WebGLSystem - OnMessage", () => { ]), undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -772,7 +691,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ImageAsset.MESSAGE_FINISH_LOAD, new ImageAsset( @@ -800,7 +718,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -813,7 +730,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ShaderAsset.MESSAGE_REQUEST_LOAD) @@ -831,7 +747,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -844,7 +759,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ShaderAsset.MESSAGE_REQUEST_LOAD, new ShaderAsset("test", new TestShader("test", "test"))) @@ -862,7 +776,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -875,7 +788,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ShaderAsset.MESSAGE_REQUEST_LOAD, new ShaderAsset("test", new GLSLShader("unknown", "test"))) @@ -893,7 +805,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -906,7 +817,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ShaderAsset.MESSAGE_REQUEST_LOAD, new ShaderAsset("test", new GLSLShader(ShaderAsset.VERTEX_TYPE, "test"))) @@ -927,7 +837,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -943,7 +852,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ShaderAsset.MESSAGE_REQUEST_LOAD, new ShaderAsset("test", new GLSLShader(ShaderAsset.VERTEX_TYPE, "test"))) @@ -966,7 +874,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -984,7 +891,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ShaderAsset.MESSAGE_REQUEST_LOAD, new ShaderAsset("test", new GLSLShader(ShaderAsset.VERTEX_TYPE, "test"))) @@ -1007,7 +913,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -1023,7 +928,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ShaderAsset.MESSAGE_REQUEST_LOAD, new ShaderAsset("test vertex", new GLSLShader(ShaderAsset.VERTEX_TYPE, "test vertex"))) @@ -1046,7 +950,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new WebGLSystem( @@ -1062,7 +965,6 @@ describe("WebGLSystem - OnMessage", () => { undefined, undefined, undefined, - undefined, 0, ), new Message(ShaderAsset.MESSAGE_REQUEST_LOAD, new ShaderAsset("test vertex", new GLSLShader(ShaderAsset.FRAGMENT_TYPE, "test vertex"))) @@ -1096,7 +998,6 @@ describe("WebGLSystem - Render", () => { undefined, undefined, undefined, - undefined, new Map(), 0, ), @@ -1109,7 +1010,6 @@ describe("WebGLSystem - Render", () => { undefined, undefined, undefined, - undefined, new Map(), 0, ), @@ -1136,7 +1036,6 @@ describe("WebGLSystem - Render", () => { undefined, undefined, undefined, - undefined, new Map(), 0, ), @@ -1157,7 +1056,6 @@ describe("WebGLSystem - Render", () => { undefined, undefined, undefined, - undefined, new Map(), 0, ), @@ -1184,7 +1082,6 @@ describe("WebGLSystem - Render", () => { undefined, undefined, undefined, - undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1210,7 +1107,6 @@ describe("WebGLSystem - Render", () => { undefined, undefined, undefined, - undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1237,8 +1133,7 @@ describe("WebGLSystem - Render", () => { }), ]), undefined, - [], - undefined, + new Map(), undefined, undefined, undefined, @@ -1263,17 +1158,16 @@ describe("WebGLSystem - Render", () => { }), ]), undefined, - [ + new Map([[0, [ new Renderable(0, Polygon.RectangleByDimensions(1, 1), new Matrix4D(), new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1,1)), + texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), }), DrawMode.TRIANGLE_STRIP ) - ], - undefined, + ]]]), undefined, undefined, undefined, @@ -1305,7 +1199,7 @@ describe("WebGLSystem - Render", () => { new Reactor("createProgram", (): WebGLProgram | null => null), ]), undefined, - [ + new Map([[0, [ new Renderable(0, Polygon.RectangleByDimensions(1, 1), new Matrix4D(), @@ -1315,7 +1209,7 @@ describe("WebGLSystem - Render", () => { }), DrawMode.TRIANGLE_STRIP ) - ], + ]]]), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], @@ -1323,7 +1217,6 @@ describe("WebGLSystem - Render", () => { ]), undefined, undefined, - undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1345,7 +1238,7 @@ describe("WebGLSystem - Render", () => { new Reactor("createProgram", (): WebGLProgram | null => null), ]), undefined, - [ + new Map([[0, [ new Renderable(0, Polygon.RectangleByDimensions(1, 1), new Matrix4D(), @@ -1355,7 +1248,7 @@ describe("WebGLSystem - Render", () => { }), DrawMode.TRIANGLE_STRIP ) - ], + ]]]), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], @@ -1363,7 +1256,6 @@ describe("WebGLSystem - Render", () => { ]), undefined, undefined, - undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1392,7 +1284,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): boolean => false) ]), undefined, - [ + new Map([[0, [ new Renderable(0, Polygon.RectangleByDimensions(1, 1), new Matrix4D(), @@ -1402,7 +1294,7 @@ describe("WebGLSystem - Render", () => { }), DrawMode.TRIANGLE_STRIP ) - ], + ]]]), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], @@ -1410,7 +1302,6 @@ describe("WebGLSystem - Render", () => { ]), undefined, undefined, - undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1433,7 +1324,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): boolean => false) ]), undefined, - [ + new Map([[0, [ new Renderable(0, Polygon.RectangleByDimensions(1, 1), new Matrix4D(), @@ -1443,7 +1334,7 @@ describe("WebGLSystem - Render", () => { }), DrawMode.TRIANGLE_STRIP ) - ], + ]]]), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], @@ -1451,7 +1342,6 @@ describe("WebGLSystem - Render", () => { ]), undefined, undefined, - undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1480,7 +1370,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [], + new Map(), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], @@ -1490,7 +1380,6 @@ describe("WebGLSystem - Render", () => { new Map([ ["_test_vert_test_frag", new WebGLProgram()] ]), - undefined, new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1513,7 +1402,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [ + new Map([[0, [ new Renderable(0, Polygon.RectangleByDimensions(1, 1), new Matrix4D(), @@ -1523,101 +1412,14 @@ describe("WebGLSystem - Render", () => { }), DrawMode.TRIANGLE_STRIP ) - ], - undefined, - new Map([ - ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], - ["test_frag", [new WebGLShader(), new GLSLShader(ShaderAsset.FRAGMENT_TYPE, "")]] - ]), - undefined, - undefined, - undefined, - new Map([ - [0, new SystemEntity(new FakeEntity(0), [ - new Transform(), - new Camera() - ])] - ]), - 0, - ), - new Message(Game.MESSAGE_RENDER, 1.0) - ], - [ - "Render, 1 renderables, cull", - undefined, - 0, - new WebGLSystem( - new FakeMessageBus(), - new FakeWebGL2RenderingContext([ - new Reactor("drawArrays", (): void => { throw ("expected no draw call"); }), - new Reactor("canvas", (): HTMLCanvasElement => { - const canvas = new HTMLCanvasElement(); - canvas.width = 10; - canvas.height = 10; - return canvas; - }), - new Reactor("createProgram", (): WebGLProgram => new WebGLProgram()), - new Reactor("getProgramParameter", (): number => 1) - ]), - undefined, - [], + ]]]), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], ["test_frag", [new WebGLShader(), new GLSLShader(ShaderAsset.FRAGMENT_TYPE, "")]] ]), - new Map([ - ["test", new WebGLTexture()] - ]), - new Map([ - ["_test_vert_test_frag", new WebGLProgram()] - ]), - new FrustumCuller(new NoneCollideAlgorithm()), - new Map([ - [0, new SystemEntity(new FakeEntity(0), [ - new Transform(), - new Camera() - ])] - ]), - 0, - ), - new WebGLSystem( - new FakeMessageBus(), - new FakeWebGL2RenderingContext([ - new Reactor("drawArrays", (): void => { throw ("expected no draw call"); }), - new Reactor("canvas", (): HTMLCanvasElement => { - const canvas = new HTMLCanvasElement(); - canvas.width = 10; - canvas.height = 10; - return canvas; - }), - new Reactor("createProgram", (): WebGLProgram => new WebGLProgram()), - new Reactor("getProgramParameter", (): number => 1) - ]), undefined, - [ - new Renderable(0, - Polygon.RectangleByDimensions(1, 1), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ) - ], undefined, - new Map([ - ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], - ["test_frag", [new WebGLShader(), new GLSLShader(ShaderAsset.FRAGMENT_TYPE, "")]] - ]), - new Map([ - ["test", new WebGLTexture()] - ]), - new Map([ - ["_test_vert_test_frag", new WebGLProgram()] - ]), - new FrustumCuller(new NoneCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1629,7 +1431,7 @@ describe("WebGLSystem - Render", () => { new Message(Game.MESSAGE_RENDER, 1.0) ], [ - "Render, 1 renderables, don't cull", + "Render, 1 renderables", undefined, 1, new WebGLSystem( @@ -1646,7 +1448,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [], + new Map(), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], @@ -1658,7 +1460,6 @@ describe("WebGLSystem - Render", () => { new Map([ ["_test_vert_test_frag", new WebGLProgram()] ]), - new FrustumCuller(new NoneCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1681,7 +1482,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [ + new Map([[0, [ new Renderable(0, Polygon.RectangleByDimensions(1, 1), new Matrix4D(), @@ -1691,7 +1492,7 @@ describe("WebGLSystem - Render", () => { }), DrawMode.TRIANGLE_STRIP ) - ], + ]]]), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], @@ -1703,7 +1504,6 @@ describe("WebGLSystem - Render", () => { new Map([ ["_test_vert_test_frag", new WebGLProgram()] ]), - new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -1714,150 +1514,6 @@ describe("WebGLSystem - Render", () => { ), new Message(Game.MESSAGE_RENDER, 1.0) ], - [ - "Render, 5 renderables, 2 cameras, cull 2", - undefined, - 6, - new WebGLSystem( - new FakeMessageBus(), - new FakeWebGL2RenderingContext([ - new Reactor("drawArrays", (): void => { drawCount++; }), - new Reactor("canvas", (): HTMLCanvasElement => { - const canvas = new HTMLCanvasElement(); - canvas.width = 10; - canvas.height = 10; - return canvas; - }), - new Reactor("createProgram", (): WebGLProgram => new WebGLProgram()), - new Reactor("getProgramParameter", (): number => 1) - ]), - undefined, - [], - undefined, - new Map([ - ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "", () => { return; }, () => { return; }, () => { return; })]], - ["test_frag", [new WebGLShader(), new GLSLShader(ShaderAsset.FRAGMENT_TYPE, "", () => { return; }, () => { return; }, () => { return; })]] - ]), - new Map([ - ["test", new WebGLTexture()] - ]), - new Map([ - ["_test_vert_test_frag", new WebGLProgram()] - ]), - new FrustumCuller(new TestCollisionAlgorithm([ - [new Vector(1, 1), new Vector(0, 0)], - [new Vector(1, 1), new Vector(1, 0)], - [new Vector(1, 1), new Vector(2, 0)], - [new Vector(2, 2), new Vector(2, 0)], - [new Vector(2, 2), new Vector(3, 0)], - [new Vector(2, 2), new Vector(4, 0)] - ])), - new Map([ - [0, new SystemEntity(new FakeEntity(0), [ - new Transform(new Vector(1, 1)), - new Camera(undefined, undefined, undefined, new Vector(1, 1)) - ])], - [1, new SystemEntity(new FakeEntity(0), [ - new Transform(new Vector(2, 2)), - new Camera(undefined, undefined, undefined, new Vector(1, 1)) - ])] - ]), - 0, - ), - new WebGLSystem( - new FakeMessageBus(), - new FakeWebGL2RenderingContext([ - new Reactor("drawArrays", (): void => { drawCount++; }), - new Reactor("canvas", (): HTMLCanvasElement => { - const canvas = new HTMLCanvasElement(); - canvas.width = 10; - canvas.height = 10; - return canvas; - }), - new Reactor("createProgram", (): WebGLProgram => new WebGLProgram()), - new Reactor("getProgramParameter", (): number => 1) - ]), - undefined, - [ - new Renderable(0, - Polygon.RectangleByDimensions(1, 1, 0, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ), - new Renderable(0, - Polygon.RectangleByDimensions(1, 1, 1, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ), - new Renderable(0, - Polygon.RectangleByDimensions(1, 1, 2, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ), - new Renderable(0, - Polygon.RectangleByDimensions(1, 1, 3, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ), - new Renderable(0, - Polygon.RectangleByDimensions(1, 1, 4, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ) - ], - undefined, - new Map([ - ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "", () => { return; }, () => { return; }, () => { return; })]], - ["test_frag", [new WebGLShader(), new GLSLShader(ShaderAsset.FRAGMENT_TYPE, "", () => { return; }, () => { return; }, () => { return; })]] - ]), - new Map([ - ["test", new WebGLTexture()] - ]), - new Map([ - ["_test_vert_test_frag", new WebGLProgram()] - ]), - new FrustumCuller(new TestCollisionAlgorithm([ - [new Vector(1, 1), new Vector(0, 0)], - [new Vector(1, 1), new Vector(1, 0)], - [new Vector(1, 1), new Vector(2, 0)], - [new Vector(2, 2), new Vector(2, 0)], - [new Vector(2, 2), new Vector(3, 0)], - [new Vector(2, 2), new Vector(4, 0)] - ])), - new Map([ - [0, new SystemEntity(new FakeEntity(0), [ - new Transform(new Vector(1, 1)), - new Camera(undefined, undefined, undefined, new Vector(1, 1)) - ])], - [1, new SystemEntity(new FakeEntity(0), [ - new Transform(new Vector(2, 2)), - new Camera(undefined, undefined, undefined, new Vector(1, 1)) - ])] - ]), - 0, - ), - new Message(Game.MESSAGE_RENDER, 1.0) - ], [ "Render, 3 renderables, 2 cameras, render only to one camera", undefined, @@ -1876,7 +1532,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [], + new Map(), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "", () => { return; }, () => { return; }, () => { return; })]], @@ -1888,14 +1544,6 @@ describe("WebGLSystem - Render", () => { new Map([ ["_test_vert_test_frag", new WebGLProgram()] ]), - new FrustumCuller(new TestCollisionAlgorithm([ - [new Vector(1, 1), new Vector(0, 0)], - [new Vector(1, 1), new Vector(1, 0)], - [new Vector(1, 1), new Vector(2, 0)], - [new Vector(2, 2), new Vector(0, 0)], - [new Vector(2, 2), new Vector(1, 0)], - [new Vector(2, 2), new Vector(2, 0)] - ])), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(new Vector(1, 1)), @@ -1922,7 +1570,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [ + new Map([[0, [ new Renderable(0, Polygon.RectangleByDimensions(1, 1, 0, 0), new Matrix4D(), @@ -1955,7 +1603,7 @@ describe("WebGLSystem - Render", () => { undefined, new FakeEntity(0) ), - ], + ]]]), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "", () => { return; }, () => { return; }, () => { return; })]], @@ -1967,14 +1615,6 @@ describe("WebGLSystem - Render", () => { new Map([ ["_test_vert_test_frag", new WebGLProgram()] ]), - new FrustumCuller(new TestCollisionAlgorithm([ - [new Vector(1, 1), new Vector(0, 0)], - [new Vector(1, 1), new Vector(1, 0)], - [new Vector(1, 1), new Vector(2, 0)], - [new Vector(2, 2), new Vector(0, 0)], - [new Vector(2, 2), new Vector(1, 0)], - [new Vector(2, 2), new Vector(2, 0)] - ])), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(new Vector(1, 1)), @@ -2007,7 +1647,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [], + new Map(), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], @@ -2019,7 +1659,6 @@ describe("WebGLSystem - Render", () => { new Map([ ["_test_vert_test_frag", new WebGLProgram()] ]), - new FrustumCuller(new NoneCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -2042,7 +1681,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [ + new Map([[0, [ new Renderable(0, Polygon.RectangleByDimensions(1, 1), new Matrix4D(), @@ -2052,7 +1691,7 @@ describe("WebGLSystem - Render", () => { }), 23 ) - ], + ]]]), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "")]], @@ -2064,7 +1703,6 @@ describe("WebGLSystem - Render", () => { new Map([ ["_test_vert_test_frag", new WebGLProgram()] ]), - new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(), @@ -2093,7 +1731,7 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [], + new Map(), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "", () => { return; }, () => { return; }, () => { return; })]], @@ -2105,7 +1743,6 @@ describe("WebGLSystem - Render", () => { new Map([ ["_test_vert_test_frag", new WebGLProgram()] ]), - new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(new Vector(1, 1)), @@ -2128,53 +1765,57 @@ describe("WebGLSystem - Render", () => { new Reactor("getProgramParameter", (): number => 1) ]), undefined, - [ - new Renderable(0, - Polygon.RectangleByDimensions(1, 1, 0, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ), - new Renderable(1, - Polygon.RectangleByDimensions(1, 1, 1, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ), - new Renderable(0, - Polygon.RectangleByDimensions(1, 1, 2, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ), - new Renderable(3, - Polygon.RectangleByDimensions(1, 1, 3, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ), - new Renderable(5, - Polygon.RectangleByDimensions(1, 1, 4, 0), - new Matrix4D(), - new Material({ - texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), - shaders: ["test_vert", "test_frag"] - }), - DrawMode.TRIANGLE_STRIP - ) - ], + new Map([ + [0, + [ + new Renderable(0, + Polygon.RectangleByDimensions(1, 1, 0, 0), + new Matrix4D(), + new Material({ + texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), + shaders: ["test_vert", "test_frag"] + }), + DrawMode.TRIANGLE_STRIP + ), + new Renderable(1, + Polygon.RectangleByDimensions(1, 1, 1, 0), + new Matrix4D(), + new Material({ + texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), + shaders: ["test_vert", "test_frag"] + }), + DrawMode.TRIANGLE_STRIP + ), + new Renderable(0, + Polygon.RectangleByDimensions(1, 1, 2, 0), + new Matrix4D(), + new Material({ + texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), + shaders: ["test_vert", "test_frag"] + }), + DrawMode.TRIANGLE_STRIP + ), + new Renderable(3, + Polygon.RectangleByDimensions(1, 1, 3, 0), + new Matrix4D(), + new Material({ + texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), + shaders: ["test_vert", "test_frag"] + }), + DrawMode.TRIANGLE_STRIP + ), + new Renderable(5, + Polygon.RectangleByDimensions(1, 1, 4, 0), + new Matrix4D(), + new Material({ + texture: new Texture("test", Polygon.RectangleByDimensions(1, 1)), + shaders: ["test_vert", "test_frag"] + }), + DrawMode.TRIANGLE_STRIP + ) + ] + ] + ]), undefined, new Map([ ["test_vert", [new WebGLShader(), new GLSLShader(ShaderAsset.VERTEX_TYPE, "", () => { return; }, () => { return; }, () => { return; })]], @@ -2186,7 +1827,6 @@ describe("WebGLSystem - Render", () => { new Map([ ["_test_vert_test_frag", new WebGLProgram()] ]), - new FrustumCuller(new AllCollideAlgorithm()), new Map([ [0, new SystemEntity(new FakeEntity(0), [ new Transform(new Vector(1, 1)), diff --git a/src/standard/webgl/webgl_system.ts b/src/standard/webgl/webgl_system.ts index 5c500f8..2c16796 100644 --- a/src/standard/webgl/webgl_system.ts +++ b/src/standard/webgl/webgl_system.ts @@ -34,9 +34,6 @@ import DefaultTextureFragmentShader from "./default_texture_fragment_shader"; import RenderSystem from "../render/render_system"; import DefaultTextFragmentShader from "./default_text_fragment_shader"; import IRenderable from "../../rendering/irenderable"; -import IFrustumCuller from "../frustum_culler/ifrustum_culler"; -import FrustumCuller from "../frustum_culler/frustum_culler"; -import Polygon from "../../shape/polygon"; import TextureFiltering from "../../rendering/texture/texture_filtering"; import TextureWrapping from "../../rendering/texture/texture_wrapping"; import DrawMode from "../../rendering/draw_mode"; @@ -80,12 +77,11 @@ class WebGLSystem extends RenderSystem { private textures: Map; private shaders: Map; private programs: Map; - private frustumCuller: IFrustumCuller; constructor(messageBus: IMessageBus, gl: WebGL2RenderingContext, scene?: IScene, - renderables: IRenderable[] = [], + renderables: Map = new Map(), defaultShaderAssets: ShaderAsset[] = [ new ShaderAsset(ShaderAsset.DEFAULT_TEXTURE_FRAGMENT_SHADER_NAME, new DefaultTextureFragmentShader()), new ShaderAsset(ShaderAsset.DEFAULT_TEXTURE_VERTEX_SHADER_NAME, new DefaultTextureVertexShader()), @@ -96,7 +92,6 @@ class WebGLSystem extends RenderSystem { shaders: Map = new Map(), textures: Map = new Map(), programs: Map = new Map(), - frustumCuller: IFrustumCuller = new FrustumCuller(), entities?: Map, subscriberID?: number) { super(messageBus, scene, WebGLSystem.EVALUATOR, renderables, entities, subscriberID); @@ -105,7 +100,6 @@ class WebGLSystem extends RenderSystem { this.textures = textures; this.shaders = shaders; this.programs = programs; - this.frustumCuller = frustumCuller; // Subscribe to messages this.messageBus.Subscribe(this, [ @@ -281,9 +275,6 @@ class WebGLSystem extends RenderSystem { (canvasHeight / 2 + (camera.viewportPosition.y / 2) * canvasHeight) - realHeight / 2 ); - const cameraViewShape = Polygon.RectangleByDimensions(camera.virtualScale.x, camera.virtualScale.y) - .Transform(transform); - // Define the viewport position of the camera gl.viewport( realPosition.x, @@ -323,9 +314,16 @@ class WebGLSystem extends RenderSystem { gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + const cameraRenderables = this.renderables.get(cameraEntity.entity.id); + + if (cameraRenderables === undefined) { + // No renderables prepared for camera + continue; + } + // Group by z order const zOrderGroups: Map = new Map(); - for (const renderable of this.renderables) { + for (const renderable of cameraRenderables) { const zOrderGroup = zOrderGroups.get(renderable.zOrder); if (zOrderGroup === undefined) { zOrderGroups.set(renderable.zOrder, [renderable]); @@ -448,12 +446,6 @@ class WebGLSystem extends RenderSystem { continue; } - // Frustum culling - if (this.frustumCuller.Cull(cameraViewShape, renderable.vertices.Apply4D(renderable.modelMatrix))) { - // Not in camera view, skip rendering - continue; - } - for (const shader of shaders) { if (shader[1].perRenderable !== undefined) { shader[1].perRenderable(glslContext, renderable, texture); @@ -466,13 +458,14 @@ class WebGLSystem extends RenderSystem { } } - } - for (const renderable of this.renderables) { - renderable.Free(); + for (const renderable of cameraRenderables) { + renderable.Free(); + } } - this.renderables = []; + + this.renderables = new Map(); } } diff --git a/yarn.lock b/yarn.lock index f022f0a..290c203 100644 --- a/yarn.lock +++ b/yarn.lock @@ -225,6 +225,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" + integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/template@^7.10.4", "@babel/template@^7.3.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -287,160 +294,162 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/console@^25.5.0": - version "25.5.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-25.5.0.tgz#770800799d510f37329c508a9edd0b7b447d9abb" - integrity sha512-T48kZa6MK1Y6k4b89sexwmSF4YLeZS/Udqg3Jj3jG/cHH+N/sLFCEoXEDMOKugJQ9FxPN1osxIknvKkxt6MKyw== +"@jest/console@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" + integrity sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g== dependencies: - "@jest/types" "^25.5.0" - chalk "^3.0.0" - jest-message-util "^25.5.0" - jest-util "^25.5.0" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^26.6.2" + jest-util "^26.6.2" slash "^3.0.0" -"@jest/core@^25.2.7", "@jest/core@^25.5.4": - version "25.5.4" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-25.5.4.tgz#3ef7412f7339210f003cdf36646bbca786efe7b4" - integrity sha512-3uSo7laYxF00Dg/DMgbn4xMJKmDdWvZnf89n8Xj/5/AeQ2dOQmn6b6Hkj/MleyzZWXpwv+WSdYWl4cLsy2JsoA== +"@jest/core@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" + integrity sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw== dependencies: - "@jest/console" "^25.5.0" - "@jest/reporters" "^25.5.1" - "@jest/test-result" "^25.5.0" - "@jest/transform" "^25.5.1" - "@jest/types" "^25.5.0" + "@jest/console" "^26.6.2" + "@jest/reporters" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" ansi-escapes "^4.2.1" - chalk "^3.0.0" + chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" - jest-changed-files "^25.5.0" - jest-config "^25.5.4" - jest-haste-map "^25.5.1" - jest-message-util "^25.5.0" - jest-regex-util "^25.2.6" - jest-resolve "^25.5.1" - jest-resolve-dependencies "^25.5.4" - jest-runner "^25.5.4" - jest-runtime "^25.5.4" - jest-snapshot "^25.5.1" - jest-util "^25.5.0" - jest-validate "^25.5.0" - jest-watcher "^25.5.0" + jest-changed-files "^26.6.2" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-resolve-dependencies "^26.6.3" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + jest-watcher "^26.6.2" micromatch "^4.0.2" p-each-series "^2.1.0" - realpath-native "^2.0.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^25.5.0": - version "25.5.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-25.5.0.tgz#aa33b0c21a716c65686638e7ef816c0e3a0c7b37" - integrity sha512-U2VXPEqL07E/V7pSZMSQCvV5Ea4lqOlT+0ZFijl/i316cRMHvZ4qC+jBdryd+lmRetjQo0YIQr6cVPNxxK87mA== +"@jest/environment@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" + integrity sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA== dependencies: - "@jest/fake-timers" "^25.5.0" - "@jest/types" "^25.5.0" - jest-mock "^25.5.0" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" -"@jest/fake-timers@^25.5.0": - version "25.5.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-25.5.0.tgz#46352e00533c024c90c2bc2ad9f2959f7f114185" - integrity sha512-9y2+uGnESw/oyOI3eww9yaxdZyHq7XvprfP/eeoCsjqKYts2yRlsHS/SgjPDV8FyMfn2nbMy8YzUk6nyvdLOpQ== +"@jest/fake-timers@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" + integrity sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA== dependencies: - "@jest/types" "^25.5.0" - jest-message-util "^25.5.0" - jest-mock "^25.5.0" - jest-util "^25.5.0" - lolex "^5.0.0" + "@jest/types" "^26.6.2" + "@sinonjs/fake-timers" "^6.0.1" + "@types/node" "*" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-util "^26.6.2" -"@jest/globals@^25.5.2": - version "25.5.2" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-25.5.2.tgz#5e45e9de8d228716af3257eeb3991cc2e162ca88" - integrity sha512-AgAS/Ny7Q2RCIj5kZ+0MuKM1wbF0WMLxbCVl/GOMoCNbODRdJ541IxJ98xnZdVSZXivKpJlNPIWa3QmY0l4CXA== +"@jest/globals@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" + integrity sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA== dependencies: - "@jest/environment" "^25.5.0" - "@jest/types" "^25.5.0" - expect "^25.5.0" + "@jest/environment" "^26.6.2" + "@jest/types" "^26.6.2" + expect "^26.6.2" -"@jest/reporters@^25.5.1": - version "25.5.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-25.5.1.tgz#cb686bcc680f664c2dbaf7ed873e93aa6811538b" - integrity sha512-3jbd8pPDTuhYJ7vqiHXbSwTJQNavczPs+f1kRprRDxETeE3u6srJ+f0NPuwvOmk+lmunZzPkYWIFZDLHQPkviw== +"@jest/reporters@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" + integrity sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^25.5.0" - "@jest/test-result" "^25.5.0" - "@jest/transform" "^25.5.1" - "@jest/types" "^25.5.0" - chalk "^3.0.0" + "@jest/console" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.2" graceful-fs "^4.2.4" istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^4.0.0" + istanbul-lib-instrument "^4.0.3" istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.2" - jest-haste-map "^25.5.1" - jest-resolve "^25.5.1" - jest-util "^25.5.0" - jest-worker "^25.5.0" + jest-haste-map "^26.6.2" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" slash "^3.0.0" source-map "^0.6.0" - string-length "^3.1.0" + string-length "^4.0.1" terminal-link "^2.0.0" - v8-to-istanbul "^4.1.3" + v8-to-istanbul "^7.0.0" optionalDependencies: - node-notifier "^6.0.0" + node-notifier "^8.0.0" -"@jest/source-map@^25.5.0": - version "25.5.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-25.5.0.tgz#df5c20d6050aa292c2c6d3f0d2c7606af315bd1b" - integrity sha512-eIGx0xN12yVpMcPaVpjXPnn3N30QGJCJQSkEDUt9x1fI1Gdvb07Ml6K5iN2hG7NmMP6FDmtPEssE3z6doOYUwQ== +"@jest/source-map@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" + integrity sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA== dependencies: callsites "^3.0.0" graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^25.5.0": - version "25.5.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-25.5.0.tgz#139a043230cdeffe9ba2d8341b27f2efc77ce87c" - integrity sha512-oV+hPJgXN7IQf/fHWkcS99y0smKLU2czLBJ9WA0jHITLst58HpQMtzSYxzaBvYc6U5U6jfoMthqsUlUlbRXs0A== +"@jest/test-result@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" + integrity sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ== dependencies: - "@jest/console" "^25.5.0" - "@jest/types" "^25.5.0" + "@jest/console" "^26.6.2" + "@jest/types" "^26.6.2" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^25.5.4": - version "25.5.4" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-25.5.4.tgz#9b4e685b36954c38d0f052e596d28161bdc8b737" - integrity sha512-pTJGEkSeg1EkCO2YWq6hbFvKNXk8ejqlxiOg1jBNLnWrgXOkdY6UmqZpwGFXNnRt9B8nO1uWMzLLZ4eCmhkPNA== +"@jest/test-sequencer@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" + integrity sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw== dependencies: - "@jest/test-result" "^25.5.0" + "@jest/test-result" "^26.6.2" graceful-fs "^4.2.4" - jest-haste-map "^25.5.1" - jest-runner "^25.5.4" - jest-runtime "^25.5.4" + jest-haste-map "^26.6.2" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" -"@jest/transform@^25.5.1": - version "25.5.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-25.5.1.tgz#0469ddc17699dd2bf985db55fa0fb9309f5c2db3" - integrity sha512-Y8CEoVwXb4QwA6Y/9uDkn0Xfz0finGkieuV0xkdF9UtZGJeLukD5nLkaVrVsODB1ojRWlaoD0AJZpVHCSnJEvg== +"@jest/transform@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" + integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^25.5.0" + "@jest/types" "^26.6.2" babel-plugin-istanbul "^6.0.0" - chalk "^3.0.0" + chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.4" - jest-haste-map "^25.5.1" - jest-regex-util "^25.2.6" - jest-util "^25.5.0" + jest-haste-map "^26.6.2" + jest-regex-util "^26.0.0" + jest-util "^26.6.2" micromatch "^4.0.2" pirates "^4.0.1" - realpath-native "^2.0.0" slash "^3.0.0" source-map "^0.6.1" write-file-atomic "^3.0.0" @@ -455,6 +464,17 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + "@sinonjs/commons@^1.7.0": version "1.8.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" @@ -462,6 +482,24 @@ dependencies: type-detect "4.0.8" +"@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@types/babel__core@^7.0.0": + version "7.1.12" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.12.tgz#4d8e9e51eb265552a7e4f1ff2219ab6133bdfb2d" + integrity sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + "@types/babel__core@^7.1.7": version "7.1.9" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" @@ -495,6 +533,13 @@ dependencies: "@babel/types" "^7.3.0" +"@types/babel__traverse@^7.0.4": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.15.tgz#db9e4238931eb69ef8aab0ad6523d4d4caa39d03" + integrity sha512-Pzh9O3sTK8V6I1olsXpCfj2k/ygO2q1X0vhhnDrEQyYLHZesWz+zMZMVcwXLCYf0U36EtmyYaFGPfXlTtDHe3A== + dependencies: + "@babel/types" "^7.3.0" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -532,6 +577,13 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/istanbul-reports@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" + integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/jest@^25.1.1": version "25.2.1" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.2.1.tgz#9544cd438607955381c1bdbdb97767a249297db5" @@ -569,15 +621,15 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== -"@types/prettier@^1.19.0": - version "1.19.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" - integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ== +"@types/prettier@^2.0.0": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.5.tgz#b6ab3bba29e16b821d84e09ecfaded462b816b00" + integrity sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ== -"@types/stack-utils@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" - integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== +"@types/stack-utils@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" + integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== "@types/tough-cookie@*": version "4.0.0" @@ -639,35 +691,30 @@ semver "^6.3.0" tsutils "^3.17.1" -abab@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c" - integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ== +abab@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== -acorn-globals@^4.3.2: - version "4.3.4" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" - integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== dependencies: - acorn "^6.0.1" - acorn-walk "^6.0.1" + acorn "^7.1.1" + acorn-walk "^7.1.1" acorn-jsx@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== -acorn-walk@^6.0.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" - integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== - -acorn@^6.0.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" - integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@^7.1.0, acorn@^7.1.1: +acorn@^7.1.1: version "7.4.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== @@ -752,11 +799,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -804,17 +846,17 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== -babel-jest@^25.5.1: - version "25.5.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.5.1.tgz#bc2e6101f849d6f6aec09720ffc7bc5332e62853" - integrity sha512-9dA9+GmMjIzgPnYtkhBg73gOo/RHqPmLruP3BaGL4KEX3Dwz6pI8auSN8G8+iuEG90+GSswyKvslN+JYSaacaQ== +babel-jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" + integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== dependencies: - "@jest/transform" "^25.5.1" - "@jest/types" "^25.5.0" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" "@types/babel__core" "^7.1.7" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^25.5.0" - chalk "^3.0.0" + babel-preset-jest "^26.6.2" + chalk "^4.0.0" graceful-fs "^4.2.4" slash "^3.0.0" @@ -829,19 +871,20 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.5.0.tgz#129c80ba5c7fc75baf3a45b93e2e372d57ca2677" - integrity sha512-u+/W+WAjMlvoocYGTwthAiQSxDcJAyHpQ6oWlHdFZaaN+Rlk8Q7iiwDPg2lN/FyJtAYnKjFxbn7xus4HCFkg5g== +babel-plugin-jest-hoist@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" + integrity sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" -babel-preset-current-node-syntax@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.3.tgz#b4b547acddbf963cba555ba9f9cbbb70bfd044da" - integrity sha512-uyexu1sVwcdFnyq9o8UQYsXwXflIh8LvrF5+cKrYam93ned1CStffB3+BEcsxGSgagoA3GEyjDqO4a/58hyPYQ== +babel-preset-current-node-syntax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.0.tgz#cf5feef29551253471cfa82fc8e0f5063df07a77" + integrity sha512-mGkvkpocWJes1CmMKtgGUwCeeq0pOhALyymozzDWYomHTbDLwueDYG6p4TK1YOeYHCzBzYPsWkgTto10JubI1Q== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" @@ -854,14 +897,15 @@ babel-preset-current-node-syntax@^0.1.2: "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-25.5.0.tgz#c1d7f191829487a907764c65307faa0e66590b49" - integrity sha512-8ZczygctQkBU+63DtSOKGh7tFL0CeCuz+1ieud9lJ1WPQ9O6A1a/r+LGn6Y705PA6whHQ3T1XuB/PmpfNYf8Fw== +babel-preset-jest@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" + integrity sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ== dependencies: - babel-plugin-jest-hoist "^25.5.0" - babel-preset-current-node-syntax "^0.1.2" + babel-plugin-jest-hoist "^26.6.2" + babel-preset-current-node-syntax "^1.0.0" backbone@^1.4.0: version "1.4.0" @@ -936,13 +980,6 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browser-resolve@^1.11.3: - version "1.11.3" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" - integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== - dependencies: - resolve "1.1.7" - bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -987,6 +1024,11 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -1016,7 +1058,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -1024,6 +1066,11 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -1034,6 +1081,11 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +cjs-module-lexer@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" + integrity sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -1161,7 +1213,7 @@ cross-spawn@^7.0.0: shebang-command "^2.0.0" which "^2.0.1" -cssom@^0.4.1: +cssom@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== @@ -1171,7 +1223,7 @@ cssom@~0.3.6: resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== -cssstyle@^2.0.0: +cssstyle@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== @@ -1185,14 +1237,14 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -data-urls@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" - integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== dependencies: - abab "^2.0.0" - whatwg-mimetype "^2.2.0" - whatwg-url "^7.0.0" + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" debug@^2.2.0, debug@^2.3.3: version "2.6.9" @@ -1213,6 +1265,11 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decimal.js@^10.2.0: + version "10.2.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" + integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -1265,6 +1322,11 @@ diff-sequences@^25.2.6: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -1272,12 +1334,12 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -domexception@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== dependencies: - webidl-conversions "^4.0.2" + webidl-conversions "^5.0.0" ecc-jsbn@~0.1.1: version "0.1.2" @@ -1287,6 +1349,11 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +emittery@^0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" + integrity sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ== + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -1337,7 +1404,12 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@^1.11.1: +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@^1.14.1: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== @@ -1480,10 +1552,10 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^3.2.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" - integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== +execa@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== dependencies: cross-spawn "^7.0.0" get-stream "^5.0.0" @@ -1492,7 +1564,6 @@ execa@^3.2.0: merge-stream "^2.0.0" npm-run-path "^4.0.0" onetime "^5.1.0" - p-finally "^2.0.0" signal-exit "^3.0.2" strip-final-newline "^2.0.0" @@ -1514,17 +1585,17 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-25.5.0.tgz#f07f848712a2813bb59167da3fb828ca21f58bba" - integrity sha512-w7KAXo0+6qqZZhovCaBVPSIqQp7/UTcx4M9uKt2m6pd2VB1voyC8JizLRqeEqud3AAVP02g+hbErDu5gu64tlA== +expect@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" + integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== dependencies: - "@jest/types" "^25.5.0" + "@jest/types" "^26.6.2" ansi-styles "^4.0.0" - jest-get-type "^25.2.6" - jest-matcher-utils "^25.5.0" - jest-message-util "^25.5.0" - jest-regex-util "^25.2.6" + jest-get-type "^26.3.0" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-regex-util "^26.0.0" extend-shallow@^2.0.1: version "2.0.1" @@ -1694,6 +1765,11 @@ fsevents@^2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" @@ -1847,6 +1923,13 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + highlight.js@^9.17.1: version "9.18.3" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.3.tgz#a1a0a2028d5e3149e2380f8a865ee8516703d634" @@ -1857,12 +1940,12 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -html-encoding-sniffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" - integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== dependencies: - whatwg-encoding "^1.0.1" + whatwg-encoding "^1.0.5" html-escaper@^2.0.0: version "2.0.2" @@ -1989,6 +2072,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-core-module@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" + integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -2084,6 +2174,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-potential-custom-element-name@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" + integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= + is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -2104,7 +2199,7 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -is-wsl@^2.1.1: +is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -2143,7 +2238,7 @@ istanbul-lib-coverage@^3.0.0: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== -istanbul-lib-instrument@^4.0.0: +istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== @@ -2179,61 +2274,59 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-25.5.0.tgz#141cc23567ceb3f534526f8614ba39421383634c" - integrity sha512-EOw9QEqapsDT7mKF162m8HFzRPbmP8qJQny6ldVOdOVBz3ACgPm/1nAn5fPQ/NDaYhX/AHkrGwwkCncpAVSXcw== +jest-changed-files@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" + integrity sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ== dependencies: - "@jest/types" "^25.5.0" - execa "^3.2.0" + "@jest/types" "^26.6.2" + execa "^4.0.0" throat "^5.0.0" -jest-cli@^25.2.7: - version "25.5.4" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-25.5.4.tgz#b9f1a84d1301a92c5c217684cb79840831db9f0d" - integrity sha512-rG8uJkIiOUpnREh1768/N3n27Cm+xPFkSNFO91tgg+8o2rXeVLStz+vkXkGr4UtzH6t1SNbjwoiswd7p4AhHTw== +jest-cli@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" + integrity sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg== dependencies: - "@jest/core" "^25.5.4" - "@jest/test-result" "^25.5.0" - "@jest/types" "^25.5.0" - chalk "^3.0.0" + "@jest/core" "^26.6.3" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^25.5.4" - jest-util "^25.5.0" - jest-validate "^25.5.0" + jest-config "^26.6.3" + jest-util "^26.6.2" + jest-validate "^26.6.2" prompts "^2.0.1" - realpath-native "^2.0.0" - yargs "^15.3.1" + yargs "^15.4.1" -jest-config@^25.5.4: - version "25.5.4" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-25.5.4.tgz#38e2057b3f976ef7309b2b2c8dcd2a708a67f02c" - integrity sha512-SZwR91SwcdK6bz7Gco8qL7YY2sx8tFJYzvg216DLihTWf+LKY/DoJXpM9nTzYakSyfblbqeU48p/p7Jzy05Atg== +jest-config@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" + integrity sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^25.5.4" - "@jest/types" "^25.5.0" - babel-jest "^25.5.1" - chalk "^3.0.0" + "@jest/test-sequencer" "^26.6.3" + "@jest/types" "^26.6.2" + babel-jest "^26.6.3" + chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" - jest-environment-jsdom "^25.5.0" - jest-environment-node "^25.5.0" - jest-get-type "^25.2.6" - jest-jasmine2 "^25.5.4" - jest-regex-util "^25.2.6" - jest-resolve "^25.5.1" - jest-util "^25.5.0" - jest-validate "^25.5.0" + jest-environment-jsdom "^26.6.2" + jest-environment-node "^26.6.2" + jest-get-type "^26.3.0" + jest-jasmine2 "^26.6.3" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" micromatch "^4.0.2" - pretty-format "^25.5.0" - realpath-native "^2.0.0" + pretty-format "^26.6.2" -jest-diff@^25.2.1, jest-diff@^25.5.0: +jest-diff@^25.2.1: version "25.5.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.5.0.tgz#1dd26ed64f96667c068cef026b677dfa01afcfa9" integrity sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A== @@ -2243,305 +2336,331 @@ jest-diff@^25.2.1, jest-diff@^25.5.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-docblock@^25.3.0: - version "25.3.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-25.3.0.tgz#8b777a27e3477cd77a168c05290c471a575623ef" - integrity sha512-aktF0kCar8+zxRHxQZwxMy70stc9R1mOmrLsT5VO3pIT0uzGRSDAXxSlz4NqQWpuLjPpuMhPRl7H+5FRsvIQAg== +jest-diff@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== dependencies: - detect-newline "^3.0.0" + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" -jest-each@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-25.5.0.tgz#0c3c2797e8225cb7bec7e4d249dcd96b934be516" - integrity sha512-QBogUxna3D8vtiItvn54xXde7+vuzqRrEeaw8r1s+1TG9eZLVJE5ZkKoSUlqFwRjnlaA4hyKGiu9OlkFIuKnjA== +jest-docblock@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" + integrity sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w== dependencies: - "@jest/types" "^25.5.0" - chalk "^3.0.0" - jest-get-type "^25.2.6" - jest-util "^25.5.0" - pretty-format "^25.5.0" - -jest-environment-jsdom@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-25.5.0.tgz#dcbe4da2ea997707997040ecf6e2560aec4e9834" - integrity sha512-7Jr02ydaq4jaWMZLY+Skn8wL5nVIYpWvmeatOHL3tOcV3Zw8sjnPpx+ZdeBfc457p8jCR9J6YCc+Lga0oIy62A== - dependencies: - "@jest/environment" "^25.5.0" - "@jest/fake-timers" "^25.5.0" - "@jest/types" "^25.5.0" - jest-mock "^25.5.0" - jest-util "^25.5.0" - jsdom "^15.2.1" + detect-newline "^3.0.0" -jest-environment-node@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-25.5.0.tgz#0f55270d94804902988e64adca37c6ce0f7d07a1" - integrity sha512-iuxK6rQR2En9EID+2k+IBs5fCFd919gVVK5BeND82fYeLWPqvRcFNPKu9+gxTwfB5XwBGBvZ0HFQa+cHtIoslA== - dependencies: - "@jest/environment" "^25.5.0" - "@jest/fake-timers" "^25.5.0" - "@jest/types" "^25.5.0" - jest-mock "^25.5.0" - jest-util "^25.5.0" - semver "^6.3.0" +jest-each@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" + integrity sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A== + dependencies: + "@jest/types" "^26.6.2" + chalk "^4.0.0" + jest-get-type "^26.3.0" + jest-util "^26.6.2" + pretty-format "^26.6.2" + +jest-environment-jsdom@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" + integrity sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" + jsdom "^16.4.0" + +jest-environment-node@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" + integrity sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" jest-get-type@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== -jest-haste-map@^25.5.1: - version "25.5.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-25.5.1.tgz#1df10f716c1d94e60a1ebf7798c9fb3da2620943" - integrity sha512-dddgh9UZjV7SCDQUrQ+5t9yy8iEgKc1AKqZR9YDww8xsVOtzPQSMVLDChc21+g29oTRexb9/B0bIlZL+sWmvAQ== +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== + +jest-haste-map@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" + integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== dependencies: - "@jest/types" "^25.5.0" + "@jest/types" "^26.6.2" "@types/graceful-fs" "^4.1.2" + "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.4" - jest-serializer "^25.5.0" - jest-util "^25.5.0" - jest-worker "^25.5.0" + jest-regex-util "^26.0.0" + jest-serializer "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" micromatch "^4.0.2" sane "^4.0.3" walker "^1.0.7" - which "^2.0.2" optionalDependencies: fsevents "^2.1.2" -jest-jasmine2@^25.5.4: - version "25.5.4" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-25.5.4.tgz#66ca8b328fb1a3c5364816f8958f6970a8526968" - integrity sha512-9acbWEfbmS8UpdcfqnDO+uBUgKa/9hcRh983IHdM+pKmJPL77G0sWAAK0V0kr5LK3a8cSBfkFSoncXwQlRZfkQ== +jest-jasmine2@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" + integrity sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^25.5.0" - "@jest/source-map" "^25.5.0" - "@jest/test-result" "^25.5.0" - "@jest/types" "^25.5.0" - chalk "^3.0.0" + "@jest/environment" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" co "^4.6.0" - expect "^25.5.0" + expect "^26.6.2" is-generator-fn "^2.0.0" - jest-each "^25.5.0" - jest-matcher-utils "^25.5.0" - jest-message-util "^25.5.0" - jest-runtime "^25.5.4" - jest-snapshot "^25.5.1" - jest-util "^25.5.0" - pretty-format "^25.5.0" + jest-each "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + pretty-format "^26.6.2" throat "^5.0.0" -jest-leak-detector@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-25.5.0.tgz#2291c6294b0ce404241bb56fe60e2d0c3e34f0bb" - integrity sha512-rV7JdLsanS8OkdDpZtgBf61L5xZ4NnYLBq72r6ldxahJWWczZjXawRsoHyXzibM5ed7C2QRjpp6ypgwGdKyoVA== +jest-leak-detector@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz#7717cf118b92238f2eba65054c8a0c9c653a91af" + integrity sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg== dependencies: - jest-get-type "^25.2.6" - pretty-format "^25.5.0" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" -jest-matcher-utils@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.5.0.tgz#fbc98a12d730e5d2453d7f1ed4a4d948e34b7867" - integrity sha512-VWI269+9JS5cpndnpCwm7dy7JtGQT30UHfrnM3mXl22gHGt/b7NkjBqXfbhZ8V4B7ANUsjK18PlSBmG0YH7gjw== +jest-matcher-utils@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" + integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== dependencies: - chalk "^3.0.0" - jest-diff "^25.5.0" - jest-get-type "^25.2.6" - pretty-format "^25.5.0" + chalk "^4.0.0" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" -jest-message-util@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-25.5.0.tgz#ea11d93204cc7ae97456e1d8716251185b8880ea" - integrity sha512-ezddz3YCT/LT0SKAmylVyWWIGYoKHOFOFXx3/nA4m794lfVUskMcwhip6vTgdVrOtYdjeQeis2ypzes9mZb4EA== +jest-message-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" + integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^25.5.0" - "@types/stack-utils" "^1.0.1" - chalk "^3.0.0" + "@jest/types" "^26.6.2" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" graceful-fs "^4.2.4" micromatch "^4.0.2" + pretty-format "^26.6.2" slash "^3.0.0" - stack-utils "^1.0.1" + stack-utils "^2.0.2" -jest-mock@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-25.5.0.tgz#a91a54dabd14e37ecd61665d6b6e06360a55387a" - integrity sha512-eXWuTV8mKzp/ovHc5+3USJMYsTBhyQ+5A1Mak35dey/RG8GlM4YWVylZuGgVXinaW6tpvk/RSecmF37FKUlpXA== +jest-mock@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" + integrity sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew== dependencies: - "@jest/types" "^25.5.0" + "@jest/types" "^26.6.2" + "@types/node" "*" -jest-pnp-resolver@^1.2.1: +jest-pnp-resolver@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== -jest-regex-util@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-25.2.6.tgz#d847d38ba15d2118d3b06390056028d0f2fd3964" - integrity sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw== +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== -jest-resolve-dependencies@^25.5.4: - version "25.5.4" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-25.5.4.tgz#85501f53957c8e3be446e863a74777b5a17397a7" - integrity sha512-yFmbPd+DAQjJQg88HveObcGBA32nqNZ02fjYmtL16t1xw9bAttSn5UGRRhzMHIQbsep7znWvAvnD4kDqOFM0Uw== +jest-resolve-dependencies@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" + integrity sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg== dependencies: - "@jest/types" "^25.5.0" - jest-regex-util "^25.2.6" - jest-snapshot "^25.5.1" + "@jest/types" "^26.6.2" + jest-regex-util "^26.0.0" + jest-snapshot "^26.6.2" -jest-resolve@^25.5.1: - version "25.5.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-25.5.1.tgz#0e6fbcfa7c26d2a5fe8f456088dc332a79266829" - integrity sha512-Hc09hYch5aWdtejsUZhA+vSzcotf7fajSlPA6EZPE1RmPBAD39XtJhvHWFStid58iit4IPDLI/Da4cwdDmAHiQ== +jest-resolve@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" + integrity sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ== dependencies: - "@jest/types" "^25.5.0" - browser-resolve "^1.11.3" - chalk "^3.0.0" + "@jest/types" "^26.6.2" + chalk "^4.0.0" graceful-fs "^4.2.4" - jest-pnp-resolver "^1.2.1" + jest-pnp-resolver "^1.2.2" + jest-util "^26.6.2" read-pkg-up "^7.0.1" - realpath-native "^2.0.0" - resolve "^1.17.0" + resolve "^1.18.1" slash "^3.0.0" -jest-runner@^25.5.4: - version "25.5.4" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-25.5.4.tgz#ffec5df3875da5f5c878ae6d0a17b8e4ecd7c71d" - integrity sha512-V/2R7fKZo6blP8E9BL9vJ8aTU4TH2beuqGNxHbxi6t14XzTb+x90B3FRgdvuHm41GY8ch4xxvf0ATH4hdpjTqg== +jest-runner@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" + integrity sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ== dependencies: - "@jest/console" "^25.5.0" - "@jest/environment" "^25.5.0" - "@jest/test-result" "^25.5.0" - "@jest/types" "^25.5.0" - chalk "^3.0.0" + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.7.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-config "^25.5.4" - jest-docblock "^25.3.0" - jest-haste-map "^25.5.1" - jest-jasmine2 "^25.5.4" - jest-leak-detector "^25.5.0" - jest-message-util "^25.5.0" - jest-resolve "^25.5.1" - jest-runtime "^25.5.4" - jest-util "^25.5.0" - jest-worker "^25.5.0" + jest-config "^26.6.3" + jest-docblock "^26.0.0" + jest-haste-map "^26.6.2" + jest-leak-detector "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" + jest-runtime "^26.6.3" + jest-util "^26.6.2" + jest-worker "^26.6.2" source-map-support "^0.5.6" throat "^5.0.0" -jest-runtime@^25.5.4: - version "25.5.4" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-25.5.4.tgz#dc981fe2cb2137abcd319e74ccae7f7eeffbfaab" - integrity sha512-RWTt8LeWh3GvjYtASH2eezkc8AehVoWKK20udV6n3/gC87wlTbE1kIA+opCvNWyyPeBs6ptYsc6nyHUb1GlUVQ== - dependencies: - "@jest/console" "^25.5.0" - "@jest/environment" "^25.5.0" - "@jest/globals" "^25.5.2" - "@jest/source-map" "^25.5.0" - "@jest/test-result" "^25.5.0" - "@jest/transform" "^25.5.1" - "@jest/types" "^25.5.0" +jest-runtime@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" + integrity sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw== + dependencies: + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/globals" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" "@types/yargs" "^15.0.0" - chalk "^3.0.0" + chalk "^4.0.0" + cjs-module-lexer "^0.6.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.4" - jest-config "^25.5.4" - jest-haste-map "^25.5.1" - jest-message-util "^25.5.0" - jest-mock "^25.5.0" - jest-regex-util "^25.2.6" - jest-resolve "^25.5.1" - jest-snapshot "^25.5.1" - jest-util "^25.5.0" - jest-validate "^25.5.0" - realpath-native "^2.0.0" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" slash "^3.0.0" strip-bom "^4.0.0" - yargs "^15.3.1" + yargs "^15.4.1" -jest-serializer@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-25.5.0.tgz#a993f484e769b4ed54e70e0efdb74007f503072b" - integrity sha512-LxD8fY1lByomEPflwur9o4e2a5twSQ7TaVNLlFUuToIdoJuBt8tzHfCsZ42Ok6LkKXWzFWf3AGmheuLAA7LcCA== +jest-serializer@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" + integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== dependencies: + "@types/node" "*" graceful-fs "^4.2.4" -jest-snapshot@^25.5.1: - version "25.5.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-25.5.1.tgz#1a2a576491f9961eb8d00c2e5fd479bc28e5ff7f" - integrity sha512-C02JE1TUe64p2v1auUJ2ze5vcuv32tkv9PyhEb318e8XOKF7MOyXdJ7kdjbvrp3ChPLU2usI7Rjxs97Dj5P0uQ== +jest-snapshot@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" + integrity sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^25.5.0" - "@types/prettier" "^1.19.0" - chalk "^3.0.0" - expect "^25.5.0" + "@jest/types" "^26.6.2" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.0.0" + chalk "^4.0.0" + expect "^26.6.2" graceful-fs "^4.2.4" - jest-diff "^25.5.0" - jest-get-type "^25.2.6" - jest-matcher-utils "^25.5.0" - jest-message-util "^25.5.0" - jest-resolve "^25.5.1" - make-dir "^3.0.0" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + jest-haste-map "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" natural-compare "^1.4.0" - pretty-format "^25.5.0" - semver "^6.3.0" + pretty-format "^26.6.2" + semver "^7.3.2" -jest-util@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-25.5.0.tgz#31c63b5d6e901274d264a4fec849230aa3fa35b0" - integrity sha512-KVlX+WWg1zUTB9ktvhsg2PXZVdkI1NBevOJSkTKYAyXyH4QSvh+Lay/e/v+bmaFfrkfx43xD8QTfgobzlEXdIA== +jest-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" + integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== dependencies: - "@jest/types" "^25.5.0" - chalk "^3.0.0" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" graceful-fs "^4.2.4" is-ci "^2.0.0" - make-dir "^3.0.0" + micromatch "^4.0.2" -jest-validate@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-25.5.0.tgz#fb4c93f332c2e4cf70151a628e58a35e459a413a" - integrity sha512-okUFKqhZIpo3jDdtUXUZ2LxGUZJIlfdYBvZb1aczzxrlyMlqdnnws9MOxezoLGhSaFc2XYaHNReNQfj5zPIWyQ== +jest-validate@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" + integrity sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ== dependencies: - "@jest/types" "^25.5.0" - camelcase "^5.3.1" - chalk "^3.0.0" - jest-get-type "^25.2.6" + "@jest/types" "^26.6.2" + camelcase "^6.0.0" + chalk "^4.0.0" + jest-get-type "^26.3.0" leven "^3.1.0" - pretty-format "^25.5.0" + pretty-format "^26.6.2" -jest-watcher@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-25.5.0.tgz#d6110d101df98badebe435003956fd4a465e8456" - integrity sha512-XrSfJnVASEl+5+bb51V0Q7WQx65dTSk7NL4yDdVjPnRNpM0hG+ncFmDYJo9O8jaSRcAitVbuVawyXCRoxGrT5Q== +jest-watcher@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" + integrity sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ== dependencies: - "@jest/test-result" "^25.5.0" - "@jest/types" "^25.5.0" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" ansi-escapes "^4.2.1" - chalk "^3.0.0" - jest-util "^25.5.0" - string-length "^3.1.0" + chalk "^4.0.0" + jest-util "^26.6.2" + string-length "^4.0.1" -jest-worker@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1" - integrity sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw== +jest-worker@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== dependencies: + "@types/node" "*" merge-stream "^2.0.0" supports-color "^7.0.0" -jest@^25.1.0: - version "25.2.7" - resolved "https://registry.yarnpkg.com/jest/-/jest-25.2.7.tgz#3929a5f35cdd496f7756876a206b99a94e1e09ae" - integrity sha512-XV1n/CE2McCikl4tfpCY950RytHYvxdo/wvtgmn/qwA8z1s16fuvgFL/KoPrrmkqJTaPMUlLVE58pwiaTX5TdA== +jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" + integrity sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q== dependencies: - "@jest/core" "^25.2.7" + "@jest/core" "^26.6.3" import-local "^3.0.2" - jest-cli "^25.2.7" + jest-cli "^26.6.3" jquery@^3.4.1: version "3.5.1" @@ -2566,36 +2685,36 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdom@^15.2.1: - version "15.2.1" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-15.2.1.tgz#d2feb1aef7183f86be521b8c6833ff5296d07ec5" - integrity sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g== - dependencies: - abab "^2.0.0" - acorn "^7.1.0" - acorn-globals "^4.3.2" - array-equal "^1.0.0" - cssom "^0.4.1" - cssstyle "^2.0.0" - data-urls "^1.1.0" - domexception "^1.0.1" - escodegen "^1.11.1" - html-encoding-sniffer "^1.0.2" +jsdom@^16.4.0: + version "16.4.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.4.0.tgz#36005bde2d136f73eee1a830c6d45e55408edddb" + integrity sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w== + dependencies: + abab "^2.0.3" + acorn "^7.1.1" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.2.0" + data-urls "^2.0.0" + decimal.js "^10.2.0" + domexception "^2.0.1" + escodegen "^1.14.1" + html-encoding-sniffer "^2.0.1" + is-potential-custom-element-name "^1.0.0" nwsapi "^2.2.0" - parse5 "5.1.0" - pn "^1.1.0" - request "^2.88.0" - request-promise-native "^1.0.7" - saxes "^3.1.9" - symbol-tree "^3.2.2" + parse5 "5.1.1" + request "^2.88.2" + request-promise-native "^1.0.8" + saxes "^5.0.0" + symbol-tree "^3.2.4" tough-cookie "^3.0.1" - w3c-hr-time "^1.0.1" - w3c-xmlserializer "^1.1.2" - webidl-conversions "^4.0.2" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" whatwg-encoding "^1.0.5" whatwg-mimetype "^2.3.0" - whatwg-url "^7.0.0" - ws "^7.0.0" + whatwg-url "^8.0.0" + ws "^7.2.3" xml-name-validator "^3.0.0" jsesc@^2.5.1: @@ -2737,13 +2856,6 @@ lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== -lolex@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-5.1.2.tgz#953694d098ce7c07bc5ed6d0e42bc6c0c6d5a367" - integrity sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A== - dependencies: - "@sinonjs/commons" "^1.7.0" - lunr@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.8.tgz#a8b89c31f30b5a044b97d2d28e2da191b6ba2072" @@ -2931,16 +3043,17 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-notifier@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-6.0.0.tgz#cea319e06baa16deec8ce5cd7f133c4a46b68e12" - integrity sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw== +node-notifier@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.0.tgz#a7eee2d51da6d0f7ff5094bc7108c911240c1620" + integrity sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA== dependencies: growly "^1.3.0" - is-wsl "^2.1.1" - semver "^6.3.0" + is-wsl "^2.2.0" + semver "^7.3.2" shellwords "^0.1.1" - which "^1.3.1" + uuid "^8.3.0" + which "^2.0.2" normalize-package-data@^2.5.0: version "2.5.0" @@ -3052,11 +3165,6 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= -p-finally@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" - integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== - p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -3093,10 +3201,10 @@ parse-json@^5.0.0: json-parse-better-errors "^1.0.1" lines-and-columns "^1.1.6" -parse5@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" - integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== +parse5@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== parse5@^4.0.0: version "4.0.0" @@ -3157,11 +3265,6 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" - integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== - posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -3182,6 +3285,16 @@ pretty-format@^25.2.1, pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" +pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -3233,6 +3346,11 @@ react-is@^16.12.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" + integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== + read-pkg-up@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" @@ -3265,11 +3383,6 @@ readable-stream@^2.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -realpath-native@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866" - integrity sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q== - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -3317,7 +3430,7 @@ request-promise-core@1.1.4: dependencies: lodash "^4.17.19" -request-promise-native@^1.0.7: +request-promise-native@^1.0.8: version "1.0.9" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== @@ -3326,7 +3439,7 @@ request-promise-native@^1.0.7: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.88.0: +request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -3384,18 +3497,21 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= - -resolve@1.x, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.17.0, resolve@^1.3.2: +resolve@1.x, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== dependencies: path-parse "^1.0.6" +resolve@^1.18.1: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -3472,12 +3588,12 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -saxes@^3.1.9: - version "3.1.11" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" - integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g== +saxes@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== dependencies: - xmlchars "^2.1.1" + xmlchars "^2.2.0" "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0: version "5.7.1" @@ -3489,6 +3605,11 @@ semver@6.x, semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -3688,10 +3809,12 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -stack-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" - integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== +stack-utils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" + integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== + dependencies: + escape-string-regexp "^2.0.0" static-extend@^0.1.1: version "0.1.2" @@ -3706,13 +3829,13 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= -string-length@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-3.1.0.tgz#107ef8c23456e187a8abd4a61162ff4ac6e25837" - integrity sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA== +string-length@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" + integrity sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw== dependencies: - astral-regex "^1.0.0" - strip-ansi "^5.2.0" + char-regex "^1.0.2" + strip-ansi "^6.0.0" string-width@^3.0.0: version "3.1.0" @@ -3795,7 +3918,7 @@ supports-hyperlinks@^2.0.0: has-flag "^4.0.0" supports-color "^7.0.0" -symbol-tree@^3.2.2: +symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== @@ -3918,12 +4041,12 @@ tough-cookie@^3.0.1: psl "^1.1.28" punycode "^2.1.1" -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= +tr46@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479" + integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg== dependencies: - punycode "^2.1.0" + punycode "^2.1.1" ts-jest@^25.1.0: version "25.3.1" @@ -4116,15 +4239,20 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^8.3.0: + version "8.3.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" + integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg== + v8-compile-cache@^2.0.3: version "2.1.1" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== -v8-to-istanbul@^4.1.3: - version "4.1.4" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz#b97936f21c0e2d9996d4985e5c5156e9d4e49cd6" - integrity sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ== +v8-to-istanbul@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.0.0.tgz#b4fe00e35649ef7785a9b7fcebcea05f37c332fc" + integrity sha512-fLL2rFuQpMtm9r8hrAV2apXX/WqHJ6+IC4/eQVdMDGBUgH/YMV4Gv3duk3kjmyg6uiQWBAA9nJwue4iJUOkHeA== dependencies: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" @@ -4147,20 +4275,18 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -w3c-hr-time@^1.0.1: +w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== dependencies: browser-process-hrtime "^1.0.0" -w3c-xmlserializer@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794" - integrity sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg== +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== dependencies: - domexception "^1.0.1" - webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" walker@^1.0.7, walker@~1.0.5: @@ -4170,38 +4296,43 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== -whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== dependencies: iconv-lite "0.4.24" -whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: +whatwg-mimetype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== -whatwg-url@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" - integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== +whatwg-url@^8.0.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.4.0.tgz#50fb9615b05469591d2b2bd6dfaed2942ed72837" + integrity sha512-vwTUFf6V4zhcPkWp/4CQPr1TW9Ml6SF4lVyaIMBdJw5i6qUUJ1QWM4Z6YYVkfka0OUIzVo/0aNtGVGk256IKWw== dependencies: lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" + tr46 "^2.0.2" + webidl-conversions "^6.1.0" which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.9, which@^1.3.1: +which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -4256,17 +4387,17 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" -ws@^7.0.0: - version "7.3.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" - integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== +ws@^7.2.3: + version "7.4.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.0.tgz#a5dd76a24197940d4a8bb9e0e152bb4503764da7" + integrity sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ== xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -xmlchars@^2.1.1: +xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== @@ -4284,7 +4415,7 @@ yargs-parser@18.x, yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^15.3.1: +yargs@^15.4.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==