@babylonjs/mcp-servers 9.31.3 → 9.32.1

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.
@@ -88,7 +88,7 @@ data: ${JSON.stringify({reason:r})}
88
88
 
89
89
  `);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:ua}),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}
90
90
 
91
- `)}_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:ua,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 eT{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 QN({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 Rn={ParticleInputBlock:{className:"ParticleInputBlock",category:"Input",description:"Provides input values to the particle graph. Can be configured as a contextual source (Position, Direction, Age, Lifetime, Color, etc.), a system source (Time, Delta, Emitter, CameraPosition), or a constant value (Float, Int, Vector2, Vector3, Color4, Matrix).",inputs:[],outputs:[{name:"output",type:"AutoDetect"}],properties:{type:"NodeParticleBlockConnectionPointTypes \u2014 the data type (Int, Float, Vector2, Vector3, Color4, Matrix, Texture)",contextualValue:"NodeParticleContextualSources \u2014 None, Position, Direction, Age, Lifetime, Color, ScaledDirection, Scale, AgeGradient, Angle, SpriteCellIndex, SpriteCellStart, SpriteCellEnd, InitialColor, ColorDead, InitialDirection, ColorStep, ScaledColorStep, LocalPositionUpdated, Size, DirectionScale",systemSource:"NodeParticleSystemSources \u2014 None, Time, Delta, Emitter, CameraPosition",value:"The actual constant value (number, Vector2, Vector3, Color4, Matrix)",min:"number \u2014 minimum value for inspector slider",max:"number \u2014 maximum value for inspector slider"}},SystemBlock:{className:"SystemBlock",category:"System",description:"The output block that produces a particle system. Every particle graph needs at least one. A graph can have multiple SystemBlocks, each producing a separate ParticleSystem.",inputs:[{name:"particle",type:"Particle"},{name:"emitRate",type:"Int",isOptional:!0},{name:"texture",type:"Texture"},{name:"translationPivot",type:"Vector2",isOptional:!0},{name:"textureMask",type:"Color4",isOptional:!0},{name:"targetStopDuration",type:"Float",isOptional:!0},{name:"onStart",type:"System",isOptional:!0},{name:"onEnd",type:"System",isOptional:!0}],outputs:[{name:"system",type:"System"}],properties:{blendMode:"number \u2014 blend mode (0=OneOne, 1=Standard, 2=Add, 3=Multiply, 4=MultiplyAdd). Default: 0",capacity:"number \u2014 max particles in system. Default: 1000",manualEmitCount:"number \u2014 manual emit count (-1 for auto). Default: -1",startDelay:"number \u2014 delay before start in ms. Default: 0",updateSpeed:"number \u2014 update speed. Default: 0.0167",preWarmCycles:"number \u2014 pre-warm cycles. Default: 0",preWarmStepOffset:"number \u2014 pre-warm step multiplier. Default: 0",isBillboardBased:"boolean \u2014 billboard-based particles. Default: true",billBoardMode:"number \u2014 billboard mode (7=All, 2=Y, 6=Stretched, 9=StretchedLocal). Default: 7",isLocal:"boolean \u2014 local coordinate space. Default: false",disposeOnStop:"boolean \u2014 dispose when stopped. Default: false",doNoStart:"boolean \u2014 do not auto-start. Default: false",renderingGroupId:"number \u2014 rendering group. Default: 0"},defaultSerializedProperties:{blendMode:0,capacity:1e3,manualEmitCount:-1,startDelay:0,updateSpeed:.0167,preWarmCycles:0,preWarmStepOffset:0,isBillboardBased:!0,billBoardMode:7,isLocal:!1,disposeOnStop:!1,doNoStart:!1,renderingGroupId:0}},ParticleTextureSourceBlock:{className:"ParticleTextureSourceBlock",category:"Texture",description:"Provides a texture for particles. The texture URL or cached data is configured via properties.",inputs:[],outputs:[{name:"texture",type:"Texture"}],properties:{url:"string \u2014 URL of the particle texture image (e.g. 'https://assets.babylonjs.com/textures/flare.png')",textureDataUrl:"string \u2014 base64 data URL alternative to url (set serializedCachedData: true)",serializedCachedData:"boolean \u2014 whether texture is stored as base64 data URL. Default: false",invertY:"boolean \u2014 whether to invert Y. Default: true"},defaultSerializedProperties:{invertY:!0,serializedCachedData:!1}},BoxShapeBlock:{className:"BoxShapeBlock",category:"Shape",description:"Box-shaped emitter that spawns particles within a box region.",inputs:[{name:"particle",type:"Particle"},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0},{name:"minEmitBox",type:"Vector3",isOptional:!0},{name:"maxEmitBox",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},SphereShapeBlock:{className:"SphereShapeBlock",category:"Shape",description:"Sphere-shaped emitter that spawns particles on or within a sphere.",inputs:[{name:"particle",type:"Particle"},{name:"radius",type:"Float",isOptional:!0},{name:"radiusRange",type:"Float",isOptional:!0},{name:"directionRandomizer",type:"Float",isOptional:!0},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},ConeShapeBlock:{className:"ConeShapeBlock",category:"Shape",description:"Cone-shaped emitter that spawns particles within a cone.",inputs:[{name:"particle",type:"Particle"},{name:"radius",type:"Float",isOptional:!0},{name:"angle",type:"Float",isOptional:!0},{name:"radiusRange",type:"Float",isOptional:!0},{name:"heightRange",type:"Float",isOptional:!0},{name:"directionRandomizer",type:"Float",isOptional:!0},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},CylinderShapeBlock:{className:"CylinderShapeBlock",category:"Shape",description:"Cylinder-shaped emitter that spawns particles within a cylinder.",inputs:[{name:"particle",type:"Particle"},{name:"radius",type:"Float",isOptional:!0},{name:"height",type:"Float",isOptional:!0},{name:"radiusRange",type:"Float",isOptional:!0},{name:"directionRandomizer",type:"Float",isOptional:!0},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},PointShapeBlock:{className:"PointShapeBlock",category:"Shape",description:"Point emitter that spawns particles from a single point.",inputs:[{name:"particle",type:"Particle"},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},CustomShapeBlock:{className:"CustomShapeBlock",category:"Shape",description:"Custom emitter that spawns particles using a user-defined function.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}]},MeshShapeBlock:{className:"MeshShapeBlock",category:"Shape",description:"Mesh-based emitter that spawns particles on the surface of a mesh.",inputs:[{name:"particle",type:"Particle"},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}],properties:{useMeshNormalsForDirection:"boolean \u2014 use mesh normals for direction. Default: true"},defaultSerializedProperties:{useMeshNormalsForDirection:!0}},CreateParticleBlock:{className:"CreateParticleBlock",category:"Setup",description:"Creates a new particle with initial properties (emit power, lifetime, color, scale, angle, size).",inputs:[{name:"emitPower",type:"Float",isOptional:!0},{name:"lifeTime",type:"Float",isOptional:!0},{name:"color",type:"Color4",isOptional:!0},{name:"colorDead",type:"Color4",isOptional:!0},{name:"scale",type:"Vector2",isOptional:!0},{name:"angle",type:"Float",isOptional:!0},{name:"size",type:"Float",isOptional:!0}],outputs:[{name:"particle",type:"Particle"}]},SetupSpriteSheetBlock:{className:"SetupSpriteSheetBlock",category:"Setup",description:"Configures sprite sheet animation for particles.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}],properties:{start:"number \u2014 start cell index. Default: 0",end:"number \u2014 end cell index. Default: 8",width:"number \u2014 sprite sheet width. Default: 64",height:"number \u2014 sprite sheet height. Default: 64",spriteCellChangeSpeed:"number \u2014 cell change speed. Default: 1",loop:"boolean \u2014 loop sprite animation. Default: false",randomStartCell:"boolean \u2014 random start cell. Default: false"},defaultSerializedProperties:{start:0,end:8,width:64,height:64,spriteCellChangeSpeed:1,loop:!1,randomStartCell:!1}},UpdatePositionBlock:{className:"UpdatePositionBlock",category:"Update",description:"Updates a particle's position with a new Vector3 value.",inputs:[{name:"particle",type:"Particle"},{name:"position",type:"Vector3"}],outputs:[{name:"output",type:"Particle"}]},UpdateDirectionBlock:{className:"UpdateDirectionBlock",category:"Update",description:"Updates a particle's direction with a new Vector3 value.",inputs:[{name:"particle",type:"Particle"},{name:"direction",type:"Vector3"}],outputs:[{name:"output",type:"Particle"}]},UpdateColorBlock:{className:"UpdateColorBlock",category:"Update",description:"Updates a particle's color with a new Color4 value.",inputs:[{name:"particle",type:"Particle"},{name:"color",type:"Color4"}],outputs:[{name:"output",type:"Particle"}]},UpdateScaleBlock:{className:"UpdateScaleBlock",category:"Update",description:"Updates a particle's scale with a new Vector2 value.",inputs:[{name:"particle",type:"Particle"},{name:"scale",type:"Vector2"}],outputs:[{name:"output",type:"Particle"}]},UpdateSizeBlock:{className:"UpdateSizeBlock",category:"Update",description:"Updates a particle's size with a new Float value.",inputs:[{name:"particle",type:"Particle"},{name:"size",type:"Float"}],outputs:[{name:"output",type:"Particle"}]},UpdateAngleBlock:{className:"UpdateAngleBlock",category:"Update",description:"Updates a particle's angle (rotation) with a new Float value.",inputs:[{name:"particle",type:"Particle"},{name:"angle",type:"Float"}],outputs:[{name:"output",type:"Particle"}]},UpdateAgeBlock:{className:"UpdateAgeBlock",category:"Update",description:"Updates a particle's age with a new Float value.",inputs:[{name:"particle",type:"Particle"},{name:"age",type:"Float"}],outputs:[{name:"output",type:"Particle"}]},BasicPositionUpdateBlock:{className:"BasicPositionUpdateBlock",category:"Update",description:"Applies basic position update to a particle (position += direction * delta).",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}]},BasicColorUpdateBlock:{className:"BasicColorUpdateBlock",category:"Update",description:"Applies basic color interpolation between initial color and dead color over particle lifetime.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}]},BasicSpriteUpdateBlock:{className:"BasicSpriteUpdateBlock",category:"Update",description:"Applies basic sprite sheet update to a particle over its lifetime.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}]},UpdateSpriteCellIndexBlock:{className:"UpdateSpriteCellIndexBlock",category:"Update",description:"Updates a particle's sprite cell index with a new Int value.",inputs:[{name:"particle",type:"Particle"},{name:"cellIndex",type:"Int"}],outputs:[{name:"output",type:"Particle"}]},UpdateFlowMapBlock:{className:"UpdateFlowMapBlock",category:"Update",description:"Updates a particle's position using a flow map texture.",inputs:[{name:"particle",type:"Particle"},{name:"flowMap",type:"Texture"},{name:"strength",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},UpdateNoiseBlock:{className:"UpdateNoiseBlock",category:"Update",description:"Updates a particle's position using a noise texture.",inputs:[{name:"particle",type:"Particle"},{name:"noiseTexture",type:"Texture"},{name:"strength",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},UpdateAttractorBlock:{className:"UpdateAttractorBlock",category:"Update",description:"Applies an attractor force to the particle, pulling it toward a point.",inputs:[{name:"particle",type:"Particle"},{name:"attractor",type:"Vector3",isOptional:!0},{name:"strength",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},AlignAngleBlock:{className:"AlignAngleBlock",category:"Update",description:"Aligns the angle of a particle to its direction vector.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}],properties:{alignment:"number \u2014 alignment offset in radians. Default: PI/2"},defaultSerializedProperties:{alignment:Math.PI/2}},ParticleTriggerBlock:{className:"ParticleTriggerBlock",category:"Trigger",description:"Triggers sub-emitters or other systems based on particle events. Connects particle flow to a system for spawning sub-particles.",inputs:[{name:"input",type:"Particle"},{name:"condition",type:"Float",isOptional:!0},{name:"system",type:"System"}],outputs:[{name:"output",type:"Particle"}]},ParticleMathBlock:{className:"ParticleMathBlock",category:"Math",description:"Applies standard math operations (Add, Subtract, Multiply, Divide, Max, Min) to two inputs.",inputs:[{name:"left",type:"AutoDetect"},{name:"right",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{operation:"ParticleMathBlockOperations \u2014 Add (0), Subtract (1), Multiply (2), Divide (3), Max (4), Min (5). Default: Add"},defaultSerializedProperties:{operation:0}},ParticleNumberMathBlock:{className:"ParticleNumberMathBlock",category:"Math",description:"Applies number-only math (Modulo, Pow) to two numeric inputs.",inputs:[{name:"left",type:"AutoDetect"},{name:"right",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{operation:"ParticleNumberMathBlockOperations \u2014 Modulo (0), Pow (1). Default: Modulo"},defaultSerializedProperties:{operation:0}},ParticleVectorMathBlock:{className:"ParticleVectorMathBlock",category:"Math",description:"Applies vector-only math (Dot, Distance) to two Vector3 inputs.",inputs:[{name:"left",type:"Vector3"},{name:"right",type:"Vector3"}],outputs:[{name:"output",type:"Float"}],properties:{operation:"ParticleVectorMathBlockOperations \u2014 Dot (0), Distance (1). Default: Dot"},defaultSerializedProperties:{operation:0}},ParticleTrigonometryBlock:{className:"ParticleTrigonometryBlock",category:"Math",description:"Applies trigonometric/scientific operations (Cos, Sin, Abs, Exp, Exp2, Round, Floor, Ceiling, Sqrt, Log, Tan, ArcTan, ArcCos, ArcSin, Sign, Negate, OneMinus, Reciprocal, ToDegrees, ToRadians, Fract).",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{operation:"ParticleTrigonometryBlockOperations \u2014 Cos (0), Sin (1), Abs (2), Exp (3), Exp2 (4), Round (5), Floor (6), Ceiling (7), Sqrt (8), Log (9), Tan (10), ArcTan (11), ArcCos (12), ArcSin (13), Sign (14), Negate (15), OneMinus (16), Reciprocal (17), ToDegrees (18), ToRadians (19), Fract (20). Default: Cos"},defaultSerializedProperties:{operation:0}},ParticleVectorLengthBlock:{className:"ParticleVectorLengthBlock",category:"Math",description:"Computes the length of a vector input.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"Float"}]},ParticleFloatToIntBlock:{className:"ParticleFloatToIntBlock",category:"Math",description:"Converts a float to an int using Round, Ceil, Floor, or Truncate.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"Int"}],properties:{operation:"ParticleFloatToIntBlockOperations \u2014 Round (0), Ceil (1), Floor (2), Truncate (3). Default: Round"},defaultSerializedProperties:{operation:0}},ParticleConditionBlock:{className:"ParticleConditionBlock",category:"Condition",description:"Evaluates a condition (Equal, NotEqual, LessThan, GreaterThan, etc.) and returns ifTrue or ifFalse value.",inputs:[{name:"left",type:"Float"},{name:"right",type:"Float",isOptional:!0},{name:"ifTrue",type:"AutoDetect",isOptional:!0},{name:"ifFalse",type:"AutoDetect",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{test:"ParticleConditionBlockTests \u2014 Equal (0), NotEqual (1), LessThan (2), GreaterThan (3), LessOrEqual (4), GreaterOrEqual (5), Xor (6), Or (7), And (8). Default: Equal",epsilon:"number \u2014 epsilon for comparison. Default: 0"},defaultSerializedProperties:{test:0,epsilon:0}},ParticleLerpBlock:{className:"ParticleLerpBlock",category:"Interpolation",description:"Linearly interpolates between two values based on a gradient.",inputs:[{name:"left",type:"AutoDetect"},{name:"right",type:"AutoDetect"},{name:"gradient",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleNLerpBlock:{className:"ParticleNLerpBlock",category:"Interpolation",description:"Normalised linear interpolation between two values.",inputs:[{name:"left",type:"AutoDetect"},{name:"right",type:"AutoDetect"},{name:"gradient",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleSmoothStepBlock:{className:"ParticleSmoothStepBlock",category:"Interpolation",description:"Smooth step interpolation between two edges.",inputs:[{name:"value",type:"AutoDetect"},{name:"edge0",type:"Float",isOptional:!0},{name:"edge1",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleStepBlock:{className:"ParticleStepBlock",category:"Interpolation",description:"Step function: returns 0 if value < edge, else 1.",inputs:[{name:"value",type:"AutoDetect"},{name:"edge",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleClampBlock:{className:"ParticleClampBlock",category:"Interpolation",description:"Clamps a value between min and max.",inputs:[{name:"value",type:"AutoDetect"},{name:"min",type:"Float",isOptional:!0},{name:"max",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleGradientBlock:{className:"ParticleGradientBlock",category:"Interpolation",description:"Defines a multi-stop gradient. Dynamically extends with more value inputs as needed.",inputs:[{name:"gradient",type:"Float",isOptional:!0},{name:"value0",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleGradientValueBlock:{className:"ParticleGradientValueBlock",category:"Interpolation",description:"Defines a single gradient entry with a reference position (0-1).",inputs:[{name:"value",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{reference:"number \u2014 gradient position 0\u20131. Default: 0"},defaultSerializedProperties:{reference:0}},ParticleRandomBlock:{className:"ParticleRandomBlock",category:"Misc",description:"Generates a random value between min and max.",inputs:[{name:"min",type:"AutoDetect",isOptional:!0},{name:"max",type:"AutoDetect",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{lockMode:"ParticleRandomBlockLocks \u2014 None (0), PerParticle (1), PerSystem (2), OncePerParticle (3). Default: PerParticle"},defaultSerializedProperties:{lockMode:1}},ParticleConverterBlock:{className:"ParticleConverterBlock",category:"Converter",description:"Converts between Color4/Vector3/Vector2/Float components. NOTE: Input port names have a TRAILING SPACE to disambiguate from outputs. When connecting to inputs, use 'color ', 'xyz ', 'xy ', 'zw ', 'x ', 'y ', 'z ', 'w ' (with trailing space).",inputs:[{name:"color ",type:"Color4",isOptional:!0},{name:"xyz ",type:"Vector3",isOptional:!0},{name:"xy ",type:"Vector2",isOptional:!0},{name:"zw ",type:"Vector2",isOptional:!0},{name:"x ",type:"Float",isOptional:!0},{name:"y ",type:"Float",isOptional:!0},{name:"z ",type:"Float",isOptional:!0},{name:"w ",type:"Float",isOptional:!0}],outputs:[{name:"color",type:"Color4"},{name:"xyz",type:"Vector3"},{name:"xy",type:"Vector2"},{name:"zw",type:"Vector2"},{name:"x",type:"Float"},{name:"y",type:"Float"},{name:"z",type:"Float"},{name:"w",type:"Float"}]},ParticleDebugBlock:{className:"ParticleDebugBlock",category:"Utility",description:"Debug block that passes through its input and can log values.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleElbowBlock:{className:"ParticleElbowBlock",category:"Utility",description:"Pass-through block used for visual routing in the editor.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleLocalVariableBlock:{className:"ParticleLocalVariableBlock",category:"Utility",description:"Stores a local variable scoped to a particle or loop iteration.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{scope:"ParticleLocalVariableBlockScope \u2014 Particle (0), Loop (1). Default: Particle"},defaultSerializedProperties:{scope:0}},ParticleTeleportInBlock:{className:"ParticleTeleportInBlock",category:"Teleport",description:"Entry point for a teleport pair. Accepts any input and teleports it to a matching TeleportOut.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[]},ParticleTeleportOutBlock:{className:"ParticleTeleportOutBlock",category:"Teleport",description:"Exit point for a teleport pair. Outputs the value received from a matching TeleportIn.",inputs:[],outputs:[{name:"output",type:"BasedOnInput"}]}};function S$(){const e=new Map;for(const[r,o]of Object.entries(Rn))e.has(o.category)||e.set(o.category,[]),e.get(o.category).push(` ${r}: ${o.description.split(".")[0]}`);const t=[];for(const[r,o]of e)t.push(`
91
+ `)}_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:ua,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 eT{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 QN({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 Rn={ParticleInputBlock:{className:"ParticleInputBlock",category:"Input",description:"Provides input values to the particle graph. Can be configured as a contextual source (Position, Direction, Age, Lifetime, Color, etc.), a system source (Time, Delta, Emitter, CameraPosition), or a constant value (Float, Int, Vector2, Vector3, Color4, Matrix).",inputs:[],outputs:[{name:"output",type:"AutoDetect"}],properties:{type:"NodeParticleBlockConnectionPointTypes \u2014 the data type (Int, Float, Vector2, Vector3, Color4, Matrix, Texture)",contextualValue:"NodeParticleContextualSources \u2014 None, Position, Direction, Age, Lifetime, Color, ScaledDirection, Scale, AgeGradient, Angle, SpriteCellIndex, SpriteCellStart, SpriteCellEnd, InitialColor, ColorDead, InitialDirection, ColorStep, ScaledColorStep, LocalPositionUpdated, Size, DirectionScale",systemSource:"NodeParticleSystemSources \u2014 None, Time, Delta, Emitter, CameraPosition",value:"The actual constant value (number, Vector2, Vector3, Color4, Matrix)",min:"number \u2014 minimum value for inspector slider",max:"number \u2014 maximum value for inspector slider"}},SystemBlock:{className:"SystemBlock",category:"System",description:"The output block that produces a particle system. Every particle graph needs at least one. A graph can have multiple SystemBlocks, each producing a separate ParticleSystem.",inputs:[{name:"particle",type:"Particle"},{name:"emitRate",type:"Int",isOptional:!0},{name:"texture",type:"Texture"},{name:"translationPivot",type:"Vector2",isOptional:!0},{name:"textureMask",type:"Color4",isOptional:!0},{name:"targetStopDuration",type:"Float",isOptional:!0},{name:"onStart",type:"System",isOptional:!0},{name:"onEnd",type:"System",isOptional:!0}],outputs:[{name:"system",type:"System"}],properties:{blendMode:"number \u2014 blend mode (0=OneOne, 1=Standard, 2=Add, 3=Multiply, 4=MultiplyAdd). Default: 0",capacity:"number \u2014 max particles in system. Default: 1000",manualEmitCount:"number \u2014 manual emit count (-1 for auto). Default: -1",startDelay:"number \u2014 delay before start in ms. Default: 0",updateSpeed:"number \u2014 update speed. Default: 0.0167",preWarmCycles:"number \u2014 pre-warm cycles. Default: 0",preWarmStepOffset:"number \u2014 pre-warm step multiplier. Default: 1",isBillboardBased:"boolean \u2014 billboard-based particles. Default: true",billBoardMode:"number \u2014 billboard mode (7=All, 2=Y, 6=Stretched, 9=StretchedLocal). Default: 7",isLocal:"boolean \u2014 local coordinate space. Default: false",disposeOnStop:"boolean \u2014 dispose when stopped. Default: false",doNoStart:"boolean \u2014 do not auto-start. Default: false",renderingGroupId:"number \u2014 rendering group. Default: 0"},defaultSerializedProperties:{blendMode:0,capacity:1e3,manualEmitCount:-1,startDelay:0,updateSpeed:.0167,preWarmCycles:0,preWarmStepOffset:1,isBillboardBased:!0,billBoardMode:7,isLocal:!1,disposeOnStop:!1,doNoStart:!1,renderingGroupId:0}},ParticleTextureSourceBlock:{className:"ParticleTextureSourceBlock",category:"Texture",description:"Provides a texture for particles. The texture URL or cached data is configured via properties.",inputs:[],outputs:[{name:"texture",type:"Texture"}],properties:{url:"string \u2014 URL of the particle texture image (e.g. 'https://assets.babylonjs.com/textures/flare.png')",textureDataUrl:"string \u2014 base64 data URL alternative to url (set serializedCachedData: true)",serializedCachedData:"boolean \u2014 whether texture is stored as base64 data URL. Default: false",invertY:"boolean \u2014 whether to invert Y. Default: true"},defaultSerializedProperties:{invertY:!0,serializedCachedData:!1}},BoxShapeBlock:{className:"BoxShapeBlock",category:"Shape",description:"Box-shaped emitter that spawns particles within a box region.",inputs:[{name:"particle",type:"Particle"},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0},{name:"minEmitBox",type:"Vector3",isOptional:!0},{name:"maxEmitBox",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},SphereShapeBlock:{className:"SphereShapeBlock",category:"Shape",description:"Sphere-shaped emitter that spawns particles on or within a sphere.",inputs:[{name:"particle",type:"Particle"},{name:"radius",type:"Float",isOptional:!0},{name:"radiusRange",type:"Float",isOptional:!0},{name:"directionRandomizer",type:"Float",isOptional:!0},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},ConeShapeBlock:{className:"ConeShapeBlock",category:"Shape",description:"Cone-shaped emitter that spawns particles within a cone.",inputs:[{name:"particle",type:"Particle"},{name:"radius",type:"Float",isOptional:!0},{name:"angle",type:"Float",isOptional:!0},{name:"radiusRange",type:"Float",isOptional:!0},{name:"heightRange",type:"Float",isOptional:!0},{name:"directionRandomizer",type:"Float",isOptional:!0},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},CylinderShapeBlock:{className:"CylinderShapeBlock",category:"Shape",description:"Cylinder-shaped emitter that spawns particles within a cylinder.",inputs:[{name:"particle",type:"Particle"},{name:"radius",type:"Float",isOptional:!0},{name:"height",type:"Float",isOptional:!0},{name:"radiusRange",type:"Float",isOptional:!0},{name:"directionRandomizer",type:"Float",isOptional:!0},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},PointShapeBlock:{className:"PointShapeBlock",category:"Shape",description:"Point emitter that spawns particles from a single point.",inputs:[{name:"particle",type:"Particle"},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},CustomShapeBlock:{className:"CustomShapeBlock",category:"Shape",description:"Custom emitter that spawns particles using a user-defined function.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}]},MeshShapeBlock:{className:"MeshShapeBlock",category:"Shape",description:"Mesh-based emitter that spawns particles on the surface of a mesh.",inputs:[{name:"particle",type:"Particle"},{name:"direction1",type:"Vector3",isOptional:!0},{name:"direction2",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}],properties:{useMeshNormalsForDirection:"boolean \u2014 use mesh normals for direction. Default: true"},defaultSerializedProperties:{useMeshNormalsForDirection:!0}},CreateParticleBlock:{className:"CreateParticleBlock",category:"Setup",description:"Creates a new particle with initial properties (emit power, lifetime, color, scale, angle, size).",inputs:[{name:"emitPower",type:"Float",isOptional:!0},{name:"lifeTime",type:"Float",isOptional:!0},{name:"color",type:"Color4",isOptional:!0},{name:"colorDead",type:"Color4",isOptional:!0},{name:"scale",type:"Vector2",isOptional:!0},{name:"angle",type:"Float",isOptional:!0},{name:"size",type:"Float",isOptional:!0}],outputs:[{name:"particle",type:"Particle"}]},SetupSpriteSheetBlock:{className:"SetupSpriteSheetBlock",category:"Setup",description:"Configures sprite sheet animation for particles.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}],properties:{start:"number \u2014 start cell index. Default: 0",end:"number \u2014 end cell index. Default: 8",width:"number \u2014 sprite sheet width. Default: 64",height:"number \u2014 sprite sheet height. Default: 64",spriteCellChangeSpeed:"number \u2014 cell change speed. Default: 1",loop:"boolean \u2014 loop sprite animation. Default: false",randomStartCell:"boolean \u2014 random start cell. Default: false"},defaultSerializedProperties:{start:0,end:8,width:64,height:64,spriteCellChangeSpeed:1,loop:!1,randomStartCell:!1}},UpdatePositionBlock:{className:"UpdatePositionBlock",category:"Update",description:"Updates a particle's position with a new Vector3 value.",inputs:[{name:"particle",type:"Particle"},{name:"position",type:"Vector3"}],outputs:[{name:"output",type:"Particle"}]},UpdateDirectionBlock:{className:"UpdateDirectionBlock",category:"Update",description:"Updates a particle's direction with a new Vector3 value.",inputs:[{name:"particle",type:"Particle"},{name:"direction",type:"Vector3"}],outputs:[{name:"output",type:"Particle"}]},UpdateColorBlock:{className:"UpdateColorBlock",category:"Update",description:"Updates a particle's color with a new Color4 value.",inputs:[{name:"particle",type:"Particle"},{name:"color",type:"Color4"}],outputs:[{name:"output",type:"Particle"}]},UpdateScaleBlock:{className:"UpdateScaleBlock",category:"Update",description:"Updates a particle's scale with a new Vector2 value.",inputs:[{name:"particle",type:"Particle"},{name:"scale",type:"Vector2"}],outputs:[{name:"output",type:"Particle"}]},UpdateSizeBlock:{className:"UpdateSizeBlock",category:"Update",description:"Updates a particle's size with a new Float value.",inputs:[{name:"particle",type:"Particle"},{name:"size",type:"Float"}],outputs:[{name:"output",type:"Particle"}]},UpdateAngleBlock:{className:"UpdateAngleBlock",category:"Update",description:"Updates a particle's angle (rotation) with a new Float value.",inputs:[{name:"particle",type:"Particle"},{name:"angle",type:"Float"}],outputs:[{name:"output",type:"Particle"}]},UpdateAgeBlock:{className:"UpdateAgeBlock",category:"Update",description:"Updates a particle's age with a new Float value.",inputs:[{name:"particle",type:"Particle"},{name:"age",type:"Float"}],outputs:[{name:"output",type:"Particle"}]},BasicPositionUpdateBlock:{className:"BasicPositionUpdateBlock",category:"Update",description:"Applies basic position update to a particle (position += direction * delta).",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}]},BasicColorUpdateBlock:{className:"BasicColorUpdateBlock",category:"Update",description:"Applies basic color interpolation between initial color and dead color over particle lifetime.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}]},BasicSpriteUpdateBlock:{className:"BasicSpriteUpdateBlock",category:"Update",description:"Applies basic sprite sheet update to a particle over its lifetime.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}]},UpdateSpriteCellIndexBlock:{className:"UpdateSpriteCellIndexBlock",category:"Update",description:"Updates a particle's sprite cell index with a new Int value.",inputs:[{name:"particle",type:"Particle"},{name:"cellIndex",type:"Int"}],outputs:[{name:"output",type:"Particle"}]},UpdateFlowMapBlock:{className:"UpdateFlowMapBlock",category:"Update",description:"Updates a particle's position using a flow map texture.",inputs:[{name:"particle",type:"Particle"},{name:"flowMap",type:"Texture"},{name:"strength",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},UpdateNoiseBlock:{className:"UpdateNoiseBlock",category:"Update",description:"Updates a particle's position using a noise texture.",inputs:[{name:"particle",type:"Particle"},{name:"noiseTexture",type:"Texture"},{name:"strength",type:"Vector3",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},UpdateAttractorBlock:{className:"UpdateAttractorBlock",category:"Update",description:"Applies an attractor force to the particle, pulling it toward a point.",inputs:[{name:"particle",type:"Particle"},{name:"attractor",type:"Vector3",isOptional:!0},{name:"strength",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"Particle"}]},AlignAngleBlock:{className:"AlignAngleBlock",category:"Update",description:"Aligns the angle of a particle to its direction vector.",inputs:[{name:"particle",type:"Particle"}],outputs:[{name:"output",type:"Particle"}],properties:{alignment:"number \u2014 alignment offset in radians. Default: PI/2"},defaultSerializedProperties:{alignment:Math.PI/2}},ParticleTriggerBlock:{className:"ParticleTriggerBlock",category:"Trigger",description:"Triggers sub-emitters or other systems based on particle events. Connects particle flow to a system for spawning sub-particles.",inputs:[{name:"input",type:"Particle"},{name:"condition",type:"Float",isOptional:!0},{name:"system",type:"System"}],outputs:[{name:"output",type:"Particle"}]},ParticleMathBlock:{className:"ParticleMathBlock",category:"Math",description:"Applies standard math operations (Add, Subtract, Multiply, Divide, Max, Min) to two inputs.",inputs:[{name:"left",type:"AutoDetect"},{name:"right",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{operation:"ParticleMathBlockOperations \u2014 Add (0), Subtract (1), Multiply (2), Divide (3), Max (4), Min (5). Default: Add"},defaultSerializedProperties:{operation:0}},ParticleNumberMathBlock:{className:"ParticleNumberMathBlock",category:"Math",description:"Applies number-only math (Modulo, Pow) to two numeric inputs.",inputs:[{name:"left",type:"AutoDetect"},{name:"right",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{operation:"ParticleNumberMathBlockOperations \u2014 Modulo (0), Pow (1). Default: Modulo"},defaultSerializedProperties:{operation:0}},ParticleVectorMathBlock:{className:"ParticleVectorMathBlock",category:"Math",description:"Applies vector-only math (Dot, Distance) to two Vector3 inputs.",inputs:[{name:"left",type:"Vector3"},{name:"right",type:"Vector3"}],outputs:[{name:"output",type:"Float"}],properties:{operation:"ParticleVectorMathBlockOperations \u2014 Dot (0), Distance (1). Default: Dot"},defaultSerializedProperties:{operation:0}},ParticleTrigonometryBlock:{className:"ParticleTrigonometryBlock",category:"Math",description:"Applies trigonometric/scientific operations (Cos, Sin, Abs, Exp, Exp2, Round, Floor, Ceiling, Sqrt, Log, Tan, ArcTan, ArcCos, ArcSin, Sign, Negate, OneMinus, Reciprocal, ToDegrees, ToRadians, Fract).",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{operation:"ParticleTrigonometryBlockOperations \u2014 Cos (0), Sin (1), Abs (2), Exp (3), Exp2 (4), Round (5), Floor (6), Ceiling (7), Sqrt (8), Log (9), Tan (10), ArcTan (11), ArcCos (12), ArcSin (13), Sign (14), Negate (15), OneMinus (16), Reciprocal (17), ToDegrees (18), ToRadians (19), Fract (20). Default: Cos"},defaultSerializedProperties:{operation:0}},ParticleVectorLengthBlock:{className:"ParticleVectorLengthBlock",category:"Math",description:"Computes the length of a vector input.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"Float"}]},ParticleFloatToIntBlock:{className:"ParticleFloatToIntBlock",category:"Math",description:"Converts a float to an int using Round, Ceil, Floor, or Truncate.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"Int"}],properties:{operation:"ParticleFloatToIntBlockOperations \u2014 Round (0), Ceil (1), Floor (2), Truncate (3). Default: Round"},defaultSerializedProperties:{operation:0}},ParticleConditionBlock:{className:"ParticleConditionBlock",category:"Condition",description:"Evaluates a condition (Equal, NotEqual, LessThan, GreaterThan, etc.) and returns ifTrue or ifFalse value.",inputs:[{name:"left",type:"Float"},{name:"right",type:"Float",isOptional:!0},{name:"ifTrue",type:"AutoDetect",isOptional:!0},{name:"ifFalse",type:"AutoDetect",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{test:"ParticleConditionBlockTests \u2014 Equal (0), NotEqual (1), LessThan (2), GreaterThan (3), LessOrEqual (4), GreaterOrEqual (5), Xor (6), Or (7), And (8). Default: Equal",epsilon:"number \u2014 epsilon for comparison. Default: 0"},defaultSerializedProperties:{test:0,epsilon:0}},ParticleLerpBlock:{className:"ParticleLerpBlock",category:"Interpolation",description:"Linearly interpolates between two values based on a gradient.",inputs:[{name:"left",type:"AutoDetect"},{name:"right",type:"AutoDetect"},{name:"gradient",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleNLerpBlock:{className:"ParticleNLerpBlock",category:"Interpolation",description:"Normalised linear interpolation between two values.",inputs:[{name:"left",type:"AutoDetect"},{name:"right",type:"AutoDetect"},{name:"gradient",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleSmoothStepBlock:{className:"ParticleSmoothStepBlock",category:"Interpolation",description:"Smooth step interpolation between two edges.",inputs:[{name:"value",type:"AutoDetect"},{name:"edge0",type:"Float",isOptional:!0},{name:"edge1",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleStepBlock:{className:"ParticleStepBlock",category:"Interpolation",description:"Step function: returns 0 if value < edge, else 1.",inputs:[{name:"value",type:"AutoDetect"},{name:"edge",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleClampBlock:{className:"ParticleClampBlock",category:"Interpolation",description:"Clamps a value between min and max.",inputs:[{name:"value",type:"AutoDetect"},{name:"min",type:"Float",isOptional:!0},{name:"max",type:"Float",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleGradientBlock:{className:"ParticleGradientBlock",category:"Interpolation",description:"Defines a multi-stop gradient. Dynamically extends with more value inputs as needed.",inputs:[{name:"gradient",type:"Float",isOptional:!0},{name:"value0",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleGradientValueBlock:{className:"ParticleGradientValueBlock",category:"Interpolation",description:"Defines a single gradient entry with a reference position (0-1).",inputs:[{name:"value",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{reference:"number \u2014 gradient position 0\u20131. Default: 0"},defaultSerializedProperties:{reference:0}},ParticleRandomBlock:{className:"ParticleRandomBlock",category:"Misc",description:"Generates a random value between min and max.",inputs:[{name:"min",type:"AutoDetect",isOptional:!0},{name:"max",type:"AutoDetect",isOptional:!0}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{lockMode:"ParticleRandomBlockLocks \u2014 None (0), PerParticle (1), PerSystem (2), OncePerParticle (3). Default: PerParticle"},defaultSerializedProperties:{lockMode:1}},ParticleConverterBlock:{className:"ParticleConverterBlock",category:"Converter",description:"Converts between Color4/Vector3/Vector2/Float components. NOTE: Input port names have a TRAILING SPACE to disambiguate from outputs. When connecting to inputs, use 'color ', 'xyz ', 'xy ', 'zw ', 'x ', 'y ', 'z ', 'w ' (with trailing space).",inputs:[{name:"color ",type:"Color4",isOptional:!0},{name:"xyz ",type:"Vector3",isOptional:!0},{name:"xy ",type:"Vector2",isOptional:!0},{name:"zw ",type:"Vector2",isOptional:!0},{name:"x ",type:"Float",isOptional:!0},{name:"y ",type:"Float",isOptional:!0},{name:"z ",type:"Float",isOptional:!0},{name:"w ",type:"Float",isOptional:!0}],outputs:[{name:"color",type:"Color4"},{name:"xyz",type:"Vector3"},{name:"xy",type:"Vector2"},{name:"zw",type:"Vector2"},{name:"x",type:"Float"},{name:"y",type:"Float"},{name:"z",type:"Float"},{name:"w",type:"Float"}]},ParticleDebugBlock:{className:"ParticleDebugBlock",category:"Utility",description:"Debug block that passes through its input and can log values.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleElbowBlock:{className:"ParticleElbowBlock",category:"Utility",description:"Pass-through block used for visual routing in the editor.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}]},ParticleLocalVariableBlock:{className:"ParticleLocalVariableBlock",category:"Utility",description:"Stores a local variable scoped to a particle or loop iteration.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[{name:"output",type:"BasedOnInput"}],properties:{scope:"ParticleLocalVariableBlockScope \u2014 Particle (0), Loop (1). Default: Particle"},defaultSerializedProperties:{scope:0}},ParticleTeleportInBlock:{className:"ParticleTeleportInBlock",category:"Teleport",description:"Entry point for a teleport pair. Accepts any input and teleports it to a matching TeleportOut.",inputs:[{name:"input",type:"AutoDetect"}],outputs:[]},ParticleTeleportOutBlock:{className:"ParticleTeleportOutBlock",category:"Teleport",description:"Exit point for a teleport pair. Outputs the value received from a matching TeleportIn.",inputs:[],outputs:[{name:"output",type:"BasedOnInput"}]}};function S$(){const e=new Map;for(const[r,o]of Object.entries(Rn))e.has(o.category)||e.set(o.category,[]),e.get(o.category).push(` ${r}: ${o.description.split(".")[0]}`);const t=[];for(const[r,o]of e)t.push(`
92
92
  ## ${r}`),t.push(...o);return t.join(`
93
93
  `)}function tT(e){return Rn[e]}const me={Int:1,Float:2,Vector2:4,Vector3:8,Matrix:16,Particle:32,Texture:64,Color4:128,FloatGradient:256,Vector2Gradient:512,Vector3Gradient:1024,Color4Gradient:2048,System:4096,AutoDetect:8192,BasedOnInput:16384,Undefined:32768},Se={None:0,Position:1,Direction:2,Age:3,Lifetime:4,Color:5,ScaledDirection:6,Scale:7,AgeGradient:8,Angle:9,SpriteCellIndex:16,SpriteCellStart:17,SpriteCellEnd:18,InitialColor:19,ColorDead:20,InitialDirection:21,ColorStep:22,ScaledColorStep:23,LocalPositionUpdated:24,Size:25,DirectionScale:32},ct={None:0,Time:1,Delta:2,Emitter:3,CameraPosition:4},la={[Se.None]:me.AutoDetect,[Se.Position]:me.Vector3,[Se.Direction]:me.Vector3,[Se.ScaledDirection]:me.Vector3,[Se.InitialDirection]:me.Vector3,[Se.LocalPositionUpdated]:me.Vector3,[Se.Color]:me.Color4,[Se.InitialColor]:me.Color4,[Se.ColorDead]:me.Color4,[Se.ColorStep]:me.Color4,[Se.ScaledColorStep]:me.Color4,[Se.Scale]:me.Vector2,[Se.Age]:me.Float,[Se.Lifetime]:me.Float,[Se.Angle]:me.Float,[Se.AgeGradient]:me.Float,[Se.Size]:me.Float,[Se.DirectionScale]:me.Float,[Se.SpriteCellIndex]:me.Int,[Se.SpriteCellStart]:me.Int,[Se.SpriteCellEnd]:me.Int},da={[ct.None]:me.AutoDetect,[ct.Time]:me.Float,[ct.Delta]:me.Float,[ct.Emitter]:me.Vector3,[ct.CameraPosition]:me.Vector3},nT={Add:0,Subtract:1,Multiply:2,Divide:3,Max:4,Min:5},rT={Cos:0,Sin:1,Abs:2,Exp:3,Exp2:4,Round:5,Floor:6,Ceiling:7,Sqrt:8,Log:9,Tan:10,ArcTan:11,ArcCos:12,ArcSin:13,Sign:14,Negate:15,OneMinus:16,Reciprocal:17,ToDegrees:18,ToRadians:19,Fract:20},iT={Equal:0,NotEqual:1,LessThan:2,GreaterThan:3,LessOrEqual:4,GreaterOrEqual:5,Xor:6,Or:7,And:8},oT={Modulo:0,Pow:1},aT={Dot:0,Distance:1},sT={Round:0,Ceil:1,Floor:2,Truncate:3},cT={None:0,PerParticle:1,PerSystem:2,OncePerParticle:3},uT={Particle:0,Loop:1},Zr={ParticleMathBlock:{operation:nT},ParticleTrigonometryBlock:{operation:rT},ParticleConditionBlock:{test:iT},ParticleNumberMathBlock:{operation:oT},ParticleVectorMathBlock:{operation:aT},ParticleFloatToIntBlock:{operation:sT},ParticleRandomBlock:{lockMode:cT},ParticleLocalVariableBlock:{scope:uT}};class fa{_particleSets=new Map;_nextId=new Map;_nextX=new Map;createParticleSet(t,r){const o={customType:"BABYLON.NodeParticleSystemSet",blocks:[],comment:r,name:t};return this._particleSets.set(t,o),this._nextId.set(t,1),this._nextX.set(t,0),o}getParticleSet(t){return this._particleSets.get(t)}listParticleSets(){return Array.from(this._particleSets.keys())}deleteParticleSet(t){return this._nextId.delete(t),this._nextX.delete(t),this._particleSets.delete(t)}clearAll(){this._particleSets.clear(),this._nextId.clear(),this._nextX.clear()}addBlock(t,r,o,n){const i=this._particleSets.get(t);if(!i)return`Particle set "${t}" not found. Create it first.`;const a=Rn[r];if(!a)return`Unknown block type "${r}". Use list_block_types to see available blocks.`;const s=[],c=this._nextId.get(t);this._nextId.set(t,c+1);const u=o??`${r}_${c}`,l={customType:`BABYLON.${a.className}`,id:c,name:u,inputs:a.inputs.map(m=>({name:m.name,displayName:m.name})),outputs:a.outputs.map(m=>({name:m.name,displayName:m.name}))};if(r==="ParticleInputBlock"&&(l.type=me.Float,l.contextualValue=Se.None,l.systemSource=ct.None,l.min=0,l.max=0,l.groupInInspector="",l.displayInInspector=!0),a.defaultSerializedProperties)for(const[m,f]of Object.entries(a.defaultSerializedProperties))l[m]=f;if(n)for(const[m,f]of Object.entries(n))if(r==="ParticleInputBlock"&&m==="type"&&typeof f=="string")l.type=me[f]??f;else if(r==="ParticleInputBlock"&&m==="contextualValue"&&typeof f=="string"){const g=Se[f]??f;l.contextualValue=g,l.systemSource=ct.None,typeof g=="number"&&g!==Se.None&&la[g]!==void 0&&(l.type=la[g])}else if(r==="ParticleInputBlock"&&m==="systemSource"&&typeof f=="string"){const g=ct[f]??f;l.systemSource=g,l.contextualValue=Se.None,typeof g=="number"&&g!==ct.None&&da[g]!==void 0&&(l.type=da[g])}else typeof f=="string"&&Zr[r]?.[m]?l[m]=Zr[r][m][f]??f:l[m]=f;if(r==="ParticleInputBlock"){const m=l.contextualValue,f=l.systemSource,g=l.value!==void 0&&l.value!==null;m===Se.None&&f===ct.None&&!g&&s.push(`\u26A0 ParticleInputBlock "${l.name}" has contextualValue=None, systemSource=None, and no value. Set a contextualValue (e.g. 'Position', 'Age'), a systemSource (e.g. 'Time', 'Delta'), or provide a constant value.`),this._normaliseInputBlockValue(l),this._ensureDefaultValue(l)}const d=this._nextX.get(t);return this._nextX.set(t,d+280),i.editorData||(i.editorData={locations:[]}),i.editorData.locations.push({blockId:c,x:d,y:0}),i.blocks.push(l),{block:l,warnings:s.length>0?s:void 0}}_normaliseInputBlockValue(t){const r=t.value;if(r==null)return;const o=t.type;if(typeof r=="number"){if(o===me.Matrix){t.value=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],t.valueType="BABYLON.Matrix";return}t.valueType="number";return}if(Array.isArray(r)){t.valueType||(t.valueType=this._inferValueType(o,r.length));return}if(typeof r=="object"){const n=r;"r"in n?(t.value=[n.r,n.g,n.b,n.a??1],t.valueType="BABYLON.Color4"):"x"in n&&("w"in n?(t.value=[n.x,n.y,n.z,n.w],t.valueType="BABYLON.Color4"):"z"in n?(t.value=[n.x,n.y,n.z],t.valueType="BABYLON.Vector3"):(t.value=[n.x,n.y],t.valueType="BABYLON.Vector2"))}}_inferValueType(t,r){const o={[me.Vector2]:"BABYLON.Vector2",[me.Vector3]:"BABYLON.Vector3",[me.Color4]:"BABYLON.Color4",[me.Matrix]:"BABYLON.Matrix"};return t!==void 0&&o[t]?o[t]:{2:"BABYLON.Vector2",3:"BABYLON.Vector3",4:"BABYLON.Color4",16:"BABYLON.Matrix"}[r]??"BABYLON.Vector3"}_ensureDefaultValue(t){if(t.value!==void 0&&t.value!==null)return;const r=t.contextualValue;if(r!==void 0&&r!==Se.None)return;const o=t.systemSource;if(o!==void 0&&o!==ct.None)return;const n=t.type;if(n===void 0)return;const a={[me.Float]:{value:0,valueType:"number"},[me.Int]:{value:0,valueType:"number"},[me.Vector2]:{value:[0,0],valueType:"BABYLON.Vector2"},[me.Vector3]:{value:[0,0,0],valueType:"BABYLON.Vector3"},[me.Color4]:{value:[1,1,1,1],valueType:"BABYLON.Color4"},[me.Matrix]:{value:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],valueType:"BABYLON.Matrix"}}[n];a&&(t.value=a.value,t.valueType=a.valueType)}removeBlock(t,r){const o=this._particleSets.get(t);if(!o)return`Particle set "${t}" not found.`;const n=o.blocks.findIndex(i=>i.id===r);if(n===-1)return`Block ${r} not found.`;for(const i of o.blocks)for(const a of i.inputs)a.targetBlockId===r&&(delete a.targetBlockId,delete a.targetConnectionName);return o.blocks.splice(n,1),o.editorData&&(o.editorData.locations=o.editorData.locations.filter(i=>i.blockId!==r)),"OK"}connectBlocks(t,r,o,n,i){const a=this._particleSets.get(t);if(!a)return`Particle set "${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.`;if(!s.outputs.find(d=>d.name===o)){const d=s.outputs.map(m=>m.name).join(", ");return`Output "${o}" not found on block ${r} ("${s.name}"). Available: ${d}`}const l=c.inputs.find(d=>d.name===i);if(!l){const d=c.inputs.map(m=>m.name).join(", ");return`Input "${i}" not found on block ${n} ("${c.name}"). Available: ${d}`}return l.inputName=l.name,l.targetBlockId=r,l.targetConnectionName=o,"OK"}disconnectInput(t,r,o){const n=this._particleSets.get(t);if(!n)return`Particle set "${t}" not found.`;const i=n.blocks.find(s=>s.id===r);if(!i)return`Block ${r} not found.`;const a=i.inputs.find(s=>s.name===o);return a?(delete a.inputName,delete a.targetBlockId,delete a.targetConnectionName,"OK"):`Input "${o}" not found.`}describeParticleSet(t){const r=this._particleSets.get(t);if(!r)return`Particle set "${t}" not found.`;const o=[];o.push(`Particle Set: ${t}`),o.push(`Blocks (${r.blocks.length}):`);for(const i of r.blocks){const a=i.customType.replace("BABYLON.","");if(o.push(` [${i.id}] ${i.name} (${a})`),i.inputs.length>0){for(const s of i.inputs)if(s.targetBlockId!==void 0){const c=r.blocks.find(u=>u.id===s.targetBlockId);o.push(` \u2190 ${s.name} \u2190 [${s.targetBlockId}] ${c?.name??"?"}.${s.targetConnectionName}`)}}}const n=r.blocks.filter(i=>i.customType==="BABYLON.SystemBlock");return o.push(`System blocks: ${n.length>0?n.map(i=>`[${i.id}]`).join(", "):"(none)"}`),r.comment&&o.push(`Comment: ${r.comment}`),o.join(`
94
94
  `)}describeBlock(t,r){const o=this._particleSets.get(t);if(!o)return`Particle set "${t}" not found.`;const n=o.blocks.find(u=>u.id===r);if(!n)return`Block ${r} not found.`;const i=n.customType.replace("BABYLON.",""),a=[];a.push(`Block [${n.id}]: "${n.name}" \u2014 type ${i}`),a.push(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babylonjs/mcp-servers",
3
- "version": "9.31.3",
3
+ "version": "9.32.1",
4
4
  "description": "Bundled Model Context Protocol servers for Babylon.js authoring workflows",
5
5
  "type": "module",
6
6
  "bin": {