Skip to content

Commit

Permalink
Typing events tile renderer (#865)
Browse files Browse the repository at this point in the history
* TilesRenderer.d.ts: add types for events

* test: add test to check exported APIs

* fix(ReorientationPlugin.d.ts): fix incorrect class name
  • Loading branch information
sguimmara authored Dec 22, 2024
1 parent 2c759f0 commit bdea72b
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 9 deletions.
4 changes: 3 additions & 1 deletion jest.config.json
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
{}
{
"testPathIgnorePatterns": ["types"]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"start": "vite --config ./vite.config.js",
"build-examples": "vite build --config ./vite.config.js",
"lint": "eslint \"src/**/*.{js,jsx,ts}\" \"test/**/*.js\" \"example/*.{js,jsx}\" && tsc -p tsconfig.json --noEmit",
"test": "jest"
"test": "tsc --project tsconfig.test.json && jest"
},
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/three/ReorientationPlugin.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export class GLTFExtensionsPlugin {
export class ReorientationPlugin {

constructor( options: {
up: '+x' | '-x' | '+y' | '-y' | '+z' | '-z',
Expand Down
72 changes: 66 additions & 6 deletions src/three/TilesRenderer.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import { Box3, Camera, Vector2, Matrix4, WebGLRenderer, Object3D, LoadingManager, Sphere } from 'three';
import { Box3, Camera, Vector2, Matrix4, WebGLRenderer, Object3D, LoadingManager, Sphere, EventListener, EventDispatcher, BaseEvent } from 'three';
import { Tile } from '../base/Tile';
import { TilesRendererBase } from '../base/TilesRendererBase';
import { TilesGroup } from './TilesGroup';
import { Ellipsoid } from './math/Ellipsoid';

export class TilesRenderer extends TilesRendererBase {
export interface TilesRendererEventMap {
'add-camera': { camera: Camera };
'delete-camera': { camera: Camera };
'camera-resolution-change': {};
'load-tile-set': { tileSet: object, url: string };
'tiles-load-start': {};
'tiles-load-end': {};
'load-content': {};
'load-model': { scene: Object3D; tile: Tile };
'dispose-model': { scene: Object3D; tile: Tile };
'tile-visibility-change': { scene: Object3D; tile: Tile; visible: boolean };
'update-before': {};
'update-after': {};
}

export class TilesRenderer<TEventMap extends TilesRendererEventMap = TilesRendererEventMap> extends TilesRendererBase implements EventDispatcher<TEventMap> {

ellipsoid: Ellipsoid;
autoDisableRendererCulling : boolean;
Expand All @@ -28,9 +43,54 @@ export class TilesRenderer extends TilesRendererBase {

forEachLoadedModel( callback : ( scene : Object3D, tile : Tile ) => void ) : void;

addEventListener( type: string, cb: ( e : object ) => void );
hasEventListener( type: string, cb: ( e : object ) => void );
removeEventListener( type: string, cb: ( e : object ) => void );
dispatchEvent( e : object );
/**
* Adds a listener to an event type.
* @param type The type of event to listen to.
* @param listener The function that gets called when the event is fired.
*/
addEventListener<T extends Extract<keyof TEventMap, string>>(
type: T,
listener: EventListener<TEventMap[T], T, this>
): void;
addEventListener<T extends string>(
type: T,
listener: EventListener<{}, T, this>
): void;

/**
* Checks if listener is added to an event type.
* @param type The type of event to listen to.
* @param listener The function that gets called when the event is fired.
*/
hasEventListener<T extends Extract<keyof TEventMap, string>>(
type: T,
listener: EventListener<TEventMap[T], T, this>
): boolean;
hasEventListener<T extends string>(
type: T,
listener: EventListener<{}, T, this>
): boolean;

/**
* Removes a listener from an event type.
* @param type The type of the listener that gets removed.
* @param listener The listener function that gets removed.
*/
removeEventListener<T extends Extract<keyof TEventMap, string>>(
type: T,
listener: EventListener<TEventMap[T], T, this>
): void;
removeEventListener<T extends string>(
type: T,
listener: EventListener<{}, T, this>
): void;

/**
* Fire an event type.
* @param event The event that gets fired.
*/
dispatchEvent<T extends Extract<keyof TEventMap, string>>(
event: BaseEvent<T> & TEventMap[T]
): void;

}
37 changes: 37 additions & 0 deletions test/types/TilesRenderer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Camera, Object3D } from 'three';
import { Tile, TilesRenderer } from '../../src';

function addCamera( event: { camera: Camera } ) {}
function deleteCamera( event: { camera: Camera } ) {}
function emptyEvent( event: { } ) {}
function loadTileset( event: { tileSet: object, url: string } ) {}
function loadModel( event: { scene: Object3D; tile: Tile } ) {}
function disposeModel( event: { scene: Object3D; tile: Tile; } ) {}
function tileVisibilityChange( event: { scene: Object3D; tile: Tile; visible: boolean } ) {}

function whatever( event: unknown ) {}

// This function is not meant to be executed, but just here to
// guarantee that the exported types match what is expected.
// eslint-disable-next-line no-unused-vars
function typecheck( renderer: TilesRenderer ) {

// Check events emitted by the TilesRenderer
renderer.addEventListener( 'add-camera', addCamera );
renderer.addEventListener( 'delete-camera', deleteCamera );
renderer.addEventListener( 'camera-resolution-change', emptyEvent );
renderer.addEventListener( 'load-tile-set', loadTileset );
renderer.addEventListener( 'tiles-load-start', emptyEvent );
renderer.addEventListener( 'tiles-load-end', emptyEvent );
renderer.addEventListener( 'load-content', emptyEvent );
renderer.addEventListener( 'load-model', loadModel );
renderer.addEventListener( 'dispose-model', disposeModel );
renderer.addEventListener( 'tile-visibility-change', tileVisibilityChange );
renderer.addEventListener( 'update-before', emptyEvent );
renderer.addEventListener( 'update-after', emptyEvent );

// Check that we are still able to call an event type that is not
// known by the TilesRenderer itself.
renderer.addEventListener( 'my-unknown-event', whatever );

}
10 changes: 10 additions & 0 deletions tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
},
"include": [
// Type-based test files to check API
"test/types/"
]
}

0 comments on commit bdea72b

Please sign in to comment.