Signals
Signals in dill-pixel provide a type-safe event system for communication between different parts of your application. The framework extends the typed-signals
library to add priority ordering and convenience methods.
Core Concepts
Signal Priorities
Signals can be ordered using predefined priorities or custom numeric values:
const priorities = { highest: Number.MIN_SAFE_INTEGER, higher: -1000, high: -100, normal: 0, low: 100, lower: 1000, lowest: Number.MAX_SAFE_INTEGER,};
Basic Usage
import { Signal } from 'dill-pixel';
export default class MyScene extends Scene<MyApplication> { initialize() { // Create a signal const onScoreChange = new Signal<(score: number) => void>();
// Connect with default (normal) priority onScoreChange.connect((score) => { console.log(Score changed to: ${score}); });
// Connect with specific priority onScoreChange.connect((score) => { console.log('High priority handler: ${score}'); }, 'high'); }
updateScore(score: number) { // Emit the signal onScoreChange.emit(score); }}
Connection Methods
Standard Connection
// Basic connectionconst connection = signal.connect(callback);// Connection with priorityconst highPriority = signal.connect(callback, 'high');const customPriority = signal.connect(callback, -50);
One-time Connection
// Connect and automatically disconnect after first executionsignal.connectOnce(callback);
N-times Connection
// Connect and automatically disconnect after N executionssignal.connectNTimes(callback, 3);
Managing Connections
Manual Disconnection
// Manually disconnect a callbackconst connection = signal.connect(callback);// Later...connection.disconnect();
Disconnecting All
// Disconnect all callbackssignal.disconnectAll();
Scene Cleanup
In scenes, use addSignalConnection
to automatically manage signal lifecycles:
class MyScene extends Scene { private scoreChangeSignal: Signal<(score: number) => void>; private levelChangeSignal: Signal<(level: number) => void>;
initialize() { // These connections will be automatically cleaned up when scene is destroyed this.addSignalConnection( this.scoreChangeSignal.connect((score) => { console.log('Score changed to: ${score}'); }), this.levelChangeSignal.connect((level) => { console.log('Level changed to: ${level}'); }), ); }}
Core Application Signals
The Application provides several built-in signals through ICoreSignals:
export interface ICoreSignals { // AudioManager; onSoundStarted: Signal<(detail: SoundDetail) => void>; onSoundEnded: Signal<(detail: SoundDetail) => void>; onMuted: Signal<(muted: boolean) => void>; onMasterVolumeChanged: Signal<(volume: number) => void>; onChannelVolumeChanged: Signal<(detail: ChannelVolumeDetail) => void>; onChannelMuted: Signal<(detail: ChannelMutedDetail) => void>; // VoiceOverPlugin; onVoiceOverStart: Signal<(instance: IAudioInstance) => void>; onVoiceOverPaused: Signal<(instance: IAudioInstance) => void>; onVoiceOverComplete: Signal<(instance: IAudioInstance) => void>; onVoiceOverResumed: Signal<(instance: IAudioInstance) => void>; onVoiceOverStopped: Signal<(instance?: IAudioInstance) => void>; // FocusManager; onFocusManagerActivated: Signal<() => void>; onFocusManagerDeactivated: Signal<() => void>; onFocusLayerChange: Signal<(currentLayerId: string | number) => void>; onFocusChange: Signal<(detail: FocusChangeDetail) => void>; // i18nPlugin; onLocaleChanged: Signal<(locale: string) => void>; // actionsPlugin; onActionContextChanged: Signal<(context: string | ActionContext) => void>; // InputManager; onGamepadConnected: Signal<(gamepad: Gamepad) => void>; onGamepadDisconnected: Signal<(gamepad: Gamepad) => void>; onControllerActivated: Signal<(controller: string) => void>; onControllerDeactivated: Signal<(controller: string) => void>; // KeyboardManager; onGlobalKeyDown: Signal<(detail: KeyboardEventDetail) => void>; onGlobalKeyUp: Signal<(detail: KeyboardEventDetail) => void>; // PopupManager; onShowPopup: Signal<(detail: PopupSignalDetail) => void>; onHidePopup: Signal<(detail: PopupSignalDetail) => void>; onPopupChanged: Signal<(detail: PopupSignalDetail) => void>; // SceneManager; onSceneChangeStart: Signal<(detail: { exiting: string | null; entering: string }) => void>; onSceneChangeComplete: Signal<(detail: { current: string }) => void>; // WebEventsManager; onResize: Signal<(size: Size) => void>; onVisibilityChanged: Signal<(visible: boolean) => void>; // AssetPlugin onLoadProgress: Signal<(progress: number) => void>; onLoadComplete: Signal<() => void>; onError: Signal<(error: Error) => void>; // DataAdapter; onDataChange: Signal<(detail: DataChangeSignalDetail) => void>;}
Best Practices
-
Type Safety
- Always define signal types explicitly for better type inference
- Use TypeScript interfaces for complex signal payloads
-
Connection Management
- Use
addSignalConnection
in scenes (or any class extending dill pixel’sContainer
class) for automatic cleanup - Disconnect manual connections when no longer needed
- Consider using
connectOnce
for one-time events
- Use
-
Priority Usage
- Use predefined priorities for common cases
- Reserve custom numeric priorities for specific ordering requirements
- Keep priority system consistent across your application
-
Performance
- Avoid creating signals in tight loops
- Clean up connections when components are destroyed
- Use
connectOnce
orconnectNTimes
instead of manual disconnection when appropriate