Skip to content

Commit 2be7eae

Browse files
authored
feat: add renderable event to CoreNode (#676)
2 parents aae199f + d74c62a commit 2be7eae

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

src/common/CommonTypes.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ export type NodeTextureFreedPayload = {
8282
type: 'texture';
8383
};
8484

85+
/**
86+
* Payload for when node renderable status changes
87+
*/
88+
export type NodeRenderablePayload = {
89+
type: 'renderable';
90+
isRenderable: boolean;
91+
};
92+
8593
/**
8694
* Combined type for all failed payloads
8795
*/
@@ -105,6 +113,14 @@ export type NodeFailedEventHandler = (
105113
payload: NodeFailedPayload,
106114
) => void;
107115

116+
/**
117+
* Event handler for when the renderable status of a node changes
118+
*/
119+
export type NodeRenderableEventHandler = (
120+
target: any,
121+
payload: NodeRenderablePayload,
122+
) => void;
123+
108124
export type NodeRenderStatePayload = {
109125
type: 'renderState';
110126
payload: CoreNodeRenderState;

src/core/CoreNode.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,5 +198,54 @@ describe('set color()', () => {
198198
node.update(0, clippingRect);
199199
expect(node.isRenderable).toBe(false);
200200
});
201+
202+
it('should emit renderable event when isRenderable status changes', () => {
203+
const node = new CoreNode(stage, defaultProps);
204+
const eventCallback = vi.fn();
205+
206+
// Listen for the renderableChanged event
207+
node.on('renderable', eventCallback);
208+
209+
// Set up node as a color texture that should be renderable
210+
node.alpha = 1;
211+
node.x = 0;
212+
node.y = 0;
213+
node.width = 100;
214+
node.height = 100;
215+
node.color = 0xffffffff;
216+
217+
// Initial state should be false
218+
expect(node.isRenderable).toBe(false);
219+
expect(eventCallback).not.toHaveBeenCalled();
220+
221+
// Update should make it renderable (false -> true)
222+
node.update(0, clippingRect);
223+
expect(node.isRenderable).toBe(true);
224+
expect(eventCallback).toHaveBeenCalledWith(node, {
225+
type: 'renderable',
226+
isRenderable: true,
227+
});
228+
229+
// Reset the mock
230+
eventCallback.mockClear();
231+
232+
// Make node invisible (alpha = 0) to make it not renderable (true -> false)
233+
node.alpha = 0;
234+
node.update(1, clippingRect);
235+
expect(node.isRenderable).toBe(false);
236+
expect(eventCallback).toHaveBeenCalledWith(node, {
237+
type: 'renderable',
238+
isRenderable: false,
239+
});
240+
241+
// Reset the mock again
242+
eventCallback.mockClear();
243+
244+
// Setting same value shouldn't trigger event
245+
node.alpha = 0;
246+
node.update(2, clippingRect);
247+
expect(node.isRenderable).toBe(false);
248+
expect(eventCallback).not.toHaveBeenCalled();
249+
});
201250
});
202251
});

src/core/CoreNode.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import type {
3838
NodeTextureFailedPayload,
3939
NodeTextureFreedPayload,
4040
NodeTextureLoadedPayload,
41+
NodeRenderablePayload,
4142
} from '../common/CommonTypes.js';
4243
import { EventEmitter } from '../common/EventEmitter.js';
4344
import {
@@ -1515,7 +1516,16 @@ export class CoreNode extends EventEmitter {
15151516
* @param isRenderable - The new renderable state
15161517
*/
15171518
setRenderable(isRenderable: boolean) {
1519+
const previousIsRenderable = this.isRenderable;
15181520
this.isRenderable = isRenderable;
1521+
1522+
// Emit event if renderable status has changed
1523+
if (previousIsRenderable !== isRenderable) {
1524+
this.emit('renderable', {
1525+
type: 'renderable',
1526+
isRenderable,
1527+
} satisfies NodeRenderablePayload);
1528+
}
15191529
}
15201530

15211531
/**

0 commit comments

Comments
 (0)