feat(manifold): add dedicated ParticleBackend (no-op transport, gates audio)
Registers a named ParticleBackend in the BackendManager + barrel in place of the inline particles PassthroughBackend. Transport is a no-op (the flow-field canvas reads engine outputs directly via rAF); selecting it gates synth audio (setMuted) like the other non-synth backends and reports a clear ready status.
This commit is contained in:
parent
711415e9ff
commit
7434b03a57
3 changed files with 38 additions and 1 deletions
|
|
@ -18,6 +18,7 @@ export { OscBridgeBackend } from './osc-backend';
|
||||||
export type { OscBackendConfig } from './osc-backend';
|
export type { OscBackendConfig } from './osc-backend';
|
||||||
export { NispsOscClient } from './osc-client';
|
export { NispsOscClient } from './osc-client';
|
||||||
export { PassthroughBackend } from './passthrough-backend';
|
export { PassthroughBackend } from './passthrough-backend';
|
||||||
|
export { ParticleBackend } from './particle-backend';
|
||||||
export {
|
export {
|
||||||
useBackendManager,
|
useBackendManager,
|
||||||
} from './useBackendManager';
|
} from './useBackendManager';
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import type { BackendId } from '../dock/output-state';
|
||||||
import { WebMidiBackend } from './midi-backend';
|
import { WebMidiBackend } from './midi-backend';
|
||||||
import { OscBridgeBackend } from './osc-backend';
|
import { OscBridgeBackend } from './osc-backend';
|
||||||
import { PassthroughBackend } from './passthrough-backend';
|
import { PassthroughBackend } from './passthrough-backend';
|
||||||
|
import { ParticleBackend } from './particle-backend';
|
||||||
|
|
||||||
/** The slice of EngineApi the manager depends on (keeps it decoupled/testable). */
|
/** The slice of EngineApi the manager depends on (keeps it decoupled/testable). */
|
||||||
export interface ManagerEngine {
|
export interface ManagerEngine {
|
||||||
|
|
@ -47,7 +48,7 @@ export class BackendManager {
|
||||||
['midi', backends?.midi ?? new WebMidiBackend()],
|
['midi', backends?.midi ?? new WebMidiBackend()],
|
||||||
['osc', backends?.osc ?? new OscBridgeBackend()],
|
['osc', backends?.osc ?? new OscBridgeBackend()],
|
||||||
['synth', backends?.synth ?? new PassthroughBackend('synth', 'Built-in Synth — audio plays in the engine')],
|
['synth', backends?.synth ?? new PassthroughBackend('synth', 'Built-in Synth — audio plays in the engine')],
|
||||||
['particles', backends?.particles ?? new PassthroughBackend('particles', 'Particle visualiser')],
|
['particles', backends?.particles ?? new ParticleBackend()],
|
||||||
['cvgate', backends?.cvgate ?? new PassthroughBackend('cvgate', 'CV / gate (via VCV bridge)')],
|
['cvgate', backends?.cvgate ?? new PassthroughBackend('cvgate', 'CV / gate (via VCV bridge)')],
|
||||||
['vcv', backends?.vcv ?? new PassthroughBackend('vcv', 'VCV bridge')],
|
['vcv', backends?.vcv ?? new PassthroughBackend('vcv', 'VCV bridge')],
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
35
manifold/src/backends/particle-backend.ts
Normal file
35
manifold/src/backends/particle-backend.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* ParticleBackend — the output backend for the Particle System mode (the DEFAULT
|
||||||
|
* mode).
|
||||||
|
*
|
||||||
|
* Transport is a NO-OP: the flow-field visualiser (console/flow-field.ts, driven
|
||||||
|
* by ParticleStage) is a SEPARATE consumer of the engine spine — it reads
|
||||||
|
* `engine.getOutputs()` directly in its own requestAnimationFrame loop and maps
|
||||||
|
* the first 20 outputs onto the visual field. So there is nothing for the
|
||||||
|
* BackendManager to "send" here.
|
||||||
|
*
|
||||||
|
* What this backend DOES contribute:
|
||||||
|
* - It is a non-synth backend, so selecting it makes the BackendManager gate
|
||||||
|
* audio (`engine.audio.setMuted(true)`) — the synth is silenced while the
|
||||||
|
* particles are on screen, exactly like the MIDI / OSC modes.
|
||||||
|
* - It reports a sensible "ready" status for the Outputs panel.
|
||||||
|
*
|
||||||
|
* It extends PassthroughBackend (the shared no-op sink) purely to keep the
|
||||||
|
* empty-`send` / nothing-to-start behaviour in one place; the audio gate lives
|
||||||
|
* in the manager (`setActive`), not here.
|
||||||
|
*/
|
||||||
|
import { PassthroughBackend } from './passthrough-backend';
|
||||||
|
import type { BackendStatus } from './backend';
|
||||||
|
|
||||||
|
export class ParticleBackend extends PassthroughBackend {
|
||||||
|
constructor() {
|
||||||
|
super('particles', 'Particle visualiser — outputs drive the flow field (no audio)');
|
||||||
|
}
|
||||||
|
|
||||||
|
override status(): BackendStatus {
|
||||||
|
return {
|
||||||
|
state: 'ready',
|
||||||
|
message: 'Particle visualiser — outputs drive the flow field (no audio)',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue