@babylonjs/mcp-servers 9.33.1 → 9.33.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -86,10 +86,10 @@ data: ${JSON.stringify({reason:r})}
86
86
 
87
87
  `);const n=await this._adapter.getDocument(t);n&&this._writeDocumentEvent(r,n),r.on("close",()=>{o.delete(r),this._recordActivity()})}async _handleGetDocumentAsync(t,r){const o=await this._adapter.getDocument(t);if(!o){this._writeJson(r,404,{error:`Document "${t.name}" not found`});return}r.statusCode=200,r.setHeader("Content-Type","application/json; charset=utf-8"),r.setHeader("Cache-Control","no-cache"),r.setHeader("X-Mcp-Editor-Session-Revision",t.revision.toString()),r.end(o)}async _handlePostDocumentAsync(t,r,o){const n=await this._readBodyAsync(r);try{JSON.parse(n)}catch{this._writeJson(o,400,{error:"Invalid JSON"});return}const i=await this._adapter.setDocument(t,n);if(typeof i=="string"&&i.length>0){this._writeJson(o,400,{error:i});return}const a=t.revision;this._touchSession(t),o.setHeader("X-Mcp-Editor-Session-Revision",t.revision.toString()),this._writeJson(o,200,{ok:!0,previousRevision:a,revision:t.revision,conflictPolicy:ca}),await this._sendDocumentUpdateAsync(t.id,!1)}async _sendDocumentUpdateAsync(t,r=!0){const o=this._sessions.get(t);if(!o)return;this._recordActivity(),r&&this._touchSession(o);const n=this._sseClients.get(t);if(!n||n.size===0)return;const i=await this._adapter.getDocument(o);if(i)for(const a of n)this._writeDocumentEvent(a,i)}_touchSession(t){t.updatedAt=Date.now(),t.revision++}_writeDocumentEvent(t,r){const o=JSON.stringify(JSON.parse(r));t.write(`data: ${o}
88
88
 
89
- `)}_isDocumentRoute(t){return t==="document"||this._legacyDocumentRoutes.has(t)}_createSessionInfo(t){const r=this._sseClients.get(t.id)?.size??0,o={sessionId:t.id,kind:t.kind,name:t.name,revision:t.revision,createdAt:t.createdAt,updatedAt:t.updatedAt,conflictPolicy:ca,subscriberCount:r,eventsUrl:`/session/${t.id}/events`,documentUrl:`/session/${t.id}/document`};for(const n of this._legacyDocumentRoutes)o[`${n}Url`]=`/session/${t.id}/${n}`;return o}_getSessionInfoList(){return[...this._sessions.values()].map(t=>this._createSessionInfo(t))}_getSseClientCount(){let t=0;for(const r of this._sseClients.values())t+=r.size;return t}async _readBodyAsync(t){const r=[];return await new Promise((o,n)=>{t.on("data",i=>r.push(i)),t.on("end",o),t.on("error",n)}),Buffer.concat(r).toString("utf-8")}_writeJson(t,r,o){t.statusCode=r,t.setHeader("Content-Type","application/json; charset=utf-8"),t.end(JSON.stringify(o))}_writeText(t,r,o){t.statusCode=r,t.setHeader("Content-Type","text/plain; charset=utf-8"),t.end(o)}}class GN{constructor(t,r={}){this._manager=null,this._sessionServer=null,this._adapter=t,this._options=r}isRunning(){return this._sessionServer?.isRunning()??!1}async startAsync(t,r){return this._manager=t,await this._getSessionServer().startAsync(r)}async stopAsync(){this._sessionServer&&await this._sessionServer.stopAsync()}createSession(t){return this._getSessionServer().createSession(t).id}getSessionIdForName(t){return this._sessionServer?.getSessionIdForName(t)}getSessionUrl(t,r){return this._getSessionServer().getSessionUrl(t,r)}notifySessionUpdate(t){this._sessionServer?.notifySessionUpdate(t)}closeSession(t){return this._sessionServer?.closeSession(t)??!1}closeSessionForName(t){return this._sessionServer?.closeSessionForName(t)??!1}getPort(){return this._sessionServer?.getPort()??0}getHealth(){return this._getSessionServer().getHealth()}getDiagnostics(){return this._getSessionServer().getDiagnostics()}_getSessionServer(){return this._sessionServer||(this._sessionServer=new BN({serverName:this._adapter.serverName,documentKind:this._adapter.documentKind,getDocument:t=>this._manager?this._adapter.getDocument(this._manager,t):void 0,setDocument:(t,r)=>this._manager?this._adapter.setDocument(this._manager,t,r):this._adapter.managerUnavailableMessage??"Document manager is not available"},this._options)),this._sessionServer}}const Xt={SceneReadyEvent:{className:"FlowGraphSceneReadyEventBlock",category:"Event",description:"Triggers when the scene is ready (all assets loaded). This is the most common entry point for a flow graph.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (use for initialization logic)"},{name:"done",description:"Fires when the event actually triggers (scene ready). USE THIS for event-driven logic."},{name:"error",description:"Fires on error"}],dataInputs:[],dataOutputs:[{name:"event",type:"string",description:"KHR_interactivity event reference for this lifecycle event (stable string ref usable with ref/extractProperty and event equality)"}]},SceneTickEvent:{className:"FlowGraphSceneTickEventBlock",category:"Event",description:"Triggers every frame (scene render loop). Provides elapsed time and delta time.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires every frame when the tick event occurs. USE THIS for per-frame logic."},{name:"error",description:"Fires on error"}],dataInputs:[],dataOutputs:[{name:"timeSinceStart",type:"number",description:"Total time since the scene started (seconds)"},{name:"deltaTime",type:"number",description:"Time since last frame (seconds)"},{name:"event",type:"string",description:"KHR_interactivity event reference for this lifecycle event (stable string ref usable with ref/extractProperty and event equality)"}],config:{useFirstTickAsStart:"boolean \u2014 start elapsed time at the first tick and leave its delta NaN (default: false)"}},MeshPickEvent:{className:"FlowGraphMeshPickEventBlock",category:"Event",description:"Triggers when a mesh is picked (clicked) by the user.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization). NOT on each pick."},{name:"done",description:"Fires each time the mesh is picked. USE THIS to react to clicks."},{name:"error"}],dataInputs:[{name:"asset",type:"any",description:"The target mesh to listen for picks on",isOptional:!0},{name:"pointerType",type:"any",description:"PointerEventTypes filter (default: POINTERPICK)",isOptional:!0}],dataOutputs:[{name:"pickedPoint",type:"Vector3",description:"World-space pick point"},{name:"pickOrigin",type:"Vector3",description:"Ray origin"},{name:"pointerId",type:"number",description:"Pointer identifier"},{name:"pickedMesh",type:"any",description:"The mesh that was picked"}],config:{stopPropagation:"boolean \u2014 whether to stop event propagation",targetMesh:"AbstractMesh reference \u2014 default target mesh"}},PointerOverEvent:{className:"FlowGraphPointerOverEventBlock",category:"Event",description:"Triggers when the pointer moves over a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer enters the mesh. USE THIS for hover logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"meshUnderPointer",type:"any",description:"The mesh under the pointer"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},PointerOutEvent:{className:"FlowGraphPointerOutEventBlock",category:"Event",description:"Triggers when the pointer moves off a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer leaves the mesh. USE THIS for hover-out logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"meshOutOfPointer",type:"any",description:"The mesh the pointer left"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},PointerDownEvent:{className:"FlowGraphPointerDownEventBlock",category:"Event",description:"Triggers when a pointer button is pressed down on a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer is pressed. USE THIS for press logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"pickedMesh",type:"any",description:"The mesh that was pressed"},{name:"pickedPoint",type:"any",description:"The 3D point where the press occurred"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},PointerUpEvent:{className:"FlowGraphPointerUpEventBlock",category:"Event",description:"Triggers when a pointer button is released on a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer is released. USE THIS for release logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"pickedMesh",type:"any",description:"The mesh that was released"},{name:"pickedPoint",type:"any",description:"The 3D point where the release occurred"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},PointerMoveEvent:{className:"FlowGraphPointerMoveEventBlock",category:"Event",description:"Triggers when the pointer moves over a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer moves. USE THIS for move logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"meshUnderPointer",type:"any",description:"The mesh under the pointer"},{name:"pickedPoint",type:"any",description:"The 3D point under the pointer"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},KeyDownEvent:{className:"FlowGraphKeyDownEventBlock",category:"Event",description:"Triggers when a keyboard key is pressed down. Can optionally ignore auto-repeat events.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the matching key-down event occurs. USE THIS for keyboard logic."},{name:"error"}],dataInputs:[{name:"key",type:"string",description:"KeyboardEvent.code value to match, such as KeyA or Space. Leave empty for any key.",isOptional:!0}],dataOutputs:[{name:"keyCode",type:"string",description:"KeyboardEvent.code for the pressed key"},{name:"keyValue",type:"string",description:"KeyboardEvent.key for the pressed key"},{name:"shiftKey",type:"boolean",description:"Whether Shift was held"},{name:"ctrlKey",type:"boolean",description:"Whether Ctrl was held"},{name:"altKey",type:"boolean",description:"Whether Alt/Option was held"},{name:"metaKey",type:"boolean",description:"Whether Meta/Cmd/Windows key was held"},{name:"commandOrCtrl",type:"boolean",description:"Whether the platform command modifier was held"},{name:"isRepeat",type:"boolean",description:"True when this key-down event is an auto-repeat event"}],config:{stopPropagation:"boolean \u2014 whether to stop event propagation",ignoreRepeat:"boolean \u2014 when true, ignores auto-repeat key-down events"}},KeyUpEvent:{className:"FlowGraphKeyUpEventBlock",category:"Event",description:"Triggers when a keyboard key is released.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the matching key-up event occurs. USE THIS for keyboard logic."},{name:"error"}],dataInputs:[{name:"key",type:"string",description:"KeyboardEvent.code value to match, such as KeyA or Space. Leave empty for any key.",isOptional:!0}],dataOutputs:[{name:"keyCode",type:"string",description:"KeyboardEvent.code for the released key"},{name:"keyValue",type:"string",description:"KeyboardEvent.key for the released key"},{name:"shiftKey",type:"boolean",description:"Whether Shift was held"},{name:"ctrlKey",type:"boolean",description:"Whether Ctrl was held"},{name:"altKey",type:"boolean",description:"Whether Alt/Option was held"},{name:"metaKey",type:"boolean",description:"Whether Meta/Cmd/Windows key was held"},{name:"commandOrCtrl",type:"boolean",description:"Whether the platform command modifier was held"}],config:{stopPropagation:"boolean \u2014 whether to stop event propagation"}},PhysicsCollisionEvent:{className:"FlowGraphPhysicsCollisionEventBlock",category:"Event",description:"Triggers when a physics body collides with another body.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time a collision occurs. USE THIS for collision logic."},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody to watch for collisions"}],dataOutputs:[{name:"otherBody",type:"any",description:"The other body in the collision"},{name:"point",type:"Vector3",description:"Collision contact point"},{name:"normal",type:"Vector3",description:"Collision normal"},{name:"impulse",type:"number",description:"Collision impulse magnitude"},{name:"distance",type:"number",description:"Penetration distance"}]},AudioSoundEndedEvent:{className:"FlowGraphSoundEndedEventBlock",category:"Event",description:"Triggers when a sound finishes playing.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the sound ends. USE THIS for sound-ended logic."},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound to watch"}],dataOutputs:[]},SendCustomEvent:{className:"FlowGraphSendCustomEventBlock",category:"Event",description:"Sends a custom event that can be received by ReceiveCustomEvent blocks. Execution block with signal flow.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[],dataOutputs:[],config:{eventId:"string \u2014 the custom event identifier",eventData:"Record<string, { type: RichType; value?: unknown }> \u2014 dynamic data inputs are created from this; value is the optional serialized default"}},ReceiveCustomEvent:{className:"FlowGraphReceiveCustomEventBlock",category:"Event",description:"Receives a custom event sent by SendCustomEvent blocks. Creates dynamic data outputs from eventData config.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the custom event is received. USE THIS for event handling."},{name:"error"}],dataInputs:[],dataOutputs:[{name:"event",type:"string",description:"KHR_interactivity event reference for the received custom event (stable string ref usable with ref/extractProperty and event equality)"}],config:{eventId:"string \u2014 must match the sender's eventId",eventData:"Record<string, { type: RichType; value?: unknown }> \u2014 dynamic data outputs are created from this; value is the optional serialized default"}},StopEventPropagation:{className:"FlowGraphStopEventPropagationBlock",category:"Event",description:"Stops propagation of an in-flight custom event (KHR_interactivity event/stopPropagation). Skips the remaining handler nodes of the currently-dispatching event referenced by the `event` input.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"event",type:"string",description:"Event reference (from an event block's `event` output) whose propagation should be stopped"},{name:"stopImmediate",type:"boolean",description:"Also stop remaining immediate handlers (default: false)",isOptional:!0}],dataOutputs:[]},ConsoleLog:{className:"FlowGraphConsoleLogBlock",category:"Execution",description:"Logs a message to the browser console. Supports template strings with {placeholder} syntax.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"message",type:"any",description:"The message to log"},{name:"logType",type:"any",description:'Log level: "log", "warn", or "error"',isOptional:!0}],dataOutputs:[],config:{messageTemplate:"string \u2014 template with {placeholder} names that become additional data inputs"}},SetProperty:{className:"FlowGraphSetPropertyBlock",category:"Execution",description:"Sets a property on a scene object (e.g. mesh.position, light.intensity). Generic and powerful.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"object",type:"any",description:"The target object (mesh, light, camera, etc.)"},{name:"value",type:"any",description:"The value to set"},{name:"propertyName",type:"any",description:"The property path (e.g. 'position', 'intensity')",isOptional:!0},{name:"customSetFunction",type:"any",description:"Custom setter function",isOptional:!0}],dataOutputs:[],config:{propertyName:"string \u2014 the property name to set",target:"any \u2014 default target object",stopOnError:"boolean \u2014 activate only error on a failed write (default: false)"}},SetVariable:{className:"FlowGraphSetVariableBlock",category:"Execution",description:"Sets a context variable that can be read by GetVariable blocks. Variables persist across executions.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"value",type:"any",description:"The value to store in the variable"}],dataOutputs:[],config:{variable:"string \u2014 the variable name to set (mutually exclusive with 'variables')",variables:"string[] \u2014 multiple variable names to set (creates one input per name)",evaluateInputsBeforeWrite:"boolean \u2014 evaluate all inputs before any variable is written (default: false)",cancelVariableAnimations:"boolean \u2014 cancel animations targeting the user-variable dictionary without firing done (default: false)"}},Branch:{className:"FlowGraphBranchBlock",category:"ControlFlow",description:"If/else branching. Routes execution to onTrue or onFalse based on a boolean condition.",signalInputs:[{name:"in"}],signalOutputs:[{name:"onTrue",description:"Fires when condition is true"},{name:"onFalse",description:"Fires when condition is false"},{name:"error"}],dataInputs:[{name:"condition",type:"boolean",description:"The branching condition"}],dataOutputs:[]},ForLoop:{className:"FlowGraphForLoopBlock",category:"ControlFlow",description:"Executes a loop body for each index from startIndex to endIndex.",signalInputs:[{name:"in"}],signalOutputs:[{name:"executionFlow",description:"Fires for each iteration"},{name:"completed",description:"Fires when the loop finishes"},{name:"error"}],dataInputs:[{name:"startIndex",type:"any",description:"Loop start index (default 0)"},{name:"endIndex",type:"any",description:"Loop end index (exclusive)"},{name:"step",type:"number",description:"Step increment (default 1)",isOptional:!0}],dataOutputs:[{name:"index",type:"FlowGraphInteger",description:"Current loop index"}],config:{initialIndex:"number \u2014 initial index override",incrementIndexWhenLoopDone:"boolean \u2014 whether to increment the index when the loop is done"}},WhileLoop:{className:"FlowGraphWhileLoopBlock",category:"ControlFlow",description:"Executes the loop body while the condition is true.",signalInputs:[{name:"in"}],signalOutputs:[{name:"executionFlow",description:"Fires for each iteration"},{name:"completed",description:"Fires when the loop exits"},{name:"error"}],dataInputs:[{name:"condition",type:"boolean",description:"Loop condition \u2014 continues while true"}],dataOutputs:[],config:{doWhile:"boolean \u2014 if true, executes the body at least once before checking the condition"}},Sequence:{className:"FlowGraphSequenceBlock",category:"ControlFlow",description:"Executes multiple output signals in order (out_0, out_1, ...). Like a sequential pipeline.",signalInputs:[{name:"in"}],signalOutputs:[{name:"error"}],dataInputs:[],dataOutputs:[],config:{outputSignalCount:"number \u2014 how many sequential outputs to create (default 1). Creates out_0, out_1, ..."}},Switch:{className:"FlowGraphSwitchBlock",category:"ControlFlow",description:"Routes execution based on a case value. Like a switch/case statement with a default.",signalInputs:[{name:"in"}],signalOutputs:[{name:"default",description:"Fires when no case matches"},{name:"error"}],dataInputs:[{name:"case",type:"any",description:"The value to switch on"}],dataOutputs:[],config:{cases:"T[] \u2014 array of case values. Creates signal output 'out_{value}' for each case"}},MultiGate:{className:"FlowGraphMultiGateBlock",category:"ControlFlow",description:"Routes execution to one of N outputs each time it is triggered. Can be sequential, random, or looping.",signalInputs:[{name:"in"},{name:"reset",description:"Resets the gate index"}],signalOutputs:[{name:"error"}],dataInputs:[],dataOutputs:[{name:"lastIndex",type:"FlowGraphInteger",description:"Index of the last output fired"}],config:{outputSignalCount:"number \u2014 how many outputs to create (out_0, out_1, ...)",isRandom:"boolean \u2014 if true, picks outputs randomly",isLoop:"boolean \u2014 if true, loops back to the first output after the last"}},WaitAll:{className:"FlowGraphWaitAllBlock",category:"ControlFlow",description:"Waits for all N signal inputs to fire before triggering the output. Useful for synchronization.",signalInputs:[{name:"reset",description:"Resets all input states"}],signalOutputs:[{name:"out",description:"Fires when all inputs have triggered"},{name:"completed"},{name:"error"}],dataInputs:[],dataOutputs:[{name:"remainingInputs",type:"FlowGraphInteger",description:"How many inputs are still pending"}],config:{inputSignalCount:"number \u2014 how many signal inputs to create (in_0, in_1, ...)"}},SetDelay:{className:"FlowGraphSetDelayBlock",category:"ControlFlow",description:"Triggers the 'done' signal after a specified duration (in seconds). The 'out' signal fires immediately.",signalInputs:[{name:"in"},{name:"cancel",description:"Cancels the pending delay"}],signalOutputs:[{name:"out",description:"Fires immediately"},{name:"done",description:"Fires after the delay"},{name:"error"}],dataInputs:[{name:"duration",type:"number",description:"Delay duration in seconds"}],dataOutputs:[{name:"lastDelayIndex",type:"FlowGraphInteger",description:"Index of the last delay set"}]},CancelDelay:{className:"FlowGraphCancelDelayBlock",category:"ControlFlow",description:"Cancels a pending delay created by SetDelay.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"delayIndex",type:"FlowGraphInteger",description:"Index of the delay to cancel"}],dataOutputs:[],config:{ignoreInvalidDelay:"boolean \u2014 ignore invalid indices while still activating out (default: false)"}},CallCounter:{className:"FlowGraphCallCounterBlock",category:"ControlFlow",description:"Counts how many times it has been triggered. Can be reset.",signalInputs:[{name:"in"},{name:"reset",description:"Resets the counter to 0"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[],dataOutputs:[{name:"count",type:"number",description:"Current call count"}]},Debounce:{className:"FlowGraphDebounceBlock",category:"ControlFlow",description:"Only fires the output after the input has been triggered N times (debounce count). Then resets.",signalInputs:[{name:"in"},{name:"reset",description:"Resets the debounce counter"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"count",type:"number",description:"Number of triggers before firing"}],dataOutputs:[{name:"currentCount",type:"number",description:"Current trigger count"}]},Throttle:{className:"FlowGraphThrottleBlock",category:"ControlFlow",description:"Limits execution to at most once per duration period (in seconds).",signalInputs:[{name:"in"},{name:"reset",description:"Resets the throttle timer"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"duration",type:"number",description:"Minimum time between executions (seconds)"}],dataOutputs:[{name:"lastRemainingTime",type:"number",description:"Time remaining until next allowed execution"}],config:{allowZeroDuration:"boolean \u2014 accept a zero duration and always activate out (default: false)"}},DoN:{className:"FlowGraphDoNBlock",category:"ControlFlow",description:"Fires the output only the first N times it is triggered, then stops. Can be reset.",signalInputs:[{name:"in"},{name:"reset",description:"Resets the execution counter"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"maxExecutions",type:"FlowGraphInteger",description:"Maximum number of times to fire"}],dataOutputs:[{name:"executionCount",type:"FlowGraphInteger",description:"How many times it has fired"}],config:{startIndex:"FlowGraphInteger \u2014 initial count value"}},FlipFlop:{className:"FlowGraphFlipFlopBlock",category:"ControlFlow",description:"Alternates between onOn and onOff signals each time it is triggered. Like a toggle switch.",signalInputs:[{name:"in"}],signalOutputs:[{name:"onOn",description:"Fires on odd triggers"},{name:"onOff",description:"Fires on even triggers"},{name:"error"}],dataInputs:[],dataOutputs:[{name:"value",type:"boolean",description:"Current toggle state"}],config:{startValue:"boolean \u2014 initial toggle state (default false)"}},PlayAnimation:{className:"FlowGraphPlayAnimationBlock",category:"Animation",description:"Plays an animation or animation group. Provides current frame and event outputs.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out",description:"Fires immediately when play starts"},{name:"done",description:"Fires when the animation finishes"},{name:"error"},{name:"animationLoopEvent",description:"Fires each time the animation loops"},{name:"animationEndEvent",description:"Fires when the animation ends"},{name:"animationGroupLoopEvent",description:"Fires when an animation group loops"}],dataInputs:[{name:"speed",type:"number",description:"Playback speed (default 0)"},{name:"loop",type:"boolean",description:"Whether to loop (default false)"},{name:"from",type:"number",description:"Start frame (default 0)"},{name:"to",type:"number",description:"End frame (default 0 = full range)"},{name:"animationGroup",type:"any",description:"AnimationGroup to play"},{name:"animation",type:"any",description:"Animation or Animation[] to play",isOptional:!0},{name:"animationTargets",type:"any",description:"Optional target array matching animation order; replaces object when supplied",isOptional:!0},{name:"object",type:"any",description:"Target object for the animation",isOptional:!0}],dataOutputs:[{name:"currentFrame",type:"number",description:"Current animation frame"},{name:"currentTime",type:"number",description:"Current animation time"},{name:"currentAnimationGroup",type:"any",description:"The active animation group"}],config:{animationGroup:"AnimationGroup \u2014 default animation group"}},StopAnimation:{className:"FlowGraphStopAnimationBlock",category:"Animation",description:"Stops a playing animation group.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"done"},{name:"error"}],dataInputs:[{name:"animationGroup",type:"any",description:"The animation group to stop"},{name:"stopAtFrame",type:"number",description:"Frame to stop at (-1 = current)",isOptional:!0}],dataOutputs:[]},PauseAnimation:{className:"FlowGraphPauseAnimationBlock",category:"Animation",description:"Pauses a playing animation group.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"animationToPause",type:"any",description:"The animation group to pause"}],dataOutputs:[]},ValueInterpolation:{className:"FlowGraphInterpolationBlock",category:"Animation",description:"Creates an Animation object from keyframe values. Use with PlayAnimation to animate properties. Takes duration/value pairs for each keyframe.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"easingFunction",type:"any",description:"Optional easing function from Easing block",isOptional:!0},{name:"propertyName",type:"any",description:"Property name(s) to animate",isOptional:!0},{name:"customBuildAnimation",type:"any",description:"Custom animation builder function",isOptional:!0}],dataOutputs:[{name:"animation",type:"any",description:"The generated Animation object"}],config:{keyFramesCount:"number \u2014 number of keyframes (creates duration_N and value_N inputs for each)",duration:"number \u2014 default duration per keyframe",propertyName:"string|string[] \u2014 property path(s) to animate",animationType:"number|FlowGraphTypes \u2014 type of animated value (e.g. BABYLON.Animation.ANIMATIONTYPE_VECTOR3)"}},Easing:{className:"FlowGraphEasingBlock",category:"Animation",description:"Creates an easing function for use with ValueInterpolation. Supports all Babylon.js easing types.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"type",type:"any",description:"EasingFunctionType enum value (default 11 = BezierCurve)"},{name:"mode",type:"number",description:"Easing mode: 0=EaseIn, 1=EaseOut, 2=EaseInOut"},{name:"parameters",type:"any",description:"Easing parameters as number array (default [1,0,0,1])",isOptional:!0}],dataOutputs:[{name:"easingFunction",type:"any",description:"The easing function object"}]},BezierCurveEasing:{className:"FlowGraphBezierCurveEasing",category:"Animation",description:"Creates a bezier curve easing function with two control points.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"mode",type:"number",description:"Easing mode: 0=EaseIn, 1=EaseOut, 2=EaseInOut"},{name:"controlPoint1",type:"Vector2",description:"First control point"},{name:"controlPoint2",type:"Vector2",description:"Second control point"}],dataOutputs:[{name:"easingFunction",type:"any",description:"The bezier easing function object"}]},Constant:{className:"FlowGraphConstantBlock",category:"Data",description:"Outputs a constant value. The type is deduced from the config value. Supports numbers, strings, booleans, vectors, colors, etc.",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"output",type:"any",description:"The constant value"}],config:{value:"any \u2014 the constant value (e.g. 42, 'hello', { value: [1,2,3], className: 'Vector3' })"}},GetVariable:{className:"FlowGraphGetVariableBlock",category:"Data",description:"Reads a context variable set by SetVariable. Variables persist across executions of the graph.",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"any",description:"The variable's current value"}],config:{variable:"string \u2014 the variable name to read",initialValue:"any \u2014 default value if the variable hasn't been set"}},GetProperty:{className:"FlowGraphGetPropertyBlock",category:"Data",description:"Reads a property from a scene object (e.g. mesh.position, light.intensity).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"object",type:"any",description:"The target object"},{name:"propertyName",type:"any",description:"The property name to read",isOptional:!0},{name:"customGetFunction",type:"any",description:"Custom getter function",isOptional:!0}],dataOutputs:[{name:"value",type:"any",description:"The property value"},{name:"isValid",type:"boolean",description:"Whether the property was found"}],config:{propertyName:"string \u2014 property path to read",object:"any \u2014 default target object",resetToDefaultWhenUndefined:"boolean \u2014 reset to default when undefined",invalidValue:"any \u2014 optional value returned with isValid=false when property resolution fails"}},GetAsset:{className:"FlowGraphGetAssetBlock",category:"Data",description:"Retrieves an asset (mesh, material, texture, etc.) from the scene's asset context by type and index.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"type",type:"any",description:"FlowGraphAssetType \u2014 the kind of asset to retrieve"},{name:"index",type:"any",description:"Index of the asset in the collection",isOptional:!0}],dataOutputs:[{name:"value",type:"any",description:"The retrieved asset"}],config:{type:"FlowGraphAssetType \u2014 asset type enum",index:"number \u2014 asset index in the collection",useIndexAsUniqueId:"boolean \u2014 whether to use index as uniqueId lookup"}},Conditional:{className:"FlowGraphConditionalBlock",category:"Data",description:"Ternary operator \u2014 returns onTrue if condition is true, onFalse otherwise. Pure data block (no signals).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"condition",type:"boolean",description:"The condition to evaluate"},{name:"onTrue",type:"any",description:"Value returned when condition is true"},{name:"onFalse",type:"any",description:"Value returned when condition is false"}],dataOutputs:[{name:"output",type:"any",description:"The selected value"}]},TransformCoordinatesSystem:{className:"FlowGraphTransformCoordinatesSystemBlock",category:"Data",description:"Transforms coordinates from one coordinate system to another using two TransformNodes.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"sourceSystem",type:"any",description:"Source TransformNode"},{name:"destinationSystem",type:"any",description:"Destination TransformNode"},{name:"inputCoordinates",type:"Vector3",description:"Coordinates to transform"}],dataOutputs:[{name:"outputCoordinates",type:"Vector3",description:"Transformed coordinates"}]},JsonPointerParser:{className:"FlowGraphJsonPointerParserBlock",category:"Data",description:"Resolves a JSON pointer path to an object and property. Used internally for glTF interop.",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"},{name:"object",type:"any"},{name:"propertyName",type:"any"},{name:"setFunction",type:"any",description:"Setter function for the resolved property (used internally by interpolation/animation)"},{name:"getFunction",type:"any",description:"Getter function for the resolved property"},{name:"generateAnimationsFunction",type:"any",description:"Builds animation property info for the resolved property"},{name:"animationTargets",type:"any",description:"Targets in the same order as the generated animations"}],config:{jsonPointer:"string \u2014 the JSON pointer path",valueType:"string \u2014 require a writable accessor with this value type when setting a property"}},DataSwitch:{className:"FlowGraphDataSwitchBlock",category:"Data",description:"Selects a data value based on a case. Like a data-only switch/case.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"case",type:"any",description:"The case value to match"},{name:"default",type:"any",description:"Default value if no case matches"}],dataOutputs:[{name:"value",type:"any",description:"The selected value"}],config:{cases:"number[] \u2014 case values. Creates data input 'in_{value}' for each case",treatCasesAsIntegers:"boolean \u2014 whether to treat case values as integers"}},Context:{className:"FlowGraphContextBlock",category:"Utility",description:"Provides access to the flow graph execution context (user variables, execution ID).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"userVariables",type:"any",description:"All user variables as a dictionary"},{name:"executionId",type:"number",description:"Current execution ID"}]},IsKeyPressed:{className:"FlowGraphIsKeyPressedBlock",category:"Utility",description:"Outputs whether a keyboard key is currently held down, optionally requiring modifier keys.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"key",type:"string",description:"KeyboardEvent.code value to check, such as KeyA, Space, ShiftLeft, or ControlLeft"},{name:"withShift",type:"boolean",description:"Require Shift to also be held",isOptional:!0},{name:"withCtrl",type:"boolean",description:"Require Ctrl to also be held",isOptional:!0},{name:"withAlt",type:"boolean",description:"Require Alt/Option to also be held",isOptional:!0},{name:"withMeta",type:"boolean",description:"Require Meta/Cmd/Windows key to also be held",isOptional:!0},{name:"withCommandOrCtrl",type:"boolean",description:"Require Cmd on macOS or Ctrl on Windows/Linux",isOptional:!0}],dataOutputs:[{name:"isPressed",type:"boolean",description:"True when the requested key and modifiers are currently held"}]},ArrayIndex:{className:"FlowGraphArrayIndexBlock",category:"Utility",description:"Retrieves an element from an array by index.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"array",type:"any",description:"The source array"},{name:"index",type:"any",description:"The index to retrieve"}],dataOutputs:[{name:"value",type:"any",description:"The element at the specified index"}]},IndexOf:{className:"FlowGraphIndexOfBlock",category:"Utility",description:"Finds the index of an element in an array.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"object",type:"any",description:"The element to search for"},{name:"array",type:"any",description:"The array to search in"}],dataOutputs:[{name:"index",type:"FlowGraphInteger",description:"The index of the element (-1 if not found)"}]},CodeExecution:{className:"FlowGraphCodeExecutionBlock",category:"Utility",description:"Executes an arbitrary JavaScript function inside the flow graph \u2014 the 'escape hatch' for any logic not covered by dedicated blocks. This is a DATA block (no signal inputs/outputs); it evaluates lazily when its 'result' output is read by a downstream block. The function signature is: (value: any, context: FlowGraphContext) => any. The 'value' input can carry any data (a mesh, a number, an object with multiple fields, etc.), and 'context' is the FlowGraphContext giving access to the scene via context.assetsContext. Use the FunctionReference block to create the function from an object + method name, or provide the function via the scene's glue code / code generator. Common use cases: physics (applyImpulse, setLinearVelocity), mesh cloning (mesh.clone), reading/writing complex properties, invoking any Babylon.js API not exposed as a dedicated block.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"function",type:"any",description:"A CodeExecutionFunction: (value, context) => result. Can come from a FunctionReference block or be set in glue code. For physics impulse example: (v, ctx) => { v.mesh.physicsBody.applyImpulse(v.impulse, v.point); return true; }"},{name:"value",type:"any",description:"The input value passed as the first argument to the function. Can be any type \u2014 a mesh, a Vector3, or a composite object with multiple fields."}],dataOutputs:[{name:"result",type:"any",description:"The return value of the function"}]},FunctionReference:{className:"FlowGraphFunctionReference",category:"Utility",description:`Creates a callable function reference. Two modes of use:
89
+ `)}_isDocumentRoute(t){return t==="document"||this._legacyDocumentRoutes.has(t)}_createSessionInfo(t){const r=this._sseClients.get(t.id)?.size??0,o={sessionId:t.id,kind:t.kind,name:t.name,revision:t.revision,createdAt:t.createdAt,updatedAt:t.updatedAt,conflictPolicy:ca,subscriberCount:r,eventsUrl:`/session/${t.id}/events`,documentUrl:`/session/${t.id}/document`};for(const n of this._legacyDocumentRoutes)o[`${n}Url`]=`/session/${t.id}/${n}`;return o}_getSessionInfoList(){return[...this._sessions.values()].map(t=>this._createSessionInfo(t))}_getSseClientCount(){let t=0;for(const r of this._sseClients.values())t+=r.size;return t}async _readBodyAsync(t){const r=[];return await new Promise((o,n)=>{t.on("data",i=>r.push(i)),t.on("end",o),t.on("error",n)}),Buffer.concat(r).toString("utf-8")}_writeJson(t,r,o){t.statusCode=r,t.setHeader("Content-Type","application/json; charset=utf-8"),t.end(JSON.stringify(o))}_writeText(t,r,o){t.statusCode=r,t.setHeader("Content-Type","text/plain; charset=utf-8"),t.end(o)}}class GN{constructor(t,r={}){this._manager=null,this._sessionServer=null,this._adapter=t,this._options=r}isRunning(){return this._sessionServer?.isRunning()??!1}async startAsync(t,r){return this._manager=t,await this._getSessionServer().startAsync(r)}async stopAsync(){this._sessionServer&&await this._sessionServer.stopAsync()}createSession(t){return this._getSessionServer().createSession(t).id}getSessionIdForName(t){return this._sessionServer?.getSessionIdForName(t)}getSessionUrl(t,r){return this._getSessionServer().getSessionUrl(t,r)}notifySessionUpdate(t){this._sessionServer?.notifySessionUpdate(t)}closeSession(t){return this._sessionServer?.closeSession(t)??!1}closeSessionForName(t){return this._sessionServer?.closeSessionForName(t)??!1}getPort(){return this._sessionServer?.getPort()??0}getHealth(){return this._getSessionServer().getHealth()}getDiagnostics(){return this._getSessionServer().getDiagnostics()}_getSessionServer(){return this._sessionServer||(this._sessionServer=new BN({serverName:this._adapter.serverName,documentKind:this._adapter.documentKind,getDocument:t=>this._manager?this._adapter.getDocument(this._manager,t):void 0,setDocument:(t,r)=>this._manager?this._adapter.setDocument(this._manager,t,r):this._adapter.managerUnavailableMessage??"Document manager is not available"},this._options)),this._sessionServer}}const Xt={SceneReadyEvent:{className:"FlowGraphSceneReadyEventBlock",category:"Event",description:"Triggers when the scene is ready (all assets loaded). This is the most common entry point for a flow graph.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (use for initialization logic)"},{name:"done",description:"Fires when the event actually triggers (scene ready). USE THIS for event-driven logic."},{name:"error",description:"Fires on error"}],dataInputs:[],dataOutputs:[{name:"event",type:"string",description:"KHR_interactivity event reference for this lifecycle event (stable string ref usable with ref/extractProperty and event equality)"}]},SceneTickEvent:{className:"FlowGraphSceneTickEventBlock",category:"Event",description:"Triggers every frame (scene render loop). Provides elapsed time and delta time.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires every frame when the tick event occurs. USE THIS for per-frame logic."},{name:"error",description:"Fires on error"}],dataInputs:[],dataOutputs:[{name:"timeSinceStart",type:"number",description:"Total time since the scene started (seconds)"},{name:"deltaTime",type:"number",description:"Time since last frame (seconds)"},{name:"event",type:"string",description:"KHR_interactivity event reference for this lifecycle event (stable string ref usable with ref/extractProperty and event equality)"}],config:{useFirstTickAsStart:"boolean \u2014 start elapsed time at the first tick and leave its delta NaN (default: false)"}},MeshPickEvent:{className:"FlowGraphMeshPickEventBlock",category:"Event",description:"Triggers when a mesh is picked (clicked) by the user.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization). NOT on each pick."},{name:"done",description:"Fires each time the mesh is picked. USE THIS to react to clicks."},{name:"error"}],dataInputs:[{name:"asset",type:"any",description:"The target mesh to listen for picks on",isOptional:!0},{name:"pointerType",type:"any",description:"PointerEventTypes filter (default: POINTERPICK)",isOptional:!0}],dataOutputs:[{name:"pickedPoint",type:"Vector3",description:"World-space pick point"},{name:"pickOrigin",type:"Vector3",description:"Ray origin"},{name:"pointerId",type:"number",description:"Pointer identifier"},{name:"pickedMesh",type:"any",description:"The mesh that was picked"}],config:{stopPropagation:"boolean \u2014 whether to stop event propagation",targetMesh:"AbstractMesh reference \u2014 default target mesh"}},MeshIntersectionEvent:{className:"FlowGraphMeshIntersectionEventBlock",category:"Event",description:"Triggers when a source mesh starts or stops intersecting one of the target meshes. Uses bounding volumes checked before each frame, so no physics engine is required.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires on every enter and exit transition. Prefer onEnter / onExit."},{name:"done",description:"Fires on every enter and exit transition. Prefer onEnter / onExit."},{name:"error"},{name:"onEnter",description:"Fires when a target mesh starts intersecting the source mesh. USE THIS for contact logic."},{name:"onExit",description:"Fires when a target mesh stops intersecting the source mesh."}],dataInputs:[{name:"sourceMesh",type:"any",description:"The mesh to check for intersections"},{name:"targetMeshes",type:"any",description:"A mesh or an array of meshes checked against the source mesh"},{name:"usePreciseIntersection",type:"boolean",description:"Use oriented bounding boxes instead of axis-aligned ones (default: false)"}],dataOutputs:[{name:"otherMesh",type:"any",description:"The target mesh that entered or exited"},{name:"isIntersecting",type:"boolean",description:"True for an enter transition, false for an exit"}]},PointerOverEvent:{className:"FlowGraphPointerOverEventBlock",category:"Event",description:"Triggers when the pointer moves over a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer enters the mesh. USE THIS for hover logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"meshUnderPointer",type:"any",description:"The mesh under the pointer"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},PointerOutEvent:{className:"FlowGraphPointerOutEventBlock",category:"Event",description:"Triggers when the pointer moves off a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer leaves the mesh. USE THIS for hover-out logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"meshOutOfPointer",type:"any",description:"The mesh the pointer left"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},PointerDownEvent:{className:"FlowGraphPointerDownEventBlock",category:"Event",description:"Triggers when a pointer button is pressed down on a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer is pressed. USE THIS for press logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"pickedMesh",type:"any",description:"The mesh that was pressed"},{name:"pickedPoint",type:"any",description:"The 3D point where the press occurred"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},PointerUpEvent:{className:"FlowGraphPointerUpEventBlock",category:"Event",description:"Triggers when a pointer button is released on a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer is released. USE THIS for release logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"pickedMesh",type:"any",description:"The mesh that was released"},{name:"pickedPoint",type:"any",description:"The 3D point where the release occurred"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},PointerMoveEvent:{className:"FlowGraphPointerMoveEventBlock",category:"Event",description:"Triggers when the pointer moves over a mesh.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the pointer moves. USE THIS for move logic."},{name:"error"}],dataInputs:[{name:"targetMesh",type:"any",description:"The mesh to watch",isOptional:!0}],dataOutputs:[{name:"pointerId",type:"number"},{name:"meshUnderPointer",type:"any",description:"The mesh under the pointer"},{name:"pickedPoint",type:"any",description:"The 3D point under the pointer"}],config:{stopPropagation:"boolean",targetMesh:"AbstractMesh reference"}},KeyDownEvent:{className:"FlowGraphKeyDownEventBlock",category:"Event",description:"Triggers when a keyboard key is pressed down. Can optionally ignore auto-repeat events.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the matching key-down event occurs. USE THIS for keyboard logic."},{name:"error"}],dataInputs:[{name:"key",type:"string",description:"KeyboardEvent.code value to match, such as KeyA or Space. Leave empty for any key.",isOptional:!0}],dataOutputs:[{name:"keyCode",type:"string",description:"KeyboardEvent.code for the pressed key"},{name:"keyValue",type:"string",description:"KeyboardEvent.key for the pressed key"},{name:"shiftKey",type:"boolean",description:"Whether Shift was held"},{name:"ctrlKey",type:"boolean",description:"Whether Ctrl was held"},{name:"altKey",type:"boolean",description:"Whether Alt/Option was held"},{name:"metaKey",type:"boolean",description:"Whether Meta/Cmd/Windows key was held"},{name:"commandOrCtrl",type:"boolean",description:"Whether the platform command modifier was held"},{name:"isRepeat",type:"boolean",description:"True when this key-down event is an auto-repeat event"}],config:{stopPropagation:"boolean \u2014 whether to stop event propagation",ignoreRepeat:"boolean \u2014 when true, ignores auto-repeat key-down events"}},KeyUpEvent:{className:"FlowGraphKeyUpEventBlock",category:"Event",description:"Triggers when a keyboard key is released.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the matching key-up event occurs. USE THIS for keyboard logic."},{name:"error"}],dataInputs:[{name:"key",type:"string",description:"KeyboardEvent.code value to match, such as KeyA or Space. Leave empty for any key.",isOptional:!0}],dataOutputs:[{name:"keyCode",type:"string",description:"KeyboardEvent.code for the released key"},{name:"keyValue",type:"string",description:"KeyboardEvent.key for the released key"},{name:"shiftKey",type:"boolean",description:"Whether Shift was held"},{name:"ctrlKey",type:"boolean",description:"Whether Ctrl was held"},{name:"altKey",type:"boolean",description:"Whether Alt/Option was held"},{name:"metaKey",type:"boolean",description:"Whether Meta/Cmd/Windows key was held"},{name:"commandOrCtrl",type:"boolean",description:"Whether the platform command modifier was held"}],config:{stopPropagation:"boolean \u2014 whether to stop event propagation"}},PhysicsCollisionEvent:{className:"FlowGraphPhysicsCollisionEventBlock",category:"Event",description:"Triggers when a physics body collides with another body.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time a collision occurs. USE THIS for collision logic."},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody to watch for collisions"}],dataOutputs:[{name:"otherBody",type:"any",description:"The other body in the collision"},{name:"point",type:"Vector3",description:"Collision contact point"},{name:"normal",type:"Vector3",description:"Collision normal"},{name:"impulse",type:"number",description:"Collision impulse magnitude"},{name:"distance",type:"number",description:"Penetration distance"}]},AudioSoundEndedEvent:{className:"FlowGraphSoundEndedEventBlock",category:"Event",description:"Triggers when a sound finishes playing.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the sound ends. USE THIS for sound-ended logic."},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound to watch (an Audio V2 sound or the name of a coordinator sound asset)"}],dataOutputs:[]},SendCustomEvent:{className:"FlowGraphSendCustomEventBlock",category:"Event",description:"Sends a custom event that can be received by ReceiveCustomEvent blocks. Execution block with signal flow.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[],dataOutputs:[],config:{eventId:"string \u2014 the custom event identifier",eventData:"Record<string, { type: RichType; value?: unknown }> \u2014 dynamic data inputs are created from this; value is the optional serialized default"}},ReceiveCustomEvent:{className:"FlowGraphReceiveCustomEventBlock",category:"Event",description:"Receives a custom event sent by SendCustomEvent blocks. Creates dynamic data outputs from eventData config.",signalInputs:[],signalOutputs:[{name:"out",description:"Fires once at graph startup (initialization)"},{name:"done",description:"Fires each time the custom event is received. USE THIS for event handling."},{name:"error"}],dataInputs:[],dataOutputs:[{name:"event",type:"string",description:"KHR_interactivity event reference for the received custom event (stable string ref usable with ref/extractProperty and event equality)"}],config:{eventId:"string \u2014 must match the sender's eventId",eventData:"Record<string, { type: RichType; value?: unknown }> \u2014 dynamic data outputs are created from this; value is the optional serialized default"}},StopEventPropagation:{className:"FlowGraphStopEventPropagationBlock",category:"Event",description:"Stops propagation of an in-flight custom event (KHR_interactivity event/stopPropagation). Skips the remaining handler nodes of the currently-dispatching event referenced by the `event` input.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"event",type:"string",description:"Event reference (from an event block's `event` output) whose propagation should be stopped"},{name:"stopImmediate",type:"boolean",description:"Also stop remaining immediate handlers (default: false)",isOptional:!0}],dataOutputs:[]},ConsoleLog:{className:"FlowGraphConsoleLogBlock",category:"Execution",description:"Logs a message to the browser console. Supports template strings with {placeholder} syntax.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"message",type:"any",description:"The message to log"},{name:"logType",type:"any",description:'Log level: "log", "warn", or "error"',isOptional:!0}],dataOutputs:[],config:{messageTemplate:"string \u2014 template with {placeholder} names that become additional data inputs"}},SetProperty:{className:"FlowGraphSetPropertyBlock",category:"Execution",description:"Sets a property on a scene object (e.g. mesh.position, light.intensity). Generic and powerful.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"object",type:"any",description:"The target object (mesh, light, camera, etc.)"},{name:"value",type:"any",description:"The value to set"},{name:"propertyName",type:"any",description:"The property path (e.g. 'position', 'intensity')",isOptional:!0},{name:"customSetFunction",type:"any",description:"Custom setter function",isOptional:!0}],dataOutputs:[],config:{propertyName:"string \u2014 the property name to set",target:"any \u2014 default target object",stopOnError:"boolean \u2014 activate only error on a failed write (default: false)"}},SetVariable:{className:"FlowGraphSetVariableBlock",category:"Execution",description:"Sets a context variable that can be read by GetVariable blocks. Variables persist across executions.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"value",type:"any",description:"The value to store in the variable"}],dataOutputs:[],config:{variable:"string \u2014 the variable name to set (mutually exclusive with 'variables')",variables:"string[] \u2014 multiple variable names to set (creates one input per name)",evaluateInputsBeforeWrite:"boolean \u2014 evaluate all inputs before any variable is written (default: false)",cancelVariableAnimations:"boolean \u2014 cancel animations targeting the user-variable dictionary without firing done (default: false)"}},Branch:{className:"FlowGraphBranchBlock",category:"ControlFlow",description:"If/else branching. Routes execution to onTrue or onFalse based on a boolean condition.",signalInputs:[{name:"in"}],signalOutputs:[{name:"onTrue",description:"Fires when condition is true"},{name:"onFalse",description:"Fires when condition is false"},{name:"error"}],dataInputs:[{name:"condition",type:"boolean",description:"The branching condition"}],dataOutputs:[]},ForLoop:{className:"FlowGraphForLoopBlock",category:"ControlFlow",description:"Executes a loop body for each index from startIndex to endIndex.",signalInputs:[{name:"in"}],signalOutputs:[{name:"executionFlow",description:"Fires for each iteration"},{name:"completed",description:"Fires when the loop finishes"},{name:"error"}],dataInputs:[{name:"startIndex",type:"any",description:"Loop start index (default 0)"},{name:"endIndex",type:"any",description:"Loop end index (exclusive)"},{name:"step",type:"number",description:"Step increment (default 1)",isOptional:!0}],dataOutputs:[{name:"index",type:"FlowGraphInteger",description:"Current loop index"}],config:{initialIndex:"number \u2014 initial index override",incrementIndexWhenLoopDone:"boolean \u2014 whether to increment the index when the loop is done"}},WhileLoop:{className:"FlowGraphWhileLoopBlock",category:"ControlFlow",description:"Executes the loop body while the condition is true.",signalInputs:[{name:"in"}],signalOutputs:[{name:"executionFlow",description:"Fires for each iteration"},{name:"completed",description:"Fires when the loop exits"},{name:"error"}],dataInputs:[{name:"condition",type:"boolean",description:"Loop condition \u2014 continues while true"}],dataOutputs:[],config:{doWhile:"boolean \u2014 if true, executes the body at least once before checking the condition"}},Sequence:{className:"FlowGraphSequenceBlock",category:"ControlFlow",description:"Executes multiple output signals in order (out_0, out_1, ...). Like a sequential pipeline.",signalInputs:[{name:"in"}],signalOutputs:[{name:"error"}],dataInputs:[],dataOutputs:[],config:{outputSignalCount:"number \u2014 how many sequential outputs to create (default 1). Creates out_0, out_1, ..."}},Switch:{className:"FlowGraphSwitchBlock",category:"ControlFlow",description:"Routes execution based on a case value. Like a switch/case statement with a default.",signalInputs:[{name:"in"}],signalOutputs:[{name:"default",description:"Fires when no case matches"},{name:"error"}],dataInputs:[{name:"case",type:"any",description:"The value to switch on"}],dataOutputs:[],config:{cases:"T[] \u2014 array of case values. Creates signal output 'out_{value}' for each case"}},MultiGate:{className:"FlowGraphMultiGateBlock",category:"ControlFlow",description:"Routes execution to one of N outputs each time it is triggered. Can be sequential, random, or looping.",signalInputs:[{name:"in"},{name:"reset",description:"Resets the gate index"}],signalOutputs:[{name:"error"}],dataInputs:[],dataOutputs:[{name:"lastIndex",type:"FlowGraphInteger",description:"Index of the last output fired"}],config:{outputSignalCount:"number \u2014 how many outputs to create (out_0, out_1, ...)",isRandom:"boolean \u2014 if true, picks outputs randomly",isLoop:"boolean \u2014 if true, loops back to the first output after the last"}},WaitAll:{className:"FlowGraphWaitAllBlock",category:"ControlFlow",description:"Waits for all N signal inputs to fire before triggering the output. Useful for synchronization.",signalInputs:[{name:"reset",description:"Resets all input states"}],signalOutputs:[{name:"out",description:"Fires when all inputs have triggered"},{name:"completed"},{name:"error"}],dataInputs:[],dataOutputs:[{name:"remainingInputs",type:"FlowGraphInteger",description:"How many inputs are still pending"}],config:{inputSignalCount:"number \u2014 how many signal inputs to create (in_0, in_1, ...)"}},SetDelay:{className:"FlowGraphSetDelayBlock",category:"ControlFlow",description:"Triggers the 'done' signal after a specified duration (in seconds). The 'out' signal fires immediately.",signalInputs:[{name:"in"},{name:"cancel",description:"Cancels the pending delay"}],signalOutputs:[{name:"out",description:"Fires immediately"},{name:"done",description:"Fires after the delay"},{name:"error"}],dataInputs:[{name:"duration",type:"number",description:"Delay duration in seconds"}],dataOutputs:[{name:"lastDelayIndex",type:"FlowGraphInteger",description:"Index of the last delay set"}]},CancelDelay:{className:"FlowGraphCancelDelayBlock",category:"ControlFlow",description:"Cancels a pending delay created by SetDelay.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"delayIndex",type:"FlowGraphInteger",description:"Index of the delay to cancel"}],dataOutputs:[],config:{ignoreInvalidDelay:"boolean \u2014 ignore invalid indices while still activating out (default: false)"}},CallCounter:{className:"FlowGraphCallCounterBlock",category:"ControlFlow",description:"Counts how many times it has been triggered. Can be reset.",signalInputs:[{name:"in"},{name:"reset",description:"Resets the counter to 0"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[],dataOutputs:[{name:"count",type:"number",description:"Current call count"}]},Debounce:{className:"FlowGraphDebounceBlock",category:"ControlFlow",description:"Only fires the output after the input has been triggered N times (debounce count). Then resets.",signalInputs:[{name:"in"},{name:"reset",description:"Resets the debounce counter"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"count",type:"number",description:"Number of triggers before firing"}],dataOutputs:[{name:"currentCount",type:"number",description:"Current trigger count"}]},Throttle:{className:"FlowGraphThrottleBlock",category:"ControlFlow",description:"Limits execution to at most once per duration period (in seconds).",signalInputs:[{name:"in"},{name:"reset",description:"Resets the throttle timer"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"duration",type:"number",description:"Minimum time between executions (seconds)"}],dataOutputs:[{name:"lastRemainingTime",type:"number",description:"Time remaining until next allowed execution"}],config:{allowZeroDuration:"boolean \u2014 accept a zero duration and always activate out (default: false)"}},DoN:{className:"FlowGraphDoNBlock",category:"ControlFlow",description:"Fires the output only the first N times it is triggered, then stops. Can be reset.",signalInputs:[{name:"in"},{name:"reset",description:"Resets the execution counter"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"maxExecutions",type:"FlowGraphInteger",description:"Maximum number of times to fire"}],dataOutputs:[{name:"executionCount",type:"FlowGraphInteger",description:"How many times it has fired"}],config:{startIndex:"FlowGraphInteger \u2014 initial count value"}},FlipFlop:{className:"FlowGraphFlipFlopBlock",category:"ControlFlow",description:"Alternates between onOn and onOff signals each time it is triggered. Like a toggle switch.",signalInputs:[{name:"in"}],signalOutputs:[{name:"onOn",description:"Fires on odd triggers"},{name:"onOff",description:"Fires on even triggers"},{name:"error"}],dataInputs:[],dataOutputs:[{name:"value",type:"boolean",description:"Current toggle state"}],config:{startValue:"boolean \u2014 initial toggle state (default false)"}},PlayAnimation:{className:"FlowGraphPlayAnimationBlock",category:"Animation",description:"Plays an animation or animation group. Provides current frame and event outputs.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out",description:"Fires immediately when play starts"},{name:"done",description:"Fires when the animation finishes"},{name:"error"},{name:"animationLoopEvent",description:"Fires each time the animation loops"},{name:"animationEndEvent",description:"Fires when the animation ends"},{name:"animationGroupLoopEvent",description:"Fires when an animation group loops"}],dataInputs:[{name:"speed",type:"number",description:"Playback speed (default 0)"},{name:"loop",type:"boolean",description:"Whether to loop (default false)"},{name:"from",type:"number",description:"Start frame (default 0)"},{name:"to",type:"number",description:"End frame (default 0 = full range)"},{name:"animationGroup",type:"any",description:"AnimationGroup to play"},{name:"animation",type:"any",description:"Animation or Animation[] to play",isOptional:!0},{name:"animationTargets",type:"any",description:"Optional target array matching animation order; replaces object when supplied",isOptional:!0},{name:"object",type:"any",description:"Target object for the animation",isOptional:!0}],dataOutputs:[{name:"currentFrame",type:"number",description:"Current animation frame"},{name:"currentTime",type:"number",description:"Current animation time"},{name:"currentAnimationGroup",type:"any",description:"The active animation group"}],config:{animationGroup:"AnimationGroup \u2014 default animation group"}},StopAnimation:{className:"FlowGraphStopAnimationBlock",category:"Animation",description:"Stops a playing animation group.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"done"},{name:"error"}],dataInputs:[{name:"animationGroup",type:"any",description:"The animation group to stop"},{name:"stopAtFrame",type:"number",description:"Frame to stop at (-1 = current)",isOptional:!0}],dataOutputs:[]},PauseAnimation:{className:"FlowGraphPauseAnimationBlock",category:"Animation",description:"Pauses a playing animation group.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"animationToPause",type:"any",description:"The animation group to pause"}],dataOutputs:[]},ValueInterpolation:{className:"FlowGraphInterpolationBlock",category:"Animation",description:"Creates an Animation object from keyframe values. Use with PlayAnimation to animate properties. Takes duration/value pairs for each keyframe.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"easingFunction",type:"any",description:"Optional easing function from Easing block",isOptional:!0},{name:"propertyName",type:"any",description:"Property name(s) to animate",isOptional:!0},{name:"customBuildAnimation",type:"any",description:"Custom animation builder function",isOptional:!0}],dataOutputs:[{name:"animation",type:"any",description:"The generated Animation object"}],config:{keyFramesCount:"number \u2014 number of keyframes (creates duration_N and value_N inputs for each)",duration:"number \u2014 default duration per keyframe",propertyName:"string|string[] \u2014 property path(s) to animate",animationType:"number|FlowGraphTypes \u2014 type of animated value (e.g. BABYLON.Animation.ANIMATIONTYPE_VECTOR3)"}},Easing:{className:"FlowGraphEasingBlock",category:"Animation",description:"Creates an easing function for use with ValueInterpolation. Supports all Babylon.js easing types.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"type",type:"any",description:"EasingFunctionType enum value (default 11 = BezierCurve)"},{name:"mode",type:"number",description:"Easing mode: 0=EaseIn, 1=EaseOut, 2=EaseInOut"},{name:"parameters",type:"any",description:"Easing parameters as number array (default [1,0,0,1])",isOptional:!0}],dataOutputs:[{name:"easingFunction",type:"any",description:"The easing function object"}]},BezierCurveEasing:{className:"FlowGraphBezierCurveEasing",category:"Animation",description:"Creates a bezier curve easing function with two control points.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"mode",type:"number",description:"Easing mode: 0=EaseIn, 1=EaseOut, 2=EaseInOut"},{name:"controlPoint1",type:"Vector2",description:"First control point"},{name:"controlPoint2",type:"Vector2",description:"Second control point"}],dataOutputs:[{name:"easingFunction",type:"any",description:"The bezier easing function object"}]},Constant:{className:"FlowGraphConstantBlock",category:"Data",description:"Outputs a constant value. The type is deduced from the config value. Supports numbers, strings, booleans, vectors, colors, etc.",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"output",type:"any",description:"The constant value"}],config:{value:"any \u2014 the constant value (e.g. 42, 'hello', { value: [1,2,3], className: 'Vector3' })"}},GetVariable:{className:"FlowGraphGetVariableBlock",category:"Data",description:"Reads a context variable set by SetVariable. Variables persist across executions of the graph.",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"any",description:"The variable's current value"}],config:{variable:"string \u2014 the variable name to read",initialValue:"any \u2014 default value if the variable hasn't been set"}},GetProperty:{className:"FlowGraphGetPropertyBlock",category:"Data",description:"Reads a property from a scene object (e.g. mesh.position, light.intensity).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"object",type:"any",description:"The target object"},{name:"propertyName",type:"any",description:"The property name to read",isOptional:!0},{name:"customGetFunction",type:"any",description:"Custom getter function",isOptional:!0}],dataOutputs:[{name:"value",type:"any",description:"The property value"},{name:"isValid",type:"boolean",description:"Whether the property was found"}],config:{propertyName:"string \u2014 property path to read",object:"any \u2014 default target object",resetToDefaultWhenUndefined:"boolean \u2014 reset to default when undefined",invalidValue:"any \u2014 optional value returned with isValid=false when property resolution fails"}},GetAsset:{className:"FlowGraphGetAssetBlock",category:"Data",description:"Retrieves an asset (mesh, material, texture, etc.) from the scene's asset context by type and index.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"type",type:"any",description:"FlowGraphAssetType \u2014 the kind of asset to retrieve"},{name:"index",type:"any",description:"Index of the asset in the collection",isOptional:!0}],dataOutputs:[{name:"value",type:"any",description:"The retrieved asset"}],config:{type:"FlowGraphAssetType \u2014 asset type enum",index:"number \u2014 asset index in the collection",useIndexAsUniqueId:"boolean \u2014 whether to use index as uniqueId lookup"}},Conditional:{className:"FlowGraphConditionalBlock",category:"Data",description:"Ternary operator \u2014 returns onTrue if condition is true, onFalse otherwise. Pure data block (no signals).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"condition",type:"boolean",description:"The condition to evaluate"},{name:"onTrue",type:"any",description:"Value returned when condition is true"},{name:"onFalse",type:"any",description:"Value returned when condition is false"}],dataOutputs:[{name:"output",type:"any",description:"The selected value"}]},TransformCoordinatesSystem:{className:"FlowGraphTransformCoordinatesSystemBlock",category:"Data",description:"Transforms coordinates from one coordinate system to another using two TransformNodes.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"sourceSystem",type:"any",description:"Source TransformNode"},{name:"destinationSystem",type:"any",description:"Destination TransformNode"},{name:"inputCoordinates",type:"Vector3",description:"Coordinates to transform"}],dataOutputs:[{name:"outputCoordinates",type:"Vector3",description:"Transformed coordinates"}]},JsonPointerParser:{className:"FlowGraphJsonPointerParserBlock",category:"Data",description:"Resolves a JSON pointer path to an object and property. Used internally for glTF interop.",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"},{name:"object",type:"any"},{name:"propertyName",type:"any"},{name:"setFunction",type:"any",description:"Setter function for the resolved property (used internally by interpolation/animation)"},{name:"getFunction",type:"any",description:"Getter function for the resolved property"},{name:"generateAnimationsFunction",type:"any",description:"Builds animation property info for the resolved property"},{name:"animationTargets",type:"any",description:"Targets in the same order as the generated animations"}],config:{jsonPointer:"string \u2014 the JSON pointer path",valueType:"string \u2014 require a writable accessor with this value type when setting a property"}},DataSwitch:{className:"FlowGraphDataSwitchBlock",category:"Data",description:"Selects a data value based on a case. Like a data-only switch/case.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"case",type:"any",description:"The case value to match"},{name:"default",type:"any",description:"Default value if no case matches"}],dataOutputs:[{name:"value",type:"any",description:"The selected value"}],config:{cases:"number[] \u2014 case values. Creates data input 'in_{value}' for each case",treatCasesAsIntegers:"boolean \u2014 whether to treat case values as integers"}},Context:{className:"FlowGraphContextBlock",category:"Utility",description:"Provides access to the flow graph execution context (user variables, execution ID).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"userVariables",type:"any",description:"All user variables as a dictionary"},{name:"executionId",type:"number",description:"Current execution ID"}]},IsKeyPressed:{className:"FlowGraphIsKeyPressedBlock",category:"Utility",description:"Outputs whether a keyboard key is currently held down, optionally requiring modifier keys.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"key",type:"string",description:"KeyboardEvent.code value to check, such as KeyA, Space, ShiftLeft, or ControlLeft"},{name:"withShift",type:"boolean",description:"Require Shift to also be held",isOptional:!0},{name:"withCtrl",type:"boolean",description:"Require Ctrl to also be held",isOptional:!0},{name:"withAlt",type:"boolean",description:"Require Alt/Option to also be held",isOptional:!0},{name:"withMeta",type:"boolean",description:"Require Meta/Cmd/Windows key to also be held",isOptional:!0},{name:"withCommandOrCtrl",type:"boolean",description:"Require Cmd on macOS or Ctrl on Windows/Linux",isOptional:!0}],dataOutputs:[{name:"isPressed",type:"boolean",description:"True when the requested key and modifiers are currently held"}]},ArrayIndex:{className:"FlowGraphArrayIndexBlock",category:"Utility",description:"Retrieves an element from an array by index.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"array",type:"any",description:"The source array"},{name:"index",type:"any",description:"The index to retrieve"}],dataOutputs:[{name:"value",type:"any",description:"The element at the specified index"}]},IndexOf:{className:"FlowGraphIndexOfBlock",category:"Utility",description:"Finds the index of an element in an array.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"object",type:"any",description:"The element to search for"},{name:"array",type:"any",description:"The array to search in"}],dataOutputs:[{name:"index",type:"FlowGraphInteger",description:"The index of the element (-1 if not found)"}]},CodeExecution:{className:"FlowGraphCodeExecutionBlock",category:"Utility",description:"Executes an arbitrary JavaScript function inside the flow graph \u2014 the 'escape hatch' for any logic not covered by dedicated blocks. This is a DATA block (no signal inputs/outputs); it evaluates lazily when its 'result' output is read by a downstream block. The function signature is: (value: any, context: FlowGraphContext) => any. The 'value' input can carry any data (a mesh, a number, an object with multiple fields, etc.), and 'context' is the FlowGraphContext giving access to the scene via context.assetsContext. Use the FunctionReference block to create the function from an object + method name, or provide the function via the scene's glue code / code generator. Common use cases: physics (applyImpulse, setLinearVelocity), mesh cloning (mesh.clone), reading/writing complex properties, invoking any Babylon.js API not exposed as a dedicated block.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"function",type:"any",description:"A CodeExecutionFunction: (value, context) => result. Can come from a FunctionReference block or be set in glue code. For physics impulse example: (v, ctx) => { v.mesh.physicsBody.applyImpulse(v.impulse, v.point); return true; }"},{name:"value",type:"any",description:"The input value passed as the first argument to the function. Can be any type \u2014 a mesh, a Vector3, or a composite object with multiple fields."}],dataOutputs:[{name:"result",type:"any",description:"The return value of the function"}]},FunctionReference:{className:"FlowGraphFunctionReference",category:"Utility",description:`Creates a callable function reference. Two modes of use:
90
90
  MODE A \u2014 Object method lookup: connect 'functionName' and 'object' data inputs. The block does object[functionName].bind(context) and outputs the bound function.
91
91
  MODE B \u2014 Inline code (config.code): put arbitrary JavaScript in config.code. The code generator will compile it into a real function and inject it at runtime. Leave 'functionName' and 'object' data inputs UNCONNECTED when using Mode B. The code has access to 'scene' (the Babylon.js scene) and 'BABYLON' (the namespace). The function signature is (value, fgContext) => result. Return a value if needed.
92
- Connect the 'output' to a CodeExecution block's 'function' input. This is a DATA block \u2014 it evaluates lazily when its output is read.`,signalInputs:[],signalOutputs:[],config:{code:"string \u2014 Optional. Arbitrary JavaScript code compiled into a function by the code generator. Has access to 'scene' (via closure) and any BABYLON API. Example: const ball = scene.getMeshByName('ball'); ball.physicsBody.applyImpulse(...); return 1;"},dataInputs:[{name:"functionName",type:"string",description:"Dot-separated path to the method on the object (e.g. 'physicsBody.applyImpulse', 'clone'). Leave unconnected when using config.code."},{name:"object",type:"any",description:"The object containing the function (e.g. a mesh from GetAsset). Leave unconnected when using config.code."},{name:"context",type:"any",description:"Optional 'this' context for the function call",isOptional:!0}],dataOutputs:[{name:"output",type:"any",description:"The bound function reference, ready to be called or connected to CodeExecution"}]},E:{className:"FlowGraphEBlock",category:"Math",description:"Outputs the mathematical constant e (\u2248 2.718).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},PI:{className:"FlowGraphPIBlock",category:"Math",description:"Outputs the mathematical constant \u03C0 (\u2248 3.14159).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},Tau:{className:"FlowGraphTauBlock",category:"Math",description:"Outputs tau (2\u03C0).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},Inf:{className:"FlowGraphInfBlock",category:"Math",description:"Outputs positive infinity.",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},NaN:{className:"FlowGraphNaNBlock",category:"Math",description:"Outputs NaN (Not a Number).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},Random:{className:"FlowGraphRandomBlock",category:"Math",description:"Outputs a random number between min and max.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"min",type:"number",description:"Minimum value (default 0)",isOptional:!0},{name:"max",type:"number",description:"Maximum value (default 1)",isOptional:!0}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}],config:{min:"number",max:"number",seed:"number \u2014 random seed for deterministic results"}},...fe("Abs","FlowGraphAbsBlock","Absolute value of the input."),...fe("Sign","FlowGraphSignBlock","Returns -1, 0, or 1 based on the sign of the input."),...fe("Trunc","FlowGraphTruncBlock","Truncates the input to an integer (removes decimal part)."),...fe("Floor","FlowGraphFloorBlock","Rounds the input down to the nearest integer."),...fe("Ceil","FlowGraphCeilBlock","Rounds the input up to the nearest integer."),...fe("Round","FlowGraphRoundBlock","Rounds the input to the nearest integer."),...fe("Fraction","FlowGraphFractBlock","Returns the fractional part of the input."),...fe("Negation","FlowGraphNegationBlock","Negates the input value."),...fe("Saturate","FlowGraphSaturateBlock","Clamps the input to the range [0, 1]."),...fe("IsNaN","FlowGraphIsNaNBlock","Returns true if the input is NaN.","boolean"),...fe("IsInfinity","FlowGraphIsInfBlock","Returns true if the input is infinite.","boolean"),...fe("DegToRad","FlowGraphDegToRadBlock","Converts degrees to radians."),...fe("RadToDeg","FlowGraphRadToDegBlock","Converts radians to degrees."),...fe("Sin","FlowGraphSinBlock","Sine of the input (in radians)."),...fe("Cos","FlowGraphCosBlock","Cosine of the input (in radians)."),...fe("Tan","FlowGraphTanBlock","Tangent of the input (in radians)."),...fe("Asin","FlowGraphASinBlock","Arcsine (inverse sine) of the input."),...fe("Acos","FlowGraphACosBlock","Arccosine (inverse cosine) of the input."),...fe("Atan","FlowGraphATanBlock","Arctangent (inverse tangent) of the input."),...fe("Sinh","FlowGraphSinhBlock","Hyperbolic sine."),...fe("Cosh","FlowGraphCoshBlock","Hyperbolic cosine."),...fe("Tanh","FlowGraphTanhBlock","Hyperbolic tangent."),...fe("Asinh","FlowGraphASinhBlock","Inverse hyperbolic sine."),...fe("Acosh","FlowGraphACoshBlock","Inverse hyperbolic cosine."),...fe("Atanh","FlowGraphATanhBlock","Inverse hyperbolic tangent."),...fe("Exponential","FlowGraphExponentialBlock","e raised to the power of the input (e^x)."),...fe("Log","FlowGraphLogBlock","Natural logarithm (base e)."),...fe("Log2","FlowGraphLog2Block","Base-2 logarithm."),...fe("Log10","FlowGraphLog10Block","Base-10 logarithm."),...fe("SquareRoot","FlowGraphSquareRootBlock","Square root of the input."),...fe("CubeRoot","FlowGraphCubeRootBlock","Cube root of the input."),...fe("BitwiseNot","FlowGraphBitwiseNotBlock","Bitwise NOT of the input.","FlowGraphInteger","FlowGraphInteger"),...fe("LeadingZeros","FlowGraphLeadingZerosBlock","Count of leading zero bits.","FlowGraphInteger","FlowGraphInteger"),...fe("TrailingZeros","FlowGraphTrailingZerosBlock","Count of trailing zero bits.","FlowGraphInteger","FlowGraphInteger"),...fe("OneBitsCounter","FlowGraphOneBitsCounterBlock","Count of set (1) bits.","FlowGraphInteger","FlowGraphInteger"),...Le("Add","FlowGraphAddBlock","Adds two values (a + b). Works with numbers, vectors, and matrices."),...Le("Subtract","FlowGraphSubtractBlock","Subtracts b from a (a - b)."),...Le("Multiply","FlowGraphMultiplyBlock","Multiplies two values (a * b)."),...Le("Divide","FlowGraphDivideBlock","Divides a by b (a / b)."),...Le("Modulo","FlowGraphModuloBlock","Remainder of a / b."),...Le("Min","FlowGraphMinBlock","Returns the smaller of a and b."),...Le("Max","FlowGraphMaxBlock","Returns the larger of a and b."),...Le("Power","FlowGraphPowerBlock","Raises a to the power of b (a^b)."),...Le("Atan2","FlowGraphATan2Block","Two-argument arctangent atan2(a, b)."),...Le("Equality","FlowGraphEqualityBlock","Returns true if a equals b.","boolean"),...Le("LessThan","FlowGraphLessThanBlock","Returns true if a < b.","boolean"),...Le("LessThanOrEqual","FlowGraphLessThanOrEqualBlock","Returns true if a <= b.","boolean"),...Le("GreaterThan","FlowGraphGreaterThanBlock","Returns true if a > b.","boolean"),...Le("GreaterThanOrEqual","FlowGraphGreaterThanOrEqualBlock","Returns true if a >= b.","boolean"),...Le("BitwiseAnd","FlowGraphBitwiseAndBlock","Bitwise AND.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),...Le("BitwiseOr","FlowGraphBitwiseOrBlock","Bitwise OR.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),...Le("BitwiseXor","FlowGraphBitwiseXorBlock","Bitwise XOR.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),...Le("BitwiseLeftShift","FlowGraphBitwiseLeftShiftBlock","Left bit shift.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),...Le("BitwiseRightShift","FlowGraphBitwiseRightShiftBlock","Right bit shift.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),Clamp:{className:"FlowGraphClampBlock",category:"Math",description:"Clamps value a between b (min) and c (max).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"Value to clamp"},{name:"b",type:"any",description:"Minimum"},{name:"c",type:"any",description:"Maximum"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},MathInterpolation:{className:"FlowGraphMathInterpolationBlock",category:"Math",description:"Linear interpolation: lerp(a, b, c) \u2014 returns a + (b - a) * c.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"Start value"},{name:"b",type:"any",description:"End value"},{name:"c",type:"any",description:"Interpolation factor (0-1)"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},SmoothStep:{className:"FlowGraphSmoothStepBlock",category:"Math",description:"Smooth Hermite interpolation coefficient: for edges a and b and value c, returns t*t*(3-2t) with t = saturate((c - min(a, b)) / |b - a|).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"Lower edge"},{name:"b",type:"any",description:"Upper edge"},{name:"c",type:"any",description:"Value to interpolate"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},...fe("Length","FlowGraphLengthBlock","Returns the length (magnitude) of a vector.","number"),...fe("Normalize","FlowGraphNormalizeBlock","Returns a normalized (unit-length) version of the vector."),...fe("Conjugate","FlowGraphConjugateBlock","Returns the conjugate of a quaternion.","Quaternion","Quaternion"),Dot:{className:"FlowGraphDotBlock",category:"Vector",description:"Computes the dot product of two vectors.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"First vector"},{name:"b",type:"any",description:"Second vector"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},Cross:{className:"FlowGraphCrossBlock",category:"Vector",description:"Computes the cross product of two Vector3 values.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3"},{name:"b",type:"Vector3"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},Rotate2D:{className:"FlowGraphRotate2DBlock",category:"Vector",description:"Rotates a 2D vector by an angle (in radians).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector2",description:"The vector to rotate"},{name:"b",type:"number",description:"Angle in radians"}],dataOutputs:[{name:"value",type:"Vector2"},{name:"isValid",type:"boolean"}]},Rotate3D:{className:"FlowGraphRotate3DBlock",category:"Vector",description:"Rotates a 3D vector by a quaternion rotation.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"The vector to rotate"},{name:"b",type:"Quaternion",description:"The rotation quaternion"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},TransformVector:{className:"FlowGraphTransformVectorBlock",category:"Vector",description:"Transforms a vector by a matrix.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"The vector to transform"},{name:"b",type:"any",description:"The transformation matrix"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},TransformCoordinates:{className:"FlowGraphTransformCoordinatesBlock",category:"Vector",description:"Transforms a Vector3 position by a Matrix (like Vector3.TransformCoordinates).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"The position to transform"},{name:"b",type:"Matrix",description:"The transformation matrix"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},AngleBetween:{className:"FlowGraphAngleBetweenBlock",category:"Vector",description:"Computes the angle between two quaternions.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Quaternion"},{name:"b",type:"Quaternion"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},QuaternionFromAxisAngle:{className:"FlowGraphQuaternionFromAxisAngleBlock",category:"Vector",description:"Creates a quaternion from an axis and angle.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"Rotation axis"},{name:"b",type:"number",description:"Rotation angle in radians"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}]},AxisAngleFromQuaternion:{className:"FlowGraphAxisAngleFromQuaternionBlock",category:"Vector",description:"Decomposes a quaternion into an axis and angle.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Quaternion"}],dataOutputs:[{name:"axis",type:"Vector3"},{name:"angle",type:"number"},{name:"isValid",type:"boolean"}]},QuaternionFromDirections:{className:"FlowGraphQuaternionFromDirectionsBlock",category:"Vector",description:"Creates a quaternion that rotates one direction to another.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"From direction"},{name:"b",type:"Vector3",description:"To direction"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}]},QuaternionFromUpForward:{className:"FlowGraphQuaternionFromUpForwardBlock",category:"Vector",description:"Creates a rotation quaternion from the specified up and forward directions.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"Up direction"},{name:"b",type:"Vector3",description:"Forward direction"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}]},QuaternionFromAngles:{className:"FlowGraphQuaternionFromAnglesBlock",category:"Vector",description:"Creates a rotation quaternion from three Tait\u2013Bryan intrinsic Euler angles (a=x, b=y, c=z, in radians) applied in the configured order.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"number",description:"Rotation around X, in radians"},{name:"b",type:"number",description:"Rotation around Y, in radians"},{name:"c",type:"number",description:"Rotation around Z, in radians"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}],config:{order:"string \u2014 intrinsic rotation order, one of xyz/xzy/yxz/yzx/zxy/zyx (default yxz)"}},VectorSlerp:{className:"FlowGraphVectorSlerpBlock",category:"Vector",description:"Spherical linear interpolation between two vectors (float2/float3). c is the interpolation coefficient.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"First vector"},{name:"b",type:"any",description:"Second vector"},{name:"c",type:"number",description:"Interpolation coefficient"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},MathSlerp:{className:"FlowGraphMathSlerpBlock",category:"Vector",description:"Spherical linear interpolation between two quaternions. c is the interpolation coefficient.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Quaternion",description:"First quaternion"},{name:"b",type:"Quaternion",description:"Second quaternion"},{name:"c",type:"number",description:"Interpolation coefficient"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}]},RGBToOkLCh:{className:"FlowGraphRGBToOkLChBlock",category:"Conversion",description:"Converts linear sRGB components to OkLCh components.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"r",type:"number"},{name:"g",type:"number"},{name:"b",type:"number"}],dataOutputs:[{name:"l",type:"number"},{name:"c",type:"number"},{name:"h",type:"number"}]},RGBFromOkLCh:{className:"FlowGraphRGBFromOkLChBlock",category:"Conversion",description:"Converts OkLCh components to linear sRGB components.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"l",type:"number"},{name:"c",type:"number"},{name:"h",type:"number"}],dataOutputs:[{name:"r",type:"number"},{name:"g",type:"number"},{name:"b",type:"number"}]},...fe("Transpose","FlowGraphTransposeBlock","Transposes a matrix.","Matrix","Matrix"),...fe("Determinant","FlowGraphDeterminantBlock","Computes the determinant of a matrix.","number","Matrix"),...fe("InvertMatrix","FlowGraphInvertMatrixBlock","Inverts a matrix.","Matrix","Matrix"),MatrixMultiplication:{className:"FlowGraphMatrixMultiplicationBlock",category:"Matrix",description:"Multiplies two matrices together.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Matrix"},{name:"b",type:"Matrix"}],dataOutputs:[{name:"value",type:"Matrix"},{name:"isValid",type:"boolean"}]},MatrixDecompose:{className:"FlowGraphMatrixDecompose",category:"Matrix",description:"Decomposes a matrix into position, rotation (quaternion), and scale.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Matrix"}],dataOutputs:[{name:"position",type:"Vector3"},{name:"rotationQuaternion",type:"Quaternion"},{name:"scaling",type:"Vector3"},{name:"isValid",type:"boolean"}]},MatrixCompose:{className:"FlowGraphMatrixCompose",category:"Matrix",description:"Composes a matrix from position, rotation (quaternion), and scale.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"position",type:"Vector3"},{name:"rotationQuaternion",type:"Quaternion"},{name:"scaling",type:"Vector3"}],dataOutputs:[{name:"value",type:"Matrix"}]},CombineVector2:{className:"FlowGraphCombineVector2Block",category:"Combine",description:"Combines two numbers into a Vector2.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input_0",type:"number",description:"X component"},{name:"input_1",type:"number",description:"Y component"}],dataOutputs:[{name:"value",type:"Vector2"},{name:"isValid",type:"boolean"}]},CombineVector3:{className:"FlowGraphCombineVector3Block",category:"Combine",description:"Combines three numbers into a Vector3.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input_0",type:"number",description:"X component"},{name:"input_1",type:"number",description:"Y component"},{name:"input_2",type:"number",description:"Z component"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},CombineVector4:{className:"FlowGraphCombineVector4Block",category:"Combine",description:"Combines four numbers into a Vector4.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input_0",type:"number",description:"X component"},{name:"input_1",type:"number",description:"Y component"},{name:"input_2",type:"number",description:"Z component"},{name:"input_3",type:"number",description:"W component"}],dataOutputs:[{name:"value",type:"Vector4"},{name:"isValid",type:"boolean"}]},CombineMatrix:{className:"FlowGraphCombineMatrixBlock",category:"Combine",description:"Combines 16 numbers into a 4x4 Matrix.",signalInputs:[],signalOutputs:[],dataInputs:Array.from({length:16},(e,t)=>({name:`input_${t}`,type:"number",description:`Matrix element [${Math.floor(t/4)}][${t%4}]`})),dataOutputs:[{name:"value",type:"Matrix"},{name:"isValid",type:"boolean"}]},CombineMatrix2D:{className:"FlowGraphCombineMatrix2DBlock",category:"Combine",description:"Combines 4 float values into a 2x2 Matrix2D.",signalInputs:[],signalOutputs:[],dataInputs:Array.from({length:4},(e,t)=>({name:`input_${t}`,type:"number",description:`Matrix element ${t}`})),dataOutputs:[{name:"value",type:"Matrix2D"},{name:"isValid",type:"boolean"}]},CombineMatrix3D:{className:"FlowGraphCombineMatrix3DBlock",category:"Combine",description:"Combines 9 float values into a 3x3 Matrix3D.",signalInputs:[],signalOutputs:[],dataInputs:Array.from({length:9},(e,t)=>({name:`input_${t}`,type:"number",description:`Matrix element [${Math.floor(t/3)}][${t%3}]`})),dataOutputs:[{name:"value",type:"Matrix3D"},{name:"isValid",type:"boolean"}]},ExtractVector2:{className:"FlowGraphExtractVector2Block",category:"Extract",description:"Extracts the X and Y components from a Vector2.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Vector2"}],dataOutputs:[{name:"output_0",type:"number",description:"X"},{name:"output_1",type:"number",description:"Y"}]},ExtractVector3:{className:"FlowGraphExtractVector3Block",category:"Extract",description:"Extracts the X, Y, and Z components from a Vector3.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Vector3"}],dataOutputs:[{name:"output_0",type:"number",description:"X"},{name:"output_1",type:"number",description:"Y"},{name:"output_2",type:"number",description:"Z"}]},ExtractVector4:{className:"FlowGraphExtractVector4Block",category:"Extract",description:"Extracts the X, Y, Z, and W components from a Vector4.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Vector4"}],dataOutputs:[{name:"output_0",type:"number",description:"X"},{name:"output_1",type:"number",description:"Y"},{name:"output_2",type:"number",description:"Z"},{name:"output_3",type:"number",description:"W"}]},ExtractMatrix:{className:"FlowGraphExtractMatrixBlock",category:"Extract",description:"Extracts all 16 elements from a 4x4 Matrix.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Matrix"}],dataOutputs:Array.from({length:16},(e,t)=>({name:`output_${t}`,type:"number",description:`Matrix element [${Math.floor(t/4)}][${t%4}]`}))},ExtractMatrix2D:{className:"FlowGraphExtractMatrix2DBlock",category:"Extract",description:"Extracts all 4 elements from a 2x2 Matrix2D.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Matrix2D"}],dataOutputs:Array.from({length:4},(e,t)=>({name:`output_${t}`,type:"number",description:`Matrix element ${t}`}))},ExtractMatrix3D:{className:"FlowGraphExtractMatrix3DBlock",category:"Extract",description:"Extracts all 9 elements from a 3x3 Matrix3D.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Matrix3D"}],dataOutputs:Array.from({length:9},(e,t)=>({name:`output_${t}`,type:"number",description:`Matrix element [${Math.floor(t/3)}][${t%3}]`}))},BooleanToFloat:{className:"FlowGraphBooleanToFloat",category:"Conversion",description:"Converts a boolean to a float (true \u2192 1.0, false \u2192 0.0).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"boolean"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},BooleanToInt:{className:"FlowGraphBooleanToInt",category:"Conversion",description:"Converts a boolean to an integer (true \u2192 1, false \u2192 0).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"boolean"}],dataOutputs:[{name:"value",type:"FlowGraphInteger"},{name:"isValid",type:"boolean"}]},FloatToBoolean:{className:"FlowGraphFloatToBoolean",category:"Conversion",description:"Converts a float to a boolean (0 \u2192 false, nonzero \u2192 true).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"number"}],dataOutputs:[{name:"value",type:"boolean"},{name:"isValid",type:"boolean"}]},IntToBoolean:{className:"FlowGraphIntToBoolean",category:"Conversion",description:"Converts an integer to a boolean (0 \u2192 false, nonzero \u2192 true).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"FlowGraphInteger"}],dataOutputs:[{name:"value",type:"boolean"},{name:"isValid",type:"boolean"}]},IntToFloat:{className:"FlowGraphIntToFloat",category:"Conversion",description:"Converts an integer to a float.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"FlowGraphInteger"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},FloatToInt:{className:"FlowGraphFloatToInt",category:"Conversion",description:"Converts a float to an integer.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"number"}],dataOutputs:[{name:"value",type:"FlowGraphInteger"},{name:"isValid",type:"boolean"}],config:{roundingMode:'"floor" | "ceil" | "round" \u2014 how to round the float value'}},PhysicsApplyForce:{className:"FlowGraphApplyForceBlock",category:"Execution",description:"Applies a force to a physics body at a given location.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody to apply force to"},{name:"force",type:"Vector3",description:"Force vector"},{name:"location",type:"Vector3",description:"World-space location to apply force at"}],dataOutputs:[]},PhysicsApplyImpulse:{className:"FlowGraphApplyImpulseBlock",category:"Execution",description:"Applies an impulse to a physics body at a given location.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody to apply impulse to"},{name:"impulse",type:"Vector3",description:"Impulse vector"},{name:"location",type:"Vector3",description:"World-space location to apply impulse at"}],dataOutputs:[]},PhysicsSetLinearVelocity:{className:"FlowGraphSetLinearVelocityBlock",category:"Execution",description:"Sets the linear velocity of a physics body.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"},{name:"velocity",type:"Vector3",description:"New linear velocity"}],dataOutputs:[]},PhysicsSetAngularVelocity:{className:"FlowGraphSetAngularVelocityBlock",category:"Execution",description:"Sets the angular velocity of a physics body.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"},{name:"velocity",type:"Vector3",description:"New angular velocity"}],dataOutputs:[]},PhysicsSetMotionType:{className:"FlowGraphSetPhysicsMotionTypeBlock",category:"Execution",description:"Sets the motion type of a physics body (Static=0, Animated=1, Dynamic=2).",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"},{name:"motionType",type:"number",description:"Motion type: Static (0), Animated (1), Dynamic (2)"}],dataOutputs:[]},PhysicsGetLinearVelocity:{className:"FlowGraphGetLinearVelocityBlock",category:"Data",description:"Gets the linear velocity of a physics body.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},PhysicsGetAngularVelocity:{className:"FlowGraphGetAngularVelocityBlock",category:"Data",description:"Gets the angular velocity of a physics body.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},PhysicsGetMassProperties:{className:"FlowGraphGetPhysicsMassPropertiesBlock",category:"Data",description:"Gets mass, center of mass, and inertia of a physics body.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"}],dataOutputs:[{name:"mass",type:"number"},{name:"centerOfMass",type:"Vector3"},{name:"inertia",type:"Vector3"}]},AudioPlaySound:{className:"FlowGraphPlaySoundBlock",category:"Execution",description:"Plays a sound with optional volume, offset, and loop control.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound to play"},{name:"volume",type:"number",description:"Playback volume (default: 1)"},{name:"startOffset",type:"number",description:"Start offset in seconds (default: 0)"},{name:"loop",type:"boolean",description:"Whether to loop (default: false)"}],dataOutputs:[]},AudioStopSound:{className:"FlowGraphStopSoundBlock",category:"Execution",description:"Stops a currently playing sound.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound to stop"}],dataOutputs:[]},AudioPauseSound:{className:"FlowGraphPauseSoundBlock",category:"Execution",description:"Pauses a currently playing sound.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound to pause"}],dataOutputs:[]},AudioSetVolume:{className:"FlowGraphSetSoundVolumeBlock",category:"Execution",description:"Sets the volume of a sound.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound"},{name:"volume",type:"number",description:"Volume level (default: 1)"}],dataOutputs:[]},AudioGetVolume:{className:"FlowGraphGetSoundVolumeBlock",category:"Data",description:"Gets the current volume of a sound.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"sound",type:"any",description:"The sound"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},AudioIsSoundPlaying:{className:"FlowGraphIsSoundPlayingBlock",category:"Data",description:"Returns whether a sound is currently playing.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"sound",type:"any",description:"The sound"}],dataOutputs:[{name:"value",type:"boolean"},{name:"isValid",type:"boolean"}]},DebugBlock:{className:"FlowGraphDebugBlock",category:"Utility",description:"Pass-through block that logs its input value for debugging. Output equals input.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"any"}],dataOutputs:[{name:"output",type:"any"}]}};function fe(e,t,r,o="any",n="any"){return{[e]:{className:t,category:"Math",description:r,signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:n,description:"Input value"}],dataOutputs:[{name:"value",type:o},{name:"isValid",type:"boolean"}]}}}function Le(e,t,r,o="any",n="any",i="any"){return{[e]:{className:t,category:"Math",description:r,signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:n,description:"First operand"},{name:"b",type:i,description:"Second operand"}],dataOutputs:[{name:"value",type:o},{name:"isValid",type:"boolean"}]}}}function y_(){const e=new Map;for(const[r,o]of Object.entries(Xt))e.has(o.category)||e.set(o.category,[]),e.get(o.category).push(` ${r} (${o.className}): ${o.description.split(".")[0]}`);const t=[];for(const[r,o]of e)t.push(`
92
+ Connect the 'output' to a CodeExecution block's 'function' input. This is a DATA block \u2014 it evaluates lazily when its output is read.`,signalInputs:[],signalOutputs:[],config:{code:"string \u2014 Optional. Arbitrary JavaScript code compiled into a function by the code generator. Has access to 'scene' (via closure) and any BABYLON API. Example: const ball = scene.getMeshByName('ball'); ball.physicsBody.applyImpulse(...); return 1;"},dataInputs:[{name:"functionName",type:"string",description:"Dot-separated path to the method on the object (e.g. 'physicsBody.applyImpulse', 'clone'). Leave unconnected when using config.code."},{name:"object",type:"any",description:"The object containing the function (e.g. a mesh from GetAsset). Leave unconnected when using config.code."},{name:"context",type:"any",description:"Optional 'this' context for the function call",isOptional:!0}],dataOutputs:[{name:"output",type:"any",description:"The bound function reference, ready to be called or connected to CodeExecution"}]},E:{className:"FlowGraphEBlock",category:"Math",description:"Outputs the mathematical constant e (\u2248 2.718).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},PI:{className:"FlowGraphPIBlock",category:"Math",description:"Outputs the mathematical constant \u03C0 (\u2248 3.14159).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},Tau:{className:"FlowGraphTauBlock",category:"Math",description:"Outputs tau (2\u03C0).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},Inf:{className:"FlowGraphInfBlock",category:"Math",description:"Outputs positive infinity.",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},NaN:{className:"FlowGraphNaNBlock",category:"Math",description:"Outputs NaN (Not a Number).",signalInputs:[],signalOutputs:[],dataInputs:[],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},Random:{className:"FlowGraphRandomBlock",category:"Math",description:"Outputs a random number between min and max.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"min",type:"number",description:"Minimum value (default 0)",isOptional:!0},{name:"max",type:"number",description:"Maximum value (default 1)",isOptional:!0}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}],config:{min:"number",max:"number",seed:"number \u2014 random seed for deterministic results"}},...fe("Abs","FlowGraphAbsBlock","Absolute value of the input."),...fe("Sign","FlowGraphSignBlock","Returns -1, 0, or 1 based on the sign of the input."),...fe("Trunc","FlowGraphTruncBlock","Truncates the input to an integer (removes decimal part)."),...fe("Floor","FlowGraphFloorBlock","Rounds the input down to the nearest integer."),...fe("Ceil","FlowGraphCeilBlock","Rounds the input up to the nearest integer."),...fe("Round","FlowGraphRoundBlock","Rounds the input to the nearest integer."),...fe("Fraction","FlowGraphFractBlock","Returns the fractional part of the input."),...fe("Negation","FlowGraphNegationBlock","Negates the input value."),...fe("Saturate","FlowGraphSaturateBlock","Clamps the input to the range [0, 1]."),...fe("IsNaN","FlowGraphIsNaNBlock","Returns true if the input is NaN.","boolean"),...fe("IsInfinity","FlowGraphIsInfBlock","Returns true if the input is infinite.","boolean"),...fe("DegToRad","FlowGraphDegToRadBlock","Converts degrees to radians."),...fe("RadToDeg","FlowGraphRadToDegBlock","Converts radians to degrees."),...fe("Sin","FlowGraphSinBlock","Sine of the input (in radians)."),...fe("Cos","FlowGraphCosBlock","Cosine of the input (in radians)."),...fe("Tan","FlowGraphTanBlock","Tangent of the input (in radians)."),...fe("Asin","FlowGraphASinBlock","Arcsine (inverse sine) of the input."),...fe("Acos","FlowGraphACosBlock","Arccosine (inverse cosine) of the input."),...fe("Atan","FlowGraphATanBlock","Arctangent (inverse tangent) of the input."),...fe("Sinh","FlowGraphSinhBlock","Hyperbolic sine."),...fe("Cosh","FlowGraphCoshBlock","Hyperbolic cosine."),...fe("Tanh","FlowGraphTanhBlock","Hyperbolic tangent."),...fe("Asinh","FlowGraphASinhBlock","Inverse hyperbolic sine."),...fe("Acosh","FlowGraphACoshBlock","Inverse hyperbolic cosine."),...fe("Atanh","FlowGraphATanhBlock","Inverse hyperbolic tangent."),...fe("Exponential","FlowGraphExponentialBlock","e raised to the power of the input (e^x)."),...fe("Log","FlowGraphLogBlock","Natural logarithm (base e)."),...fe("Log2","FlowGraphLog2Block","Base-2 logarithm."),...fe("Log10","FlowGraphLog10Block","Base-10 logarithm."),...fe("SquareRoot","FlowGraphSquareRootBlock","Square root of the input."),...fe("CubeRoot","FlowGraphCubeRootBlock","Cube root of the input."),...fe("BitwiseNot","FlowGraphBitwiseNotBlock","Bitwise NOT of the input.","FlowGraphInteger","FlowGraphInteger"),...fe("LeadingZeros","FlowGraphLeadingZerosBlock","Count of leading zero bits.","FlowGraphInteger","FlowGraphInteger"),...fe("TrailingZeros","FlowGraphTrailingZerosBlock","Count of trailing zero bits.","FlowGraphInteger","FlowGraphInteger"),...fe("OneBitsCounter","FlowGraphOneBitsCounterBlock","Count of set (1) bits.","FlowGraphInteger","FlowGraphInteger"),...Le("Add","FlowGraphAddBlock","Adds two values (a + b). Works with numbers, vectors, and matrices."),...Le("Subtract","FlowGraphSubtractBlock","Subtracts b from a (a - b)."),...Le("Multiply","FlowGraphMultiplyBlock","Multiplies two values (a * b)."),...Le("Divide","FlowGraphDivideBlock","Divides a by b (a / b)."),...Le("Modulo","FlowGraphModuloBlock","Remainder of a / b."),...Le("Min","FlowGraphMinBlock","Returns the smaller of a and b."),...Le("Max","FlowGraphMaxBlock","Returns the larger of a and b."),...Le("Power","FlowGraphPowerBlock","Raises a to the power of b (a^b)."),...Le("Atan2","FlowGraphATan2Block","Two-argument arctangent atan2(a, b)."),...Le("Equality","FlowGraphEqualityBlock","Returns true if a equals b.","boolean"),...Le("LessThan","FlowGraphLessThanBlock","Returns true if a < b.","boolean"),...Le("LessThanOrEqual","FlowGraphLessThanOrEqualBlock","Returns true if a <= b.","boolean"),...Le("GreaterThan","FlowGraphGreaterThanBlock","Returns true if a > b.","boolean"),...Le("GreaterThanOrEqual","FlowGraphGreaterThanOrEqualBlock","Returns true if a >= b.","boolean"),...Le("BitwiseAnd","FlowGraphBitwiseAndBlock","Bitwise AND.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),...Le("BitwiseOr","FlowGraphBitwiseOrBlock","Bitwise OR.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),...Le("BitwiseXor","FlowGraphBitwiseXorBlock","Bitwise XOR.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),...Le("BitwiseLeftShift","FlowGraphBitwiseLeftShiftBlock","Left bit shift.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),...Le("BitwiseRightShift","FlowGraphBitwiseRightShiftBlock","Right bit shift.","FlowGraphInteger","FlowGraphInteger","FlowGraphInteger"),Clamp:{className:"FlowGraphClampBlock",category:"Math",description:"Clamps value a between b (min) and c (max).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"Value to clamp"},{name:"b",type:"any",description:"Minimum"},{name:"c",type:"any",description:"Maximum"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},MathInterpolation:{className:"FlowGraphMathInterpolationBlock",category:"Math",description:"Linear interpolation: lerp(a, b, c) \u2014 returns a + (b - a) * c.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"Start value"},{name:"b",type:"any",description:"End value"},{name:"c",type:"any",description:"Interpolation factor (0-1)"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},SmoothStep:{className:"FlowGraphSmoothStepBlock",category:"Math",description:"Smooth Hermite interpolation coefficient: for edges a and b and value c, returns t*t*(3-2t) with t = saturate((c - min(a, b)) / |b - a|).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"Lower edge"},{name:"b",type:"any",description:"Upper edge"},{name:"c",type:"any",description:"Value to interpolate"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},...fe("Length","FlowGraphLengthBlock","Returns the length (magnitude) of a vector.","number"),...fe("Normalize","FlowGraphNormalizeBlock","Returns a normalized (unit-length) version of the vector."),...fe("Conjugate","FlowGraphConjugateBlock","Returns the conjugate of a quaternion.","Quaternion","Quaternion"),Dot:{className:"FlowGraphDotBlock",category:"Vector",description:"Computes the dot product of two vectors.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"First vector"},{name:"b",type:"any",description:"Second vector"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},Cross:{className:"FlowGraphCrossBlock",category:"Vector",description:"Computes the cross product of two Vector3 values.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3"},{name:"b",type:"Vector3"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},Rotate2D:{className:"FlowGraphRotate2DBlock",category:"Vector",description:"Rotates a 2D vector by an angle (in radians).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector2",description:"The vector to rotate"},{name:"b",type:"number",description:"Angle in radians"}],dataOutputs:[{name:"value",type:"Vector2"},{name:"isValid",type:"boolean"}]},Rotate3D:{className:"FlowGraphRotate3DBlock",category:"Vector",description:"Rotates a 3D vector by a quaternion rotation.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"The vector to rotate"},{name:"b",type:"Quaternion",description:"The rotation quaternion"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},TransformVector:{className:"FlowGraphTransformVectorBlock",category:"Vector",description:"Transforms a vector by a matrix.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"The vector to transform"},{name:"b",type:"any",description:"The transformation matrix"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},TransformCoordinates:{className:"FlowGraphTransformCoordinatesBlock",category:"Vector",description:"Transforms a Vector3 position by a Matrix (like Vector3.TransformCoordinates).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"The position to transform"},{name:"b",type:"Matrix",description:"The transformation matrix"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},AngleBetween:{className:"FlowGraphAngleBetweenBlock",category:"Vector",description:"Computes the angle between two quaternions.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Quaternion"},{name:"b",type:"Quaternion"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},QuaternionFromAxisAngle:{className:"FlowGraphQuaternionFromAxisAngleBlock",category:"Vector",description:"Creates a quaternion from an axis and angle.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"Rotation axis"},{name:"b",type:"number",description:"Rotation angle in radians"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}]},AxisAngleFromQuaternion:{className:"FlowGraphAxisAngleFromQuaternionBlock",category:"Vector",description:"Decomposes a quaternion into an axis and angle.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Quaternion"}],dataOutputs:[{name:"axis",type:"Vector3"},{name:"angle",type:"number"},{name:"isValid",type:"boolean"}]},QuaternionFromDirections:{className:"FlowGraphQuaternionFromDirectionsBlock",category:"Vector",description:"Creates a quaternion that rotates one direction to another.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"From direction"},{name:"b",type:"Vector3",description:"To direction"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}]},QuaternionFromUpForward:{className:"FlowGraphQuaternionFromUpForwardBlock",category:"Vector",description:"Creates a rotation quaternion from the specified up and forward directions.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Vector3",description:"Up direction"},{name:"b",type:"Vector3",description:"Forward direction"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}]},QuaternionFromAngles:{className:"FlowGraphQuaternionFromAnglesBlock",category:"Vector",description:"Creates a rotation quaternion from three Tait\u2013Bryan intrinsic Euler angles (a=x, b=y, c=z, in radians) applied in the configured order.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"number",description:"Rotation around X, in radians"},{name:"b",type:"number",description:"Rotation around Y, in radians"},{name:"c",type:"number",description:"Rotation around Z, in radians"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}],config:{order:"string \u2014 intrinsic rotation order, one of xyz/xzy/yxz/yzx/zxy/zyx (default yxz)"}},VectorSlerp:{className:"FlowGraphVectorSlerpBlock",category:"Vector",description:"Spherical linear interpolation between two vectors (float2/float3). c is the interpolation coefficient.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"any",description:"First vector"},{name:"b",type:"any",description:"Second vector"},{name:"c",type:"number",description:"Interpolation coefficient"}],dataOutputs:[{name:"value",type:"any"},{name:"isValid",type:"boolean"}]},MathSlerp:{className:"FlowGraphMathSlerpBlock",category:"Vector",description:"Spherical linear interpolation between two quaternions. c is the interpolation coefficient.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Quaternion",description:"First quaternion"},{name:"b",type:"Quaternion",description:"Second quaternion"},{name:"c",type:"number",description:"Interpolation coefficient"}],dataOutputs:[{name:"value",type:"Quaternion"},{name:"isValid",type:"boolean"}]},RGBToOkLCh:{className:"FlowGraphRGBToOkLChBlock",category:"Conversion",description:"Converts linear sRGB components to OkLCh components.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"r",type:"number"},{name:"g",type:"number"},{name:"b",type:"number"}],dataOutputs:[{name:"l",type:"number"},{name:"c",type:"number"},{name:"h",type:"number"}]},RGBFromOkLCh:{className:"FlowGraphRGBFromOkLChBlock",category:"Conversion",description:"Converts OkLCh components to linear sRGB components.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"l",type:"number"},{name:"c",type:"number"},{name:"h",type:"number"}],dataOutputs:[{name:"r",type:"number"},{name:"g",type:"number"},{name:"b",type:"number"}]},...fe("Transpose","FlowGraphTransposeBlock","Transposes a matrix.","Matrix","Matrix"),...fe("Determinant","FlowGraphDeterminantBlock","Computes the determinant of a matrix.","number","Matrix"),...fe("InvertMatrix","FlowGraphInvertMatrixBlock","Inverts a matrix.","Matrix","Matrix"),MatrixMultiplication:{className:"FlowGraphMatrixMultiplicationBlock",category:"Matrix",description:"Multiplies two matrices together.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"Matrix"},{name:"b",type:"Matrix"}],dataOutputs:[{name:"value",type:"Matrix"},{name:"isValid",type:"boolean"}]},MatrixDecompose:{className:"FlowGraphMatrixDecompose",category:"Matrix",description:"Decomposes a matrix into position, rotation (quaternion), and scale.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Matrix"}],dataOutputs:[{name:"position",type:"Vector3"},{name:"rotationQuaternion",type:"Quaternion"},{name:"scaling",type:"Vector3"},{name:"isValid",type:"boolean"}]},MatrixCompose:{className:"FlowGraphMatrixCompose",category:"Matrix",description:"Composes a matrix from position, rotation (quaternion), and scale.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"position",type:"Vector3"},{name:"rotationQuaternion",type:"Quaternion"},{name:"scaling",type:"Vector3"}],dataOutputs:[{name:"value",type:"Matrix"}]},CombineVector2:{className:"FlowGraphCombineVector2Block",category:"Combine",description:"Combines two numbers into a Vector2.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input_0",type:"number",description:"X component"},{name:"input_1",type:"number",description:"Y component"}],dataOutputs:[{name:"value",type:"Vector2"},{name:"isValid",type:"boolean"}]},CombineVector3:{className:"FlowGraphCombineVector3Block",category:"Combine",description:"Combines three numbers into a Vector3.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input_0",type:"number",description:"X component"},{name:"input_1",type:"number",description:"Y component"},{name:"input_2",type:"number",description:"Z component"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},CombineVector4:{className:"FlowGraphCombineVector4Block",category:"Combine",description:"Combines four numbers into a Vector4.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input_0",type:"number",description:"X component"},{name:"input_1",type:"number",description:"Y component"},{name:"input_2",type:"number",description:"Z component"},{name:"input_3",type:"number",description:"W component"}],dataOutputs:[{name:"value",type:"Vector4"},{name:"isValid",type:"boolean"}]},CombineMatrix:{className:"FlowGraphCombineMatrixBlock",category:"Combine",description:"Combines 16 numbers into a 4x4 Matrix.",signalInputs:[],signalOutputs:[],dataInputs:Array.from({length:16},(e,t)=>({name:`input_${t}`,type:"number",description:`Matrix element [${Math.floor(t/4)}][${t%4}]`})),dataOutputs:[{name:"value",type:"Matrix"},{name:"isValid",type:"boolean"}]},CombineMatrix2D:{className:"FlowGraphCombineMatrix2DBlock",category:"Combine",description:"Combines 4 float values into a 2x2 Matrix2D.",signalInputs:[],signalOutputs:[],dataInputs:Array.from({length:4},(e,t)=>({name:`input_${t}`,type:"number",description:`Matrix element ${t}`})),dataOutputs:[{name:"value",type:"Matrix2D"},{name:"isValid",type:"boolean"}]},CombineMatrix3D:{className:"FlowGraphCombineMatrix3DBlock",category:"Combine",description:"Combines 9 float values into a 3x3 Matrix3D.",signalInputs:[],signalOutputs:[],dataInputs:Array.from({length:9},(e,t)=>({name:`input_${t}`,type:"number",description:`Matrix element [${Math.floor(t/3)}][${t%3}]`})),dataOutputs:[{name:"value",type:"Matrix3D"},{name:"isValid",type:"boolean"}]},ExtractVector2:{className:"FlowGraphExtractVector2Block",category:"Extract",description:"Extracts the X and Y components from a Vector2.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Vector2"}],dataOutputs:[{name:"output_0",type:"number",description:"X"},{name:"output_1",type:"number",description:"Y"}]},ExtractVector3:{className:"FlowGraphExtractVector3Block",category:"Extract",description:"Extracts the X, Y, and Z components from a Vector3.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Vector3"}],dataOutputs:[{name:"output_0",type:"number",description:"X"},{name:"output_1",type:"number",description:"Y"},{name:"output_2",type:"number",description:"Z"}]},ExtractVector4:{className:"FlowGraphExtractVector4Block",category:"Extract",description:"Extracts the X, Y, Z, and W components from a Vector4.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Vector4"}],dataOutputs:[{name:"output_0",type:"number",description:"X"},{name:"output_1",type:"number",description:"Y"},{name:"output_2",type:"number",description:"Z"},{name:"output_3",type:"number",description:"W"}]},ExtractMatrix:{className:"FlowGraphExtractMatrixBlock",category:"Extract",description:"Extracts all 16 elements from a 4x4 Matrix.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Matrix"}],dataOutputs:Array.from({length:16},(e,t)=>({name:`output_${t}`,type:"number",description:`Matrix element [${Math.floor(t/4)}][${t%4}]`}))},ExtractMatrix2D:{className:"FlowGraphExtractMatrix2DBlock",category:"Extract",description:"Extracts all 4 elements from a 2x2 Matrix2D.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Matrix2D"}],dataOutputs:Array.from({length:4},(e,t)=>({name:`output_${t}`,type:"number",description:`Matrix element ${t}`}))},ExtractMatrix3D:{className:"FlowGraphExtractMatrix3DBlock",category:"Extract",description:"Extracts all 9 elements from a 3x3 Matrix3D.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"Matrix3D"}],dataOutputs:Array.from({length:9},(e,t)=>({name:`output_${t}`,type:"number",description:`Matrix element [${Math.floor(t/3)}][${t%3}]`}))},BooleanToFloat:{className:"FlowGraphBooleanToFloat",category:"Conversion",description:"Converts a boolean to a float (true \u2192 1.0, false \u2192 0.0).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"boolean"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},BooleanToInt:{className:"FlowGraphBooleanToInt",category:"Conversion",description:"Converts a boolean to an integer (true \u2192 1, false \u2192 0).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"boolean"}],dataOutputs:[{name:"value",type:"FlowGraphInteger"},{name:"isValid",type:"boolean"}]},FloatToBoolean:{className:"FlowGraphFloatToBoolean",category:"Conversion",description:"Converts a float to a boolean (0 \u2192 false, nonzero \u2192 true).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"number"}],dataOutputs:[{name:"value",type:"boolean"},{name:"isValid",type:"boolean"}]},IntToBoolean:{className:"FlowGraphIntToBoolean",category:"Conversion",description:"Converts an integer to a boolean (0 \u2192 false, nonzero \u2192 true).",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"FlowGraphInteger"}],dataOutputs:[{name:"value",type:"boolean"},{name:"isValid",type:"boolean"}]},IntToFloat:{className:"FlowGraphIntToFloat",category:"Conversion",description:"Converts an integer to a float.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"FlowGraphInteger"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},FloatToInt:{className:"FlowGraphFloatToInt",category:"Conversion",description:"Converts a float to an integer.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:"number"}],dataOutputs:[{name:"value",type:"FlowGraphInteger"},{name:"isValid",type:"boolean"}],config:{roundingMode:'"floor" | "ceil" | "round" \u2014 how to round the float value'}},PhysicsApplyForce:{className:"FlowGraphApplyForceBlock",category:"Execution",description:"Applies a force to a physics body at a given location.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody to apply force to"},{name:"force",type:"Vector3",description:"Force vector"},{name:"location",type:"Vector3",description:"World-space location to apply force at"}],dataOutputs:[]},PhysicsApplyImpulse:{className:"FlowGraphApplyImpulseBlock",category:"Execution",description:"Applies an impulse to a physics body at a given location.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody to apply impulse to"},{name:"impulse",type:"Vector3",description:"Impulse vector"},{name:"location",type:"Vector3",description:"World-space location to apply impulse at"}],dataOutputs:[]},PhysicsSetLinearVelocity:{className:"FlowGraphSetLinearVelocityBlock",category:"Execution",description:"Sets the linear velocity of a physics body.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"},{name:"velocity",type:"Vector3",description:"New linear velocity"}],dataOutputs:[]},PhysicsSetAngularVelocity:{className:"FlowGraphSetAngularVelocityBlock",category:"Execution",description:"Sets the angular velocity of a physics body.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"},{name:"velocity",type:"Vector3",description:"New angular velocity"}],dataOutputs:[]},PhysicsSetMotionType:{className:"FlowGraphSetPhysicsMotionTypeBlock",category:"Execution",description:"Sets the motion type of a physics body (Static=0, Animated=1, Dynamic=2).",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"},{name:"motionType",type:"number",description:"Motion type: Static (0), Animated (1), Dynamic (2)"}],dataOutputs:[]},PhysicsGetLinearVelocity:{className:"FlowGraphGetLinearVelocityBlock",category:"Data",description:"Gets the linear velocity of a physics body.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},PhysicsGetAngularVelocity:{className:"FlowGraphGetAngularVelocityBlock",category:"Data",description:"Gets the angular velocity of a physics body.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"}],dataOutputs:[{name:"value",type:"Vector3"},{name:"isValid",type:"boolean"}]},PhysicsGetMassProperties:{className:"FlowGraphGetPhysicsMassPropertiesBlock",category:"Data",description:"Gets mass, center of mass, and inertia of a physics body.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"body",type:"any",description:"The PhysicsBody"}],dataOutputs:[{name:"mass",type:"number"},{name:"centerOfMass",type:"Vector3"},{name:"inertia",type:"Vector3"}]},AudioPlaySound:{className:"FlowGraphPlaySoundBlock",category:"Execution",description:"Plays a sound with optional volume, offset, and loop control.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound to play (an Audio V2 sound or the name of a coordinator sound asset)"},{name:"volume",type:"number",description:"Playback volume (default: 1)"},{name:"startOffset",type:"number",description:"Start offset in seconds (default: 0)"},{name:"loop",type:"boolean",description:"Whether to loop (default: false)"}],dataOutputs:[]},AudioStopSound:{className:"FlowGraphStopSoundBlock",category:"Execution",description:"Stops a currently playing sound.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound to stop (an Audio V2 sound or the name of a coordinator sound asset)"}],dataOutputs:[]},AudioPauseSound:{className:"FlowGraphPauseSoundBlock",category:"Execution",description:"Pauses a currently playing sound.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound to pause (an Audio V2 sound or the name of a coordinator sound asset)"}],dataOutputs:[]},AudioSetVolume:{className:"FlowGraphSetSoundVolumeBlock",category:"Execution",description:"Sets the volume of a sound.",signalInputs:[{name:"in"}],signalOutputs:[{name:"out"},{name:"error"}],dataInputs:[{name:"sound",type:"any",description:"The sound (an Audio V2 sound or the name of a coordinator sound asset)"},{name:"volume",type:"number",description:"Volume level (default: 1)"}],dataOutputs:[]},AudioGetVolume:{className:"FlowGraphGetSoundVolumeBlock",category:"Data",description:"Gets the current volume of a sound.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"sound",type:"any",description:"The sound (an Audio V2 sound or the name of a coordinator sound asset)"}],dataOutputs:[{name:"value",type:"number"},{name:"isValid",type:"boolean"}]},AudioIsSoundPlaying:{className:"FlowGraphIsSoundPlayingBlock",category:"Data",description:"Returns whether a sound is currently playing.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"sound",type:"any",description:"The sound (an Audio V2 sound or the name of a coordinator sound asset)"}],dataOutputs:[{name:"value",type:"boolean"},{name:"isValid",type:"boolean"}]},DebugBlock:{className:"FlowGraphDebugBlock",category:"Utility",description:"Pass-through block that logs its input value for debugging. Output equals input.",signalInputs:[],signalOutputs:[],dataInputs:[{name:"input",type:"any"}],dataOutputs:[{name:"output",type:"any"}]}};function fe(e,t,r,o="any",n="any"){return{[e]:{className:t,category:"Math",description:r,signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:n,description:"Input value"}],dataOutputs:[{name:"value",type:o},{name:"isValid",type:"boolean"}]}}}function Le(e,t,r,o="any",n="any",i="any"){return{[e]:{className:t,category:"Math",description:r,signalInputs:[],signalOutputs:[],dataInputs:[{name:"a",type:n,description:"First operand"},{name:"b",type:i,description:"Second operand"}],dataOutputs:[{name:"value",type:o},{name:"isValid",type:"boolean"}]}}}function y_(){const e=new Map;for(const[r,o]of Object.entries(Xt))e.has(o.category)||e.set(o.category,[]),e.get(o.category).push(` ${r} (${o.className}): ${o.description.split(".")[0]}`);const t=[];for(const[r,o]of e)t.push(`
93
93
  ## ${r}
94
94
  `),t.push(...o);return t.join(`
95
95
  `)}function qN(e){if(Xt[e])return Xt[e];for(const t of Object.values(Xt))if(t.className===e)return t}const JN={any:void 0,string:"",number:0,boolean:!1,FlowGraphInteger:{value:0,className:"FlowGraphInteger"},Vector2:{value:[0,0],className:"Vector2"},Vector3:{value:[0,0,0],className:"Vector3"},Vector4:{value:[0,0,0,0],className:"Vector4"},Quaternion:{value:[0,0,0,1],className:"Quaternion"},Matrix:{value:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],className:"Matrix"},Color3:{value:[0,0,0],className:"Color3"},Color4:{value:[0,0,0,0],className:"Color4"},Matrix2D:{value:[1,0,0,1],className:"FlowGraphMatrix2D"},Matrix3D:{value:[1,0,0,0,1,0,0,0,1],className:"FlowGraphMatrix3D"}};function __(e){return JN[e]??void 0}const $_={targetMesh:"asset",target:"object"};function b_(e,t){if(e)for(const r of t){if(Object.prototype.hasOwnProperty.call(e,r.name)&&e[r.name]!==void 0){r.defaultValue=e[r.name];continue}for(const o of Object.keys($_))if($_[o]===r.name&&Object.prototype.hasOwnProperty.call(e,o)&&e[o]!==void 0){r.defaultValue=e[o];break}}}let w_=0;function At(){return w_++,`fg-${w_.toString(16).padStart(8,"0")}`}class KN{_graphs=new Map;createGraph(t){const r={name:t,blocks:[],contexts:[{uniqueId:At(),_userVariables:{},_connectionValues:{}}],nextBlockId:1};return this._graphs.set(t,r),r}getGraph(t){return this._graphs.get(t)}listGraphs(){return Array.from(this._graphs.keys())}deleteGraph(t){return this._graphs.delete(t)}clearAll(){this._graphs.clear()}addBlock(t,r,o,n){const i=this._graphs.get(t);if(!i)return`Graph "${t}" not found. Create it first with create_graph.`;const a=this._resolveBlockType(r);if(!a)return`Unknown block type "${r}". Use list_block_types to see available blocks.`;const s=i.nextBlockId++,c=o??`${r}_${s}`,u=At(),l=a.signalInputs.map(m=>({uniqueId:At(),name:m.name,_connectionType:0,connectedPointIds:[]})),d=a.signalOutputs.map(m=>({uniqueId:At(),name:m.name,_connectionType:1,connectedPointIds:[]}));if(n){const m=n.outputSignalCount??n.outputCount;if(typeof m=="number"&&m>0)for(let k=0;k<m;k++){const N=`out_${k}`;d.find(v=>v.name===N)||d.push({uniqueId:At(),name:N,_connectionType:1,connectedPointIds:[]})}if(Array.isArray(n.cases))for(let k=0;k<n.cases.length;k++){const N=`case_${k}`;d.find(v=>v.name===N)||d.push({uniqueId:At(),name:N,_connectionType:1,connectedPointIds:[]})}if(typeof n.inputSignalCount=="number"&&n.inputSignalCount>0)for(let k=0;k<n.inputSignalCount;k++){const N=`in_${k}`;l.find(v=>v.name===N)||l.push({uniqueId:At(),name:N,_connectionType:0,connectedPointIds:[]})}}const f=a.dataInputs.map(m=>({uniqueId:At(),name:m.name,_connectionType:0,connectedPointIds:[],className:"FlowGraphDataConnection",richType:{typeName:m.type,defaultValue:__(m.type)},optional:m.isOptional??!1})),p=a.dataOutputs.map(m=>({uniqueId:At(),name:m.name,_connectionType:1,connectedPointIds:[],className:"FlowGraphDataConnection",richType:{typeName:m.type,defaultValue:__(m.type)}}));b_(n,f),this._normalizeConfigAliases(n,a);const g=[];if(n&&a.config){const m=new Set(Object.keys(a.config));for(const k of Object.keys(n))if(!m.has(k)){const N=` Known keys: ${[...m].join(", ")}`;g.push(`Unknown config key "${k}" for ${a.className}.${N}`)}}const b={className:a.className,config:n??{},uniqueId:u,dataInputs:f,dataOutputs:p,signalInputs:l,signalOutputs:d,metadata:{displayName:c}},_={id:s,serialized:b,typeInfo:a,displayName:c};i.blocks.push(_);const S={id:s,name:c,uniqueId:u};return g.length>0&&(S.warnings=g),S}removeBlock(t,r){const o=this._graphs.get(t);if(!o)return`Graph "${t}" not found.`;const n=o.blocks.findIndex(s=>s.id===r);if(n===-1)return`Block ${r} not found.`;const i=o.blocks[n],a=new Set;for(const s of[...i.serialized.dataInputs,...i.serialized.dataOutputs,...i.serialized.signalInputs,...i.serialized.signalOutputs])a.add(s.uniqueId);for(const s of o.blocks)if(s.id!==r)for(const c of[...s.serialized.dataInputs,...s.serialized.dataOutputs,...s.serialized.signalInputs,...s.serialized.signalOutputs])c.connectedPointIds=c.connectedPointIds.filter(u=>!a.has(u));return o.blocks.splice(n,1),"OK"}setBlockConfig(t,r,o){const n=this._graphs.get(t);if(!n)return`Graph "${t}" not found.`;const i=n.blocks.find(a=>a.id===r);if(!i)return`Block ${r} not found.`;this._normalizeConfigAliases(o,i.typeInfo);for(const a of Object.keys(o))a==="__proto__"||a==="constructor"||a==="prototype"||(i.serialized.config[a]=o[a]);return b_(i.serialized.config,i.serialized.dataInputs),"OK"}connectData(t,r,o,n,i){const a=this._graphs.get(t);if(!a)return`Graph "${t}" not found.`;const s=a.blocks.find(d=>d.id===r);if(!s)return`Source block ${r} not found.`;const c=a.blocks.find(d=>d.id===n);if(!c)return`Target block ${n} not found.`;const u=s.serialized.dataOutputs.find(d=>d.name===o);if(!u){const f={value:["output"],output:["value"]}[o],p=f?s.serialized.dataOutputs.find(b=>f.includes(b.name)):void 0;if(p){const b=c.serialized.dataInputs.find(_=>_.name===i);if(!b){const _=c.serialized.dataInputs.map(S=>S.name).join(", ");return`Input "${i}" not found on block ${n} (${c.displayName}). Available inputs: ${_}`}return b.connectedPointIds.includes(p.uniqueId)||b.connectedPointIds.push(p.uniqueId),"OK"}const g=s.serialized.dataOutputs.map(b=>b.name).join(", ");return`Output "${o}" not found on block ${r} (${s.displayName}). Available outputs: ${g}`}const l=c.serialized.dataInputs.find(d=>d.name===i);if(!l){const f={value:["input"],input:["value"]}[i],p=f?c.serialized.dataInputs.find(b=>f.includes(b.name)):void 0;if(p)return p.connectedPointIds.includes(u.uniqueId)||p.connectedPointIds.push(u.uniqueId),"OK";const g=c.serialized.dataInputs.map(b=>b.name).join(", ");return`Input "${i}" not found on block ${n} (${c.displayName}). Available inputs: ${g}`}return l.connectedPointIds.includes(u.uniqueId)||l.connectedPointIds.push(u.uniqueId),"OK"}connectSignal(t,r,o,n,i){const a=this._graphs.get(t);if(!a)return`Graph "${t}" not found.`;const s=a.blocks.find(f=>f.id===r);if(!s)return`Source block ${r} not found.`;const c=a.blocks.find(f=>f.id===n);if(!c)return`Target block ${n} not found.`;let u=o;o==="out"&&s.typeInfo.category==="Event"&&s.serialized.signalOutputs.some(p=>p.name==="done")&&(u="done");const l=s.serialized.signalOutputs.find(f=>f.name===u);if(!l){const f=s.serialized.signalOutputs.map(p=>p.name).join(", ");return`Signal output "${o}" not found on block ${r} (${s.displayName}). Available: ${f}`}const d=c.serialized.signalInputs.find(f=>f.name===i);if(!d){const f=c.serialized.signalInputs.map(p=>p.name).join(", ");return`Signal input "${i}" not found on block ${n} (${c.displayName}). Available: ${f}`}return l.connectedPointIds.includes(d.uniqueId)||l.connectedPointIds.push(d.uniqueId),"OK"}disconnectData(t,r,o){const n=this._graphs.get(t);if(!n)return`Graph "${t}" not found.`;const i=n.blocks.find(s=>s.id===r);if(!i)return`Block ${r} not found.`;const a=i.serialized.dataInputs.find(s=>s.name===o);return a?(a.connectedPointIds=[],"OK"):`Data input "${o}" not found on block ${r}.`}disconnectSignal(t,r,o){const n=this._graphs.get(t);if(!n)return`Graph "${t}" not found.`;const i=n.blocks.find(s=>s.id===r);if(!i)return`Block ${r} not found.`;const a=i.serialized.signalOutputs.find(s=>s.name===o);return a?(a.connectedPointIds=[],"OK"):`Signal output "${o}" not found on block ${r}.`}setVariable(t,r,o){const n=this._graphs.get(t);return n?(n.contexts.length===0&&n.contexts.push({uniqueId:At(),_userVariables:{},_connectionValues:{}}),n.contexts[0]._userVariables[r]=o,"OK"):`Graph "${t}" not found.`}describeGraph(t){const r=this._graphs.get(t);if(!r)return`Graph "${t}" not found.`;if(r.blocks.length===0)return`Graph "${t}" is empty. Add blocks with add_block.`;const o=[`# Flow Graph: ${t}`,`Blocks: ${r.blocks.length}`,""],n=new Map;for(const i of r.blocks){const a=i.typeInfo.category;n.has(a)||n.set(a,[]),n.get(a).push(i)}for(const[i,a]of n){o.push(`## ${i}`);for(const s of a){o.push(` [${s.id}] ${s.displayName} (${s.serialized.className})`);for(const c of s.serialized.dataInputs)if(c.connectedPointIds.length>0){const u=this._findConnectionSource(r,c.connectedPointIds[0]);o.push(` \u2190 ${c.name}: connected from ${u}`)}for(const c of s.serialized.signalOutputs)if(c.connectedPointIds.length>0){const u=this._findSignalTarget(r,c.connectedPointIds[0]);o.push(` \u2192 ${c.name}: connected to ${u}`)}}o.push("")}if(r.contexts.length>0&&Object.keys(r.contexts[0]._userVariables).length>0){o.push("## Context Variables");for(const[i,a]of Object.entries(r.contexts[0]._userVariables))o.push(` ${i} = ${JSON.stringify(a)}`)}return o.join(`