@@ -40,6 +40,8 @@ const trimUndefTail = (xs: unknown[]) => {
4040 return a ;
4141} ;
4242
43+ const CAMERA_SOURCE_INDEX = 0 ;
44+
4345function makeIssueKey ( kind : IssueKind , parts : Array < string | number | undefined > ) : string {
4446 return [ kind , ...parts . map ( ( p ) => ( p ?? '' ) . toString ( ) ) ] . join ( ':' ) ;
4547}
@@ -70,6 +72,9 @@ export class HydraEngine {
7072 private typeByName = new Map < string , TransformType > ( ) ;
7173 private inputsByName = new Map < string , string [ ] > ( ) ;
7274
75+ private isCameraInitialised = false ;
76+ private cameraInitError : string | null = null ;
77+
7378 private onWindowResize ( ) : void {
7479 if ( ! this . canvas ) return ;
7580
@@ -84,6 +89,28 @@ export class HydraEngine {
8489 }
8590 }
8691
92+ private initCameraSource ( ) : void {
93+ if ( this . isCameraInitialised || this . cameraInitError || ! this . hydra ) return ;
94+
95+ this . isCameraInitialised = true ;
96+
97+ try {
98+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
99+ const hydraAny = this . hydra as any ;
100+ const source = hydraAny . sources ?. [ CAMERA_SOURCE_INDEX ] ;
101+
102+ if ( ! source || typeof source . initCam !== 'function' ) {
103+ throw new Error ( 'Hydra camera source not available' ) ;
104+ }
105+
106+ source . initCam ( ) ;
107+ } catch ( error ) {
108+ this . cameraInitError =
109+ error instanceof Error ? error . message : 'Unknown error initialising camera source' ;
110+ console . warn ( 'Camera initialisation failed:' , error ) ;
111+ }
112+ }
113+
87114 async init ( canvas : HTMLCanvasElement ) : Promise < void > {
88115 this . canvas = canvas ;
89116 this . canvas . style . backgroundColor = '#000000' ;
@@ -211,6 +238,55 @@ export class HydraEngine {
211238 return result ;
212239 }
213240
241+ if ( node . type === 'camera' ) {
242+ if ( ! this . hydra ) {
243+ const result : BuildResult = {
244+ ok : false ,
245+ issues : [
246+ {
247+ key : makeIssueKey ( 'RUNTIME_EXECUTION_ERROR' , [ node . id ] ) ,
248+ kind : 'RUNTIME_EXECUTION_ERROR' ,
249+ severity : 'error' ,
250+ message : 'Hydra is not initialised; cannot use camera source' ,
251+ nodeId : node . id
252+ }
253+ ]
254+ } ;
255+ memo . set ( nodeId , result ) ;
256+ return result ;
257+ }
258+
259+ this . initCameraSource ( ) ;
260+
261+ if ( this . cameraInitError ) {
262+ const result : BuildResult = {
263+ ok : false ,
264+ issues : [
265+ {
266+ key : makeIssueKey ( 'RUNTIME_EXECUTION_ERROR' , [ node . id ] ) ,
267+ kind : 'RUNTIME_EXECUTION_ERROR' ,
268+ severity : 'error' ,
269+ message : this . cameraInitError ,
270+ nodeId : node . id
271+ }
272+ ]
273+ } ;
274+ memo . set ( nodeId , result ) ;
275+ return result ;
276+ }
277+
278+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
279+ const gens = this . generators as any ;
280+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
281+ const hydraAny = this . hydra as any ;
282+ const source = hydraAny . sources ?. [ CAMERA_SOURCE_INDEX ] ;
283+ const chain = typeof gens . src === 'function' ? gens . src ( source ) : gens . solid ?.( 0 , 0 , 0 , 1 ) ;
284+
285+ const result : BuildResult = { ok : true , chain } ;
286+ memo . set ( nodeId , result ) ;
287+ return result ;
288+ }
289+
214290 // Validate transform exists
215291 const tType = this . typeByName . get ( node . type ) ;
216292 if ( ! tType ) {
0 commit comments