Skip to content

Commit

Permalink
events: improve naming and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
sguimmara committed Sep 10, 2023
1 parent 379834f commit f548ef0
Show file tree
Hide file tree
Showing 13 changed files with 57 additions and 45 deletions.
16 changes: 8 additions & 8 deletions src/core/EventDispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@ import { EventHandler, Observable, ObservableEvent } from "./Observable";
* @param T The observed object type.
* @param TEvents The type of events.
*/
export class EventDispatcher<T extends object, TEvents> implements Observable<T, TEvents> {
private readonly handlers: Map<string, EventHandler<T, unknown>[]>;
private readonly emitter: T;
export class EventDispatcher<TSource extends object, TEvents> implements Observable<TSource, TEvents> {
private readonly handlers: Map<string, EventHandler<TSource, unknown>[]>;
private readonly source: TSource;

constructor(emitter: T) {
constructor(source: TSource) {
this.handlers = new Map();
this.emitter = emitter;
this.source = source;
}

dispatch<K extends keyof TEvents>(type: K, value?: TEvents[K]) {
dispatch<Type extends keyof TEvents>(type: Type, value?: TEvents[Type]) {
const key = type as string;
if (this.handlers.has(key)) {
const handlers = this.handlers.get(key);
handlers.forEach(fn => {
fn(new ObservableEvent<T, TEvents[K]>(this.emitter, value));
fn(new ObservableEvent<TSource, TEvents[Type]>(this.source, value));
});
}
}

on<K extends keyof TEvents>(type: K, handler: EventHandler<T, TEvents[K]>): void {
on<Type extends keyof TEvents>(type: Type, handler: EventHandler<TSource, TEvents[Type]>): void {
if (!type) {
throw new Error('missing event name');
}
Expand Down
28 changes: 20 additions & 8 deletions src/core/Observable.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
export type EventHandler<TSource, T> = (event: ObservableEvent<TSource, T>) => void;

export class ObservableEvent<TSource, T> {
readonly emitter: TSource;
readonly value: T;
/**
* An event emitted by an {@link Observable}
* @param TSource The type of the event source.
* @param TArgs The type of the event argument.
*/
export class ObservableEvent<TSource, TArgs> {
/**
* The source of the event.
*/
readonly source: TSource;
/**
* The optional argument of the event.
*/
readonly value: TArgs;

constructor(emitter: TSource, value: T) {
this.emitter = emitter;
constructor(source: TSource, value: TArgs) {
this.source = source;
this.value = value;
}
}

/**
* Trait for objects that emit events.
* @typeParam Events The type of events.
* @param TSource The type of the source.
* @param Events The type of events.
*/

export interface Observable<TSource, Events> {
Expand All @@ -21,7 +33,7 @@ export interface Observable<TSource, Events> {
* @param type The event type.
* @param handler The event handler.
* @example
* myObservable.on('destroy', evt => console.info(`${evt.emitter} was destroyed`));
* myObservable.on('destroyed', evt => console.info(`${evt.source} was destroyed`));
*/
on<K extends keyof Events>(type: K, handler: EventHandler<TSource, Events[K]>): void;
on<Type extends keyof Events>(type: Type, handler: EventHandler<TSource, Events[Type]>): void;
}
4 changes: 2 additions & 2 deletions src/geometries/Mesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type Attribute =
* The supported event names.
*/
export interface Events {
'destroy': undefined;
'destroyed': undefined;
}

function initializeArray(vertexCount: number, elementSize: number, fillValue: number) {
Expand Down Expand Up @@ -134,7 +134,7 @@ export default class Mesh implements Version, Destroy, Clone, Observable<Mesh, E
}

destroy(): void {
this.dispatcher.dispatch("destroy");
this.dispatcher.dispatch('destroyed');
}

getIndices(): Uint16Array | Uint32Array {
Expand Down
4 changes: 2 additions & 2 deletions src/materials/Material.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ function allocateUniforms(layout: UniformInfo[]): UntypedUniform[] {
}

export interface Events {
"destroy": undefined;
'destroyed': undefined;
};

export default class Material implements Observable<Material, Events>, Destroy, Version {
Expand Down Expand Up @@ -193,7 +193,7 @@ export default class Material implements Observable<Material, Events>, Destroy,
}

destroy() {
this.dispatcher.dispatch("destroy", undefined);
this.dispatcher.dispatch('destroyed', undefined);
}

on<K extends keyof Events>(type: K, handler: EventHandler<Material, Events[K]>): void {
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/BufferStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class BufferStore implements Service, Stats {
let storage = this.geometryStorages.get(mesh.id);
if (!storage) {
storage = new GeometryStorage(mesh);
mesh.on('destroy', evt => this.onGeometryDestroyed(evt.emitter));
mesh.on('destroyed', evt => this.onGeometryDestroyed(evt.source));
this.geometryStorages.set(mesh.id, storage);
} else if (storage.attributeBuffers.has(slot)) {
storage.update(this.memoryManager);
Expand Down Expand Up @@ -183,7 +183,7 @@ class BufferStore implements Service, Stats {
getIndexBuffer(mesh: Mesh): GPUBuffer {
let storage = this.geometryStorages.get(mesh.id);
if (!storage) {
mesh.on('destroy', evt => this.onGeometryDestroyed(evt.emitter as Mesh));
mesh.on('destroyed', evt => this.onGeometryDestroyed(evt.source as Mesh));
storage = new GeometryStorage(mesh);
this.geometryStorages.set(mesh.id, storage);
} else if (storage.indexBuffer) {
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/PipelineManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class PipelineManager implements Service {
});
this.perObjectMap.set(mesh.id, perObject);

mesh.on("destroy", () => this.onMeshDestroyed(mesh));
mesh.on('destroyed', () => this.onMeshDestroyed(mesh));
} else {
this.bufferStore.updateUniform(perObject.transformUniform);
}
Expand Down Expand Up @@ -583,8 +583,8 @@ class PipelineManager implements Service {

this.perMaterialMap.set(material.id, perMaterial);

material.on("destroy", (evt) =>
this.onMaterialDestroyed(evt.emitter as Material)
material.on('destroyed', (evt) =>
this.onMaterialDestroyed(evt.source as Material)
);
} else {
this.updatePipeline(perMaterial, mesh);
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/TextureStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class TextureStore implements Service {
return this.textures.get(texture.id);
}

texture.on("destroy", () => this.onTextureDestroyed(texture));
texture.on('destroyed', () => this.onTextureDestroyed(texture));

let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST;
if (texture.source.isGPUImage) {
Expand Down
4 changes: 2 additions & 2 deletions src/scene/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface Events {
/**
* Raised when the node is destroyed.
*/
'destroy': undefined;
'destroyed': undefined;
/**
* Raised when the children list has changed.
*/
Expand Down Expand Up @@ -77,7 +77,7 @@ export default class Node implements Observable<Node, Events>, Destroy {
}

destroy(): void {
this.dispatcher.dispatch('destroy');
this.dispatcher.dispatch('destroyed');
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/textures/Texture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Source from "./Source";
let TEXTURE_ID = 0;

export interface Events {
'destroy': undefined;
'destroyed': undefined;
}

/**
Expand Down Expand Up @@ -33,6 +33,6 @@ export default class Texture implements Observable<Texture, Events>, Destroy {
}

destroy() {
this.dispatcher.dispatch("destroy");
this.dispatcher.dispatch('destroyed');
}
}
8 changes: 4 additions & 4 deletions tests/core/EventDispatcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class MyClass {}

describe("on", () => {
it("should register the event handlers", () => {
const emitter = {};
const dispatcher = new EventDispatcher<MyClass, Events>(emitter);
const source = {};
const dispatcher = new EventDispatcher<MyClass, Events>(source);

const stringHandler = vi.fn<[ObservableEvent<MyClass, string>], void>();
dispatcher.on('baz', stringHandler);
Expand All @@ -29,8 +29,8 @@ describe("on", () => {
dispatcher.dispatch("foo", true);
dispatcher.dispatch("baz", 'hello');

expect(stringHandler).toHaveBeenCalledWith({ emitter, value: 'hello' });
expect(boolHandler).toHaveBeenCalledWith({ emitter, value: true });
expect(stringHandler).toHaveBeenCalledWith({ source, value: 'hello' });
expect(boolHandler).toHaveBeenCalledWith({ source, value: true });
});

it('should throw on missing params', () => {
Expand Down
6 changes: 3 additions & 3 deletions tests/geometries/Mesh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ describe('constructor', () => {
});
});

describe('destroy', () => {
describe('destroyed', () => {
it('should raise the destroy event', () => {
const m = new Mesh();
const listener = vi.fn();

m.on('destroy', listener);
m.on('destroyed', listener);

m.destroy();

expect(listener).toHaveBeenCalledWith({ emitter: m });
expect(listener).toHaveBeenCalledWith({ source: m });
});
});

Expand Down
10 changes: 5 additions & 5 deletions tests/scene/Node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ describe('constructor', () => {
});
});

describe('destroy', () => {
it('should dispatch a "destroy" event', () => {
describe('destroyed', () => {
it('should dispatch a "destroyed" event', () => {
const obj = new Node();

const handler = vi.fn();
obj.on('destroy', handler);
obj.on('destroyed', handler);

obj.destroy();

expect(handler).toHaveBeenCalledWith({ emitter: obj });
expect(handler).toHaveBeenCalledWith({ source: obj });
});
});

Expand Down Expand Up @@ -50,7 +50,7 @@ describe('add', () => {

parent.add(child);

expect(handler).toHaveBeenCalledWith({ emitter: child, value: { old: undefined, new: parent } });
expect(handler).toHaveBeenCalledWith({ source: child, value: { old: undefined, new: parent } });
});
});

Expand Down
6 changes: 3 additions & 3 deletions tests/textures/Texture.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ describe('constructor', () => {
});
});

describe('destroy', () => {
describe('destroyed', () => {
it('should raise an event', () => {
const t = new Texture();

const listener = vi.fn();
t.on('destroy', listener);
t.on('destroyed', listener);

expect(listener).not.toHaveBeenCalled();

t.destroy();

expect(listener).toHaveBeenCalledWith({ emitter: t });
expect(listener).toHaveBeenCalledWith({ source: t });
});
});

0 comments on commit f548ef0

Please sign in to comment.