@hology/core 0.0.205 → 0.0.207

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.
Files changed (52) hide show
  1. package/dist/config/project-config.d.ts +4 -0
  2. package/dist/effects/sequence/sequence-data.d.ts +8 -3
  3. package/dist/effects/sequence/sequence-data.js +1 -1
  4. package/dist/effects/sequence/sequence-definitions.js +1 -1
  5. package/dist/effects/sequence/sequence-player.d.ts +2 -0
  6. package/dist/effects/sequence/sequence-player.js +1 -1
  7. package/dist/effects/sequence/sequence-value-lane.js +1 -1
  8. package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
  9. package/dist/gameplay/actors/factory.d.ts +1 -0
  10. package/dist/gameplay/actors/factory.js +1 -1
  11. package/dist/gameplay/actors/internal/component-init.d.ts +1 -0
  12. package/dist/gameplay/actors/internal/component-init.js +1 -1
  13. package/dist/gameplay/animation/anim-sm.d.ts +2 -0
  14. package/dist/gameplay/animation/anim-sm.js +1 -1
  15. package/dist/gameplay/index.d.ts +1 -0
  16. package/dist/gameplay/index.js +1 -1
  17. package/dist/gameplay/initiate.d.ts +4 -0
  18. package/dist/gameplay/services/asset-loader.d.ts +3 -0
  19. package/dist/gameplay/services/asset-loader.js +1 -1
  20. package/dist/gameplay/services/world.js +1 -1
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.js +1 -1
  23. package/dist/rendering.d.ts +4 -0
  24. package/dist/rendering.js +1 -1
  25. package/dist/scene/custom-param-deserialize.d.ts +1 -0
  26. package/dist/scene/custom-param-deserialize.js +1 -1
  27. package/dist/scene/custom-param-runtime-types.d.ts +3 -1
  28. package/dist/scene/custom-param-runtime-types.js +1 -1
  29. package/dist/scene/materializer.d.ts +12 -1
  30. package/dist/scene/materializer.js +1 -1
  31. package/dist/scene/model.d.ts +18 -2
  32. package/dist/scene/model.js +1 -1
  33. package/dist/scene/objects/data-asset.d.ts +10 -0
  34. package/dist/scene/objects/data-asset.js +4 -0
  35. package/dist/scene/storage/storage.d.ts +1 -0
  36. package/dist/scene/storage/storage.js +1 -1
  37. package/dist/shader/graph/compiler.js +1 -1
  38. package/dist/shader/parameter.d.ts +64 -3
  39. package/dist/shader/parameter.js +1 -1
  40. package/dist/test/data-asset-definition.test.d.ts +2 -0
  41. package/dist/test/data-asset-definition.test.js +4 -0
  42. package/dist/test/parameter-definition.test.d.ts +2 -0
  43. package/dist/test/parameter-definition.test.js +4 -0
  44. package/dist/test/sequence-property-parameters.test.js +1 -1
  45. package/dist/test/sequence-vfx.test.d.ts +2 -0
  46. package/dist/test/sequence-vfx.test.js +4 -0
  47. package/dist/test/storage-case-collision.test.js +1 -1
  48. package/dist/test/world-lifecycle.test.d.ts +2 -0
  49. package/dist/test/world-lifecycle.test.js +4 -0
  50. package/dist/utils/type.d.ts +1 -1
  51. package/package.json +1 -1
  52. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import{BackSide as t,Color as e,DoubleSide as a,FrontSide as r,Matrix4 as u,Texture as i,Vector2 as o,Vector3 as n,Vector4 as s}from"three";import{BooleanNode as l,FloatNode as p,Mat4Node as c,NodeShaderMaterial as h,RgbNode as v,RgbaNode as y,Sampler2DNode as m,Texture2dLookupNode as d,UniformFloatNode as f,Vec2Node as g,Vec3Node as b,Vec4Node as x,abs as w,acos as T,asin as I,attributes as S,atan as O,atan2 as M,autoVarying as C,bulge as N,bool as E,ceil as G,clamp as U,colorToNormal as B,cos as $,cross as z,degrees as V,distance as k,dot as P,exp as A,exp2 as j,float as D,floor as L,fract as q,inversesqrt as F,batchingMatrix as R,colorGradientSampler as _,curveSampler as W,ifDefApply as H,sampleNamedEasingCurve as Y,length as J,LayerMixMode as K,log as Q,log2 as X,mat4 as Z,max as tt,min as et,mix as at,mixColorsByLayer as rt,particleUniforms as ut,mod as it,normalize as ot,pow as nt,radians as st,rgba as lt,rgb as pt,saturate as ct,select as ht,sign as vt,sin as yt,smoothstep as mt,sqrt as dt,standardMaterial as ft,scaleTransform as gt,step as bt,tan as xt,textureSampler2d as wt,timeUniforms as Tt,toonMaterial as It,translate as St,transformed as Ot,triplanarMapping as Mt,twirl as Ct,uniformFloat as Nt,uniforms as Et,varyingAttributes as Gt,vec2 as Ut,vec3 as Bt,vec4 as $t,getPaintedMaterialLayerWeight as zt}from"../../shader-nodes/index.js";import{SpriteNodeShaderMaterial as Vt,getSpritePosition as kt}from"../sprite-shader.js";import{oneMinus as Pt}from"../../shader-nodes/index.js";import{vectorToRadial as At,remap as jt,hueShift as Dt,blendColor as Lt,desaturateColor as qt}from"../../shader-nodes/math.js";import{rectangleFloat as Ft,roundedRectangleFloat as Rt}from"../../shader-nodes/shapes.js";import{edgeDepthEffect as _t,fresnelEffect as Wt,depthFadeEffect as Ht}from"../../shader-nodes/effects.js";import{fragmentLinearEyeDepth as Yt,sampleSceneDepth as Jt,sampleSceneLinearEyeDepth as Kt,screenUV as Qt,nearUniformName as Xt,farUniformName as Zt}from"../../shader-nodes/depth.js";import{sampleSceneColor as te}from"../../shader-nodes/scene-sample.js";import{decalDiscard as ee,decalUV as ae}from"../../shader-nodes/decal.js";import{Trail as re,trailUV as ue}from"../../effects/vfx/trail-renderer.js";import{SimplexNoiseNode as ie,Voronoi2d as oe,rotateAxis as ne}from"../../shader-nodes/index.js";import{flipbookUv as se}from"../../shader-nodes/texture-sequence.js";import{parallaxOcclusionMapping as le}from"../../shader-nodes/pom.js";import{defaultInlineLiteralValueForPort as pe,inlineLiteralTypeForPort as ce,SHADER_GRAPH_NODE_DEFINITIONS as he}from"./registry.js";import{shaderGraphParameterTypeToValueType as ve}from"./parameters.js";import{varying as ye,reflect as me,refract as de,dFdx as fe,dFdy as ge,fwidth as be}from"three-shader-graph";import{decalNormal as xe}from"../../shader-nodes/decal.js";import{Curve2 as we}from"../../utils/curve.js";export class ShaderGraphCompileError extends Error{constructor(t,e,a){super(t),this.nodeId=e,this.port=a,this.name="ShaderGraphCompileError"}}export const shaderGraphPostProcessWeightUniformName="hology_post_process_weight";export class ShaderGraphCompiler{constructor(t,e={}){this.graph=t,this.options=e,this.compiled=new Map,this.nodesById=new Map((t.nodes??[]).map(t=>[t.id,t]))}validate(){this.compile()}compile(){if(1!==this.graph.version)throw new ShaderGraphCompileError(`Unsupported shader graph version ${this.graph.version}`);return this.validateEdges(),{output:this.compileOutput(),nodes:this.compiled}}validateEdges(){for(const t of this.graph.edges??[]){if(!this.nodesById.has(t.from.nodeId))throw new ShaderGraphCompileError(`Edge references missing source node "${t.from.nodeId}"`,t.from.nodeId,t.from.port);if(!this.nodesById.has(t.to.nodeId))throw new ShaderGraphCompileError(`Edge references missing target node "${t.to.nodeId}"`,t.to.nodeId,t.to.port)}}compileOutput(){if("postProcess"===this.graph.target)return this.compilePostProcessOutput();const t=this.graph.outputs?.color,e={color:null!=t?this.toColorOutput(this.resolveOutputBinding(t,"color")):lt("#ffffff",1),transparent:Ie(this.graph)},a=this.graph.outputs?.opacity;null!=a&&(e.opacity=this.expectType(this.resolveOutputBinding(a,"opacity"),["float"],"opacity").value);const r=this.graph.outputs?.roughness;null!=r&&(e.roughness=this.expectType(this.resolveOutputBinding(r,"roughness"),["float"],"roughness").value);const u=this.graph.outputs?.metalness;null!=u&&(e.metalness=this.floatOutput(u,"metalness"));const i=this.graph.outputs?.normal;null!=i&&(e.normal=this.toVec3Output(this.resolveOutputBinding(i,"normal"),"normal"));const o=this.graph.outputs?.emissive;null!=o&&(e.emissive=this.toVec3Output(this.resolveOutputBinding(o,"emissive"),"emissive"));const n=this.graph.outputs?.ambientOcclusion;null!=n&&(e.ambientOcclusion=this.floatOutput(n,"ambientOcclusion"));const s=this.graph.outputs?.ambientOcclusionIntensity;null!=s&&(e.ambientOcclusionIntensity=this.floatOutput(s,"ambientOcclusionIntensity"));const l=this.graph.outputs?.sheenColor;null!=l&&(e.sheenColor=this.toVec3Output(this.resolveOutputBinding(l,"sheenColor"),"sheenColor"));const p=this.graph.outputs?.sheenRoughness;null!=p&&(e.sheenRoughness=this.floatOutput(p,"sheenRoughness"));const c=this.graph.outputs?.anisotropy;null!=c&&(e.anisotropy=this.floatOutput(c,"anisotropy"));const h=this.graph.outputs?.anisotropyDirection;null!=h&&(e.anisotropyDirection=this.expectType(this.resolveOutputBinding(h,"anisotropyDirection"),["vec2"],"anisotropyDirection").value);const v=this.graph.outputs?.bakedLight;null!=v&&(e.bakedLight=this.toVec3Output(this.resolveOutputBinding(v,"bakedLight"),"bakedLight"));const y=this.graph.outputs?.transform;null!=y&&"decal"!==this.graph.target&&(e.transform=this.toMat4Output(this.resolveOutputBinding(y,"transform"),"transform"));const m=this.graph.outputs?.discard;null!=m&&(e.discard=this.expectType(this.resolveOutputBinding(m,"discard"),["boolean"],"discard").value);const d=this.graph.outputs?.transparent;null!=d&&null!=d.value&&(e.transparent=Boolean(d.value));const f=this.graph.outputs?.alphaTest;return null!=f&&null!=f.value&&(e.alphaTest=Number(f.value)),this.applyShadingModel(e)}compilePostProcessOutput(){const t=this.graph.outputs?.color,e=null!=t?this.toColorOutput(this.resolveOutputBinding(t,"color")):te(Qt),a=this.graph.outputs?.opacity;return Te(e,null!=a?this.expectType(this.resolveOutputBinding(a,"opacity"),["float"],"opacity").value:void 0)}applyShadingModel(t){const e=null!=t.opacity?function(t,e){if(t instanceof p)return lt(Bt(t,t,t),e);if(t instanceof g)return lt(Bt(t.x,t.y,0),e);if(t instanceof x)return lt(t.rgb,t.w.multiply(e));return lt(t,e)}(t.color,t.opacity):t.color;switch(this.graph.shadingModel??"standard"){case"standard":{const a={color:Ce(e),roughness:t.roughness??D(.5),...null!=t.metalness?{metalness:t.metalness}:{},..."decal"===this.graph.target?{normal:ot(ye(Et.normalMatrix).multiplyVec(xe))}:{},...null!=t.normal?{normal:t.normal}:{},...null!=t.emissive?{emissive:Ne(t.emissive)}:{},...null!=t.ambientOcclusion?{ambientOcclusion:t.ambientOcclusion}:{},...null!=t.ambientOcclusionIntensity?{ambientOcclusionIntensity:t.ambientOcclusionIntensity}:{},...null!=t.sheenColor?{sheenColor:t.sheenColor.rgb}:{},...null!=t.sheenRoughness?{sheenRoughness:t.sheenRoughness}:{},...null!=t.anisotropy?{anisotropy:t.anisotropy}:{},...null!=t.anisotropyDirection?{anisotropyDirection:t.anisotropyDirection}:{},...null!=t.bakedLight?{bakedLight:t.bakedLight}:{}};return{...t,color:ft(a)}}case"toon":{const a={color:Ce(e),...null!=t.normal?{normal:t.normal}:{},...null!=t.emissive?{emissive:Ne(t.emissive)}:{},...null!=t.ambientOcclusion?{ambientOcclusion:t.ambientOcclusion}:{},...null!=t.ambientOcclusionIntensity?{ambientOcclusionIntensity:t.ambientOcclusionIntensity}:{},...null!=t.bakedLight?{bakedLight:t.bakedLight}:{}};return{...t,color:It(a)}}case"unlit":return{...t,color:e}}}compileNode(t){const e=this.compiled.get(t);if(null!=e)return e;const a=this.nodesById.get(t);if(null==a)throw new ShaderGraphCompileError(`Missing shader graph node "${t}"`,t);if(null==he[a.kind])throw new ShaderGraphCompileError(`Unsupported shader graph node "${a.kind}"`,a.id);const r=this.compileNodeInternal(a);return this.compiled.set(t,r),r}compileNodeInternal(t){switch(t.kind){case"input.parameter":return this.output(t,this.compileParameterNode(t));case"input.slider":return this.output(t,{value:{type:"float",value:D(Ae(Ge(t,"value",.5)))}});case"constant.boolean":return this.output(t,{value:{type:"boolean",value:E(Boolean(Ee(t,"value",!1)))}});case"constant.float":return this.output(t,{value:{type:"float",value:D(Ge(t,"value",0))}});case"constant.vec2":return this.output(t,{value:{type:"vec2",value:Le(Ee(t,"value",[0,0]))}});case"constant.vec3":return this.output(t,{value:{type:"vec3",value:qe(Ee(t,"value",[0,0,0]))}});case"constant.rgba":return this.output(t,{value:{type:"rgba",value:Fe(Ee(t,"value","#ffffff"),Ge(t,"alpha",1))}});case"builtin.uv":{const e=this.defaultUV();return this.output(t,{value:{type:"vec2",value:!0===Ee(t,"flipY",!1)?Ut(e.x,Pt(e.y)):e},u:{type:"float",value:e.x},v:{type:"float",value:e.y}})}case"builtin.screenUv":return this.output(t,{value:{type:"vec2",value:Qt}});case"builtin.color":{const e=C(S.color);return this.output(t,{value:{type:"rgba",value:e},rgb:{type:"rgb",value:e.rgb},r:{type:"float",value:e.r},g:{type:"float",value:e.g},b:{type:"float",value:e.b},a:{type:"float",value:e.a}})}case"builtin.position":{const e=C(S.position);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.worldPosition":{const e=C(Ot.worldPosition);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.objectPosition":{let e=Et.instanceMatrix.multiplyVec($t(0,0,0,1));e=H("USE_BATCHING",e,t=>R.multiplyVec(t));const a=C(Et.modelMatrix.multiplyVec(e).xyz);return this.output(t,{value:{type:"vec3",value:a},x:{type:"float",value:a.x},y:{type:"float",value:a.y},z:{type:"float",value:a.z}})}case"builtin.viewDir":{const e=C(Ot.viewDir);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.normal":{const e=C(S.normal);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.time":return this.output(t,{value:{type:"float",value:Tt.elapsed}});case"builtin.camera":{const e=Nt(Xt),a=Nt(Zt),r=Et.cameraPosition;return this.output(t,{position:{type:"vec3",value:r},x:{type:"float",value:r.x},y:{type:"float",value:r.y},z:{type:"float",value:r.z},near:{type:"float",value:e},far:{type:"float",value:a}})}case"builtin.viewMatrix":return this.output(t,{value:{type:"mat4",value:Et.viewMatrix}});case"builtin.projectionMatrix":return this.output(t,{value:{type:"mat4",value:Et.projectionMatrix}});case"builtin.modelViewMatrix":return this.output(t,{value:{type:"mat4",value:Et.modelViewMatrix}});case"builtin.particle":return this.output(t,{energy:{type:"float",value:ut.energy},color:{type:"rgb",value:ut.color},opacity:{type:"float",value:ut.opacity},time:{type:"float",value:ut.time}});case"math.add":case"math.subtract":case"math.multiply":case"math.divide":return this.output(t,{value:this.compileBinaryMath(t)});case"math.oneMinus":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:e.type,value:Pt(e.value)}})}case"math.abs":return this.output(t,{value:this.compileUnaryMath(t,w)});case"math.sign":return this.output(t,{value:this.compileUnaryMath(t,vt)});case"math.floor":return this.output(t,{value:this.compileUnaryMath(t,L)});case"math.ceil":return this.output(t,{value:this.compileUnaryMath(t,G)});case"math.fract":return this.output(t,{value:this.compileUnaryMath(t,q)});case"math.sin":return this.output(t,{value:this.compileUnaryMath(t,yt)});case"math.cos":return this.output(t,{value:this.compileUnaryMath(t,$)});case"math.tan":return this.output(t,{value:this.compileUnaryMath(t,xt)});case"math.asin":return this.output(t,{value:this.compileUnaryMath(t,I)});case"math.acos":return this.output(t,{value:this.compileUnaryMath(t,T)});case"math.atan":return this.output(t,{value:this.compileUnaryMath(t,O)});case"math.atan2":return this.output(t,{value:this.compileAtan2(t)});case"math.radians":return this.output(t,{value:this.compileUnaryMath(t,st)});case"math.degrees":return this.output(t,{value:this.compileUnaryMath(t,V)});case"math.sqrt":return this.output(t,{value:this.compileUnaryMath(t,dt)});case"math.inverseSqrt":return this.output(t,{value:this.compileUnaryMath(t,F)});case"math.exp":return this.output(t,{value:this.compileUnaryMath(t,A)});case"math.exp2":return this.output(t,{value:this.compileUnaryMath(t,j)});case"math.log":return this.output(t,{value:this.compileUnaryMath(t,Q)});case"math.log2":return this.output(t,{value:this.compileUnaryMath(t,X)});case"math.saturate":return this.output(t,{value:this.compileUnaryMath(t,ct)});case"math.length":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:"float",value:J(e.value)}})}case"math.normalize":return this.output(t,{value:this.compileUnaryMath(t,ot)});case"math.clamp":{const e=this.expectNumeric(this.input(t,"value")),a=this.expectNumeric(this.input(t,"min",{type:"float",value:D(0)})),r=this.expectNumeric(this.input(t,"max",{type:"float",value:D(1)}));return this.output(t,{value:{type:e.type,value:U(e.value,a.value,r.value)}})}case"math.min":return this.output(t,{value:this.compileBinaryFunction(t,et)});case"math.max":return this.output(t,{value:this.compileBinaryFunction(t,tt)});case"math.pow":return this.output(t,{value:this.compileBinaryFunction(t,nt)});case"math.mod":return this.output(t,{value:this.compileBinaryFunction(t,it)});case"math.step":return this.output(t,{value:this.compileBinaryFunction(t,bt,!0)});case"math.smoothstep":{const e=this.expectNumeric(this.input(t,"edge0",{type:"float",value:D(0)})),a=this.expectNumeric(this.input(t,"edge1",{type:"float",value:D(1)})),r=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:r.type,value:mt(e.value,a.value,r.value)}})}case"math.mix":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b")),r=this.expectNumeric(this.input(t,"t",{type:"float",value:D(.5)})),u=ze(e.type,a.type,t.id);return this.output(t,{value:{type:u,value:at(e.value,a.value,r.value)}})}case"math.remap":{const e=this.expectType(this.input(t,"value"),["float"],t.id,"value").value,a=this.floatInput(t,"inMin",-1),r=this.floatInput(t,"inMax",1),u=this.floatInput(t,"outMin",0),i=this.floatInput(t,"outMax",1);return this.output(t,{value:{type:"float",value:jt(e,a,r,u,i)}})}case"math.select":{const e=this.boolInput(t,"condition",!1),a=this.expectNumeric(this.input(t,"a")),r=this.expectNumeric(this.input(t,"b")),u=ze(a.type,r.type,t.id);return this.output(t,{value:{type:u,value:ht(e,a.value,r.value)}})}case"math.reflect":{const e=this.expectType(this.input(t,"incident"),["vec2","vec3","vec4","rgb","rgba"],t.id,"incident"),a=this.expectType(this.input(t,"normal"),["vec2","vec3","vec4","rgb","rgba"],t.id,"normal");return this.output(t,{value:{type:e.type,value:me(e.value,a.value)}})}case"math.refract":{const e=this.expectType(this.input(t,"incident"),["vec2","vec3","vec4","rgb","rgba"],t.id,"incident"),a=this.expectType(this.input(t,"normal"),["vec2","vec3","vec4","rgb","rgba"],t.id,"normal"),r=this.floatInput(t,"ior",1.5);return this.output(t,{value:{type:e.type,value:de(e.value,a.value,r)}})}case"math.derivative":{const e=this.expectNumeric(this.input(t,"value")),a=String(Ee(t,"mode","fwidth"));let r;return r="dFdx"===a?fe(e.value):"dFdy"===a?ge(e.value):be(e.value),this.output(t,{value:{type:e.type,value:r}})}case"layer.mixPainted":return this.output(t,{value:this.compilePaintedLayerMix(t)});case"math.dot":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b"));return ze(e.type,a.type,t.id),this.output(t,{value:{type:"float",value:P(e.value,a.value)}})}case"math.distance":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b"));return ze(e.type,a.type,t.id),this.output(t,{value:{type:"float",value:k(e.value,a.value)}})}case"math.cross":{const e=this.expectType(this.input(t,"a"),["vec3","rgb"],t.id,"a"),a=this.expectType(this.input(t,"b"),["vec3","rgb"],t.id,"b");return this.output(t,{value:{type:"vec3",value:z(e.value,a.value)}})}case"compare.greaterThan":case"compare.greaterThanOrEqual":case"compare.lessThan":case"compare.lessThanOrEqual":case"compare.equal":case"compare.notEqual":return this.output(t,{value:{type:"boolean",value:this.compileComparison(t)}});case"boolean.not":{const e=this.boolInput(t,"value",!1);return this.output(t,{value:{type:"boolean",value:ht(e,E(!1),E(!0))}})}case"boolean.and":return this.output(t,{value:{type:"boolean",value:this.compileBooleanBinary(t,"and")}});case"boolean.or":return this.output(t,{value:{type:"boolean",value:this.compileBooleanBinary(t,"or")}});case"compose.vec2":return this.output(t,{value:{type:"vec2",value:Ut(this.floatInput(t,"x",0),this.floatInput(t,"y",0))}});case"compose.vec3":return this.output(t,{value:{type:"vec3",value:Bt(this.floatInput(t,"x",0),this.floatInput(t,"y",0),this.floatInput(t,"z",0))}});case"compose.vec4":return this.output(t,{value:{type:"vec4",value:$t(this.floatInput(t,"x",0),this.floatInput(t,"y",0),this.floatInput(t,"z",0),this.floatInput(t,"w",0))}});case"compose.rgba":return this.output(t,{value:{type:"rgba",value:$t(this.floatInput(t,"r",1),this.floatInput(t,"g",1),this.floatInput(t,"b",1),this.floatInput(t,"a",1))}});case"decompose.component":{const e=this.expectNumeric(this.input(t,"value")),a=String(Ee(t,"component","x"));return this.output(t,{value:{type:"float",value:ke(e,a,t.id)}})}case"decompose.split":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,function(t,e){const a={},r=(r,u)=>{a[r]={type:"float",value:ke(t,u,e)}};switch(t.type){case"vec2":return r("x","x"),r("y","y"),r("u","x"),r("v","y"),a;case"vec3":return r("x","x"),r("y","y"),r("z","z"),a;case"rgb":return r("r","r"),r("g","g"),r("b","b"),r("x","x"),r("y","y"),r("z","z"),a;case"vec4":return r("x","x"),r("y","y"),r("z","z"),r("w","w"),a;case"rgba":return r("r","r"),r("g","g"),r("b","b"),r("a","a"),r("x","x"),r("y","y"),r("z","z"),r("w","w"),a;case"float":return a.x={type:"float",value:t.value},a}}(e,t.id))}case"color.gradient":{const e=this.expectType(this.input(t,"t",{type:"float",value:D(.5)}),["float"],t.id,"t"),a=_(function(t){const e=Ee(t,"stops",[]);if(!Array.isArray(e))return[];const a=e.map((t,a)=>{if(null==t||"object"!=typeof t||Array.isArray(t))return;const r=t,u="string"==typeof r.color?r.color:"#ffffff";return{position:je(r.position,Re(a,e.length)),color:u,alpha:je(r.alpha,1)}}).filter(t=>null!=t);return a.length>0?a:[]}(t)).sample(e.value);return this.output(t,{value:{type:"rgba",value:a}})}case"utility.curve":{const e=this.expectType(this.input(t,"t",{type:"float",value:D(.5)}),["float"],t.id,"t"),a=Ee(t,"curve","Linear"),r=Y(a,e.value)??W(we.decode(a)).sample(e.value);return this.output(t,{value:{type:"float",value:r}})}case"color.hueShift":{const e=this.expectType(this.input(t,"color"),["rgba","rgb","vec4","vec3"],t.id,"color"),a=e.value,r="rgba"===e.type||"vec4"===e.type?a.rgb??a.xyz:a,u=this.floatInput(t,"shift",0),i=Dt(r,u);return"rgba"===e.type||"vec4"===e.type?this.output(t,{value:{type:e.type,value:$t(i,a.a??a.w)}}):this.output(t,{value:{type:e.type,value:i}})}case"color.blend":{const e=this.expectType(this.input(t,"base"),["rgba","rgb","vec4","vec3"],t.id,"base"),a=this.expectType(this.input(t,"blend"),["rgba","rgb","vec4","vec3"],t.id,"blend"),r=String(Ee(t,"mode","multiply")),u=e.value,i=a.value,o="rgba"===e.type||"vec4"===e.type?u.rgb??u.xyz:u,n="rgba"===a.type||"vec4"===a.type?i.rgb??i.xyz:i;let s=Lt(o,n,r);if("rgba"===a.type||"vec4"===a.type){const t=i.a??i.w;s=at(o,s,t)}if("rgba"===e.type||"vec4"===e.type){const a=u.a??u.w;return this.output(t,{value:{type:e.type,value:$t(s,a)}})}return this.output(t,{value:{type:e.type,value:s}})}case"color.desaturate":{const e=this.expectType(this.input(t,"color"),["rgba","rgb","vec4","vec3"],t.id,"color"),a=e.value,r="rgba"===e.type||"vec4"===e.type?a.rgb??a.xyz:a,u=this.floatInput(t,"fraction",1),i=qt(r,u);return"rgba"===e.type||"vec4"===e.type?this.output(t,{value:{type:e.type,value:$t(i,a.a??a.w)}}):this.output(t,{value:{type:e.type,value:i}})}case"color.unpackNormal":{const e=this.expectType(this.input(t,"color"),["vec3","vec4","rgb","rgba"],t.id,"color"),a=this.floatInput(t,"scale",1),r=this.optionalInput(t,"normal");return this.output(t,{value:{type:"vec3",value:B(e.value,a,r?this.expectType(r,["vec3"],t.id,"normal").value:void 0)}})}case"texture.sampler2d":{const e=this.input(t,"texture");return this.output(t,{value:this.toSampler(e,t.id)})}case"texture.sample2d":{const e=this.toSampler(this.input(t,"sampler"),t.id),a=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv"),r=e.value.sample(a.value);return this.output(t,{rgba:{type:"rgba",value:r},rgb:{type:"rgb",value:r.rgb},r:{type:"float",value:r.r},g:{type:"float",value:r.g},b:{type:"float",value:r.b},a:{type:"float",value:r.a}})}case"texture.triplanarMapping":{const e=this.input(t,"sampler"),a=this.toSampler(e,t.id),r=this.expectType(this.input(t,"scale",{type:"float",value:D(1)}),["float"],t.id,"scale"),u=this.expectType(this.input(t,"normal",{type:"vec3",value:Gt.normal}),["vec3"],t.id,"normal"),i=this.expectType(this.input(t,"position",{type:"vec3",value:Gt.position}),["vec3"],t.id,"position"),o=Mt(a.value,r.value,u.value,i.value);return this.output(t,{rgba:{type:"rgba",value:o},rgb:{type:"rgb",value:o.rgb},r:{type:"float",value:o.r},g:{type:"float",value:o.g},b:{type:"float",value:o.b},a:{type:"float",value:o.a}})}case"scene.sampleColor":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:Qt}),["vec2"],t.id,"uv"),a=te(e.value);return this.output(t,{rgba:{type:"rgba",value:a},rgb:{type:"rgb",value:a.rgb},r:{type:"float",value:a.r},g:{type:"float",value:a.g},b:{type:"float",value:a.b},a:{type:"float",value:a.a}})}case"scene.sampleDepth":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:Qt}),["vec2"],t.id,"uv");return this.output(t,{depth:{type:"float",value:Jt(e.value)},linearEyeDepth:{type:"float",value:Kt(e.value)}})}case"scene.fragmentDepth":return this.output(t,{linearEyeDepth:{type:"float",value:Yt}});case"transform.translate":{const e=this.expectType(this.input(t,"offset",{type:"vec3",value:Bt(0,0,0)}),["vec3","rgb"],t.id,"offset");return this.output(t,{value:{type:"mat4",value:St(e.value)}})}case"transform.scale":{const e=this.expectType(this.input(t,"scale",{type:"vec3",value:Bt(1,1,1)}),["vec3","rgb"],t.id,"scale").value;return this.output(t,{value:{type:"mat4",value:gt(e.x,e.y,e.z)}})}case"transform.rotateAxis":{const e=this.expectType(this.input(t,"axis",{type:"vec3",value:Bt(0,1,0)}),["vec3","rgb"],t.id,"axis"),a=this.expectType(this.input(t,"angle",{type:"float",value:D(0)}),["float"],t.id,"angle");return this.output(t,{value:{type:"mat4",value:ne(e.value,a.value)}})}case"uv.rotate":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"angle",{type:"float",value:D(0)}),["float"],t.id,"angle").value,r=this.expectType(this.input(t,"center",{type:"vec2",value:Ut(.5,.5)}),["vec2"],t.id,"center").value;return this.output(t,{value:{type:"vec2",value:Ve(e,a,r)}})}case"uv.twirl":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"strength",{type:"float",value:D(1)}),["float"],t.id,"strength").value,r=this.expectType(this.input(t,"center",{type:"vec2",value:Ut(.5,.5)}),["vec2"],t.id,"center").value,u=this.expectType(this.input(t,"offset",{type:"vec2",value:Ut(0,0)}),["vec2"],t.id,"offset").value;return this.output(t,{value:{type:"vec2",value:Ct(e,a,r,u)}})}case"uv.radial":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=At(e.subtractScalar(.5));return this.output(t,{coords:{type:"vec2",value:a.coords},radius:{type:"float",value:a.radius},angle:{type:"float",value:a.angle}})}case"uv.bulge":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"center",{type:"vec2",value:Ut(.5,.5)}),["vec2"],t.id,"center").value,r=this.expectType(this.input(t,"power",{type:"float",value:D(1)}),["float"],t.id,"power").value;return this.output(t,{value:{type:"vec2",value:N(e,a,r)}})}case"uv.flipbook":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"columns",Ge(t,"columns",1)),r=this.floatInput(t,"rows",Ge(t,"rows",1)),u=this.floatInput(t,"fps",Ge(t,"fps",60)),i=this.expectType(this.input(t,"time",{type:"float",value:Tt.elapsed}),["float"],t.id,"time").value,o=String(Ee(t,"mode","clamp"));return this.output(t,{value:{type:"vec2",value:se(e,a,r,i,u,o)}})}case"uv.pom":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.input(t,"heightMap"),r=this.toSampler(a,t.id).value,u=this.floatInput(t,"heightScale",.05),i=Ge(t,"minLayers",8),o=Ge(t,"maxLayers",24);return this.output(t,{value:{type:"vec2",value:le(e,r,u,i,o)}})}case"shape.rectangle":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value;return this.output(t,{value:{type:"float",value:Ft(e,this.floatInput(t,"width",.5),this.floatInput(t,"height",.5))}})}case"shape.roundedRectangle":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value;return this.output(t,{value:{type:"float",value:Rt(e,this.floatInput(t,"width",.5),this.floatInput(t,"height",.5),this.floatInput(t,"radius",.1))}})}case"noise.simplex":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"scale",8);return this.output(t,{value:{type:"float",value:new ie(e.multiplyScalar(a))}})}case"noise.voronoi2d":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"scale",8);return this.output(t,{value:{type:"float",value:new oe(e.multiplyScalar(a))}})}case"effect.fresnel":return this.output(t,{value:{type:"float",value:C(Wt(this.floatInput(t,"power",1)))}});case"effect.edgeDepth":{const e=this.floatInput(t,"power",1);return this.output(t,{value:{type:"float",value:_t(e)}})}case"effect.depthFade":{const e=this.floatInput(t,"distance",1);return this.output(t,{value:{type:"float",value:Ht(e)}})}case"util.panner":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"coord"),a=this.expectType(this.input(t,"speed",{type:"vec2",value:Ut(0,0)}),["vec2"],t.id,"speed"),r=this.expectType(this.input(t,"tile",{type:"vec2",value:Ut(1,1)}),["vec2"],t.id,"tile"),u=this.expectType(this.input(t,"time",{type:"float",value:Tt.elapsed}),["float"],t.id,"time");return this.output(t,{value:{type:"vec2",value:e.value.multiply(r.value).add(a.value.multiplyScalar(u.value))}})}}}compileParameterNode(t){const e=String(Ee(t,"parameter","")),a=this.graph.parameters?.find(t=>t.name===e||t.id===e);if(null==a)throw new ShaderGraphCompileError(`Parameter "${e}" does not exist`,t.id);const r=ve(a.type),u={type:r,value:Be(this.options.parameters?.[a.name]??a.defaultValue,r,a.name)};if("sampler2d"!==r)return{value:u};const i=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv"),o=u.value.sample(i.value);return{value:{type:"rgba",value:o},rgb:{type:"rgb",value:o.rgb},r:{type:"float",value:o.r},g:{type:"float",value:o.g},b:{type:"float",value:o.b},a:{type:"float",value:o.a},sampler:u}}compileBinaryMath(t){const e=this.expectBinaryMathValue(this.input(t,"a")),a=this.expectBinaryMathValue(this.input(t,"b")),r=t.kind.split(".")[1];if("mat4"===e.type||"mat4"===a.type)return function(t,e,a,r){if("mat4"===t.type&&"mat4"===e.type&&"divide"!==a)return{type:"mat4",value:$e(t.value,e.value,a,r)};if("mat4"===t.type&&"float"===e.type&&("multiply"===a||"divide"===a))return{type:"mat4",value:$e(t.value,e.value,a,r)};if("float"===t.type&&"mat4"===e.type&&"multiply"===a)return{type:"mat4",value:$e(e.value,t.value,a,r)};if("mat4"===t.type&&"vec4"===e.type&&"multiply"===a)return{type:"vec4",value:t.value.multiplyVec(e.value)};throw new ShaderGraphCompileError(`Cannot ${a} ${t.type} and ${e.type}`,r)}(e,a,r,t.id);if(e.type===a.type)return{type:e.type,value:$e(e.value,a.value,r,t.id)};if("float"===e.type&&"float"!==a.type&&"multiply"===r)return{type:a.type,value:$e(a.value,e.value,r,t.id)};if("float"!==e.type&&"float"===a.type)return{type:e.type,value:$e(e.value,a.value,r,t.id)};throw new ShaderGraphCompileError(`Cannot ${r} ${e.type} and ${a.type}`,t.id)}expectBinaryMathValue(t){if(!Pe(t.type)&&"mat4"!==t.type)throw new ShaderGraphCompileError(`Expected a numeric value but got ${t.type}`);return t}compileUnaryMath(t,e){const a=this.expectNumeric(this.input(t,"value"));return{type:a.type,value:e(a.value)}}compileAtan2(t){const e=this.expectNumeric(this.input(t,"y")),a=this.expectNumeric(this.input(t,"x"));return{type:function(t,e,a){if(t===e)return t;if("rgb"===t&&"vec3"===e||"vec3"===t&&"rgb"===e)return"vec3";if("rgba"===t&&"vec4"===e||"vec4"===t&&"rgba"===e)return"vec4";throw new ShaderGraphCompileError(`Cannot mix ${t} and ${e}`,a)}(e.type,a.type,t.id),value:M(e.value,a.value)}}compileBinaryFunction(t,e,a=!1){const r=this.expectNumeric(this.input(t,"a")),u=this.expectNumeric(this.input(t,"b"));return{type:a&&"float"===u.type?r.type:ze(r.type,u.type,t.id),value:e(r.value,u.value)}}compilePaintedLayerMix(t){const e=this.expectNumeric(this.input(t,"base")),a=[e.value],r=[zt(0)];let u=e.type;for(let e=1;e<=8;e++){const i=this.optionalInput(t,`layer${e}`);if(null==i)continue;const o=this.expectNumeric(i);u=ze(u,o.type,t.id),a.push(o.value),r.push(zt(e))}return 1===a.length?e:{type:u,value:rt({layerColors:a,layerWeights:r,enableNoise:Boolean(Ee(t,"enableNoise",!0)),noiseScale:this.floatInput(t,"noiseScale",Ge(t,"noiseScale",.1)),noiseAmount:this.floatInput(t,"noiseAmount",Ge(t,"noiseAmount",.5)),decay:this.floatInput(t,"softness",Ge(t,"softness",.3)),mode:"hard"===String(Ee(t,"mode","soft"))?K.hard:K.soft})}}defaultUV(){return"trail"===this.graph.target?ue:"decal"===this.graph.target?ae:C(S.uv)}input(t,e,a){const r=t.inputs?.[e];if(null!=r)return this.resolveInput(r,t.id,e);const u=(this.graph.edges??[]).find(a=>a.to.nodeId===t.id&&a.to.port===e);if(null!=u)return this.resolveSocket(u.from,t.id,e);if(null!=a)return a;const i=this.inlineLiteralFallback(t,e);if(null!=i)return i;throw new ShaderGraphCompileError(`Missing input "${e}"`,t.id,e)}optionalInput(t,e){const a=t.inputs?.[e];if(null!=a)return this.resolveInput(a,t.id,e);const r=(this.graph.edges??[]).find(a=>a.to.nodeId===t.id&&a.to.port===e);return null!=r?this.resolveSocket(r.from,t.id,e):void 0}floatInput(t,e,a){return this.expectType(this.input(t,e,{type:"float",value:D(a)}),["float"],t.id,e).value}boolInput(t,e,a){return this.expectType(this.input(t,e,{type:"boolean",value:E(a)}),["boolean"],t.id,e).value}compileComparison(t){const e=this.expectType(this.input(t,"a"),["float"],t.id,"a").value,a=this.expectType(this.input(t,"b"),["float"],t.id,"b").value;switch(t.kind){case"compare.greaterThan":return e.gt(a);case"compare.greaterThanOrEqual":return e.gte(a);case"compare.lessThan":return e.lt(a);case"compare.lessThanOrEqual":return e.lte(a);case"compare.equal":return e.equals(a);case"compare.notEqual":return e.notEquals(a)}throw new ShaderGraphCompileError(`Unsupported comparison node "${t.kind}"`,t.id)}compileBooleanBinary(t,e){const a=this.boolInput(t,"a",!1),r=this.boolInput(t,"b",!1);return"and"===e?a.and(r):a.or(r)}resolveOutputBinding(t,e){if(null!=t.input)return this.resolveSocket(t.input,void 0,e);if(void 0!==t.value)return Ue(t.value);throw new ShaderGraphCompileError(`Output "${e}" is missing an input or value`)}floatOutput(t,e){return this.expectType(this.resolveOutputBinding(t,e),["float"],e).value}resolveInput(t,e,a){return function(t){return null!=t.nodeId}(t)?this.resolveSocket(t,e,a):Ue(t.value,t.valueType)}inlineLiteralFallback(t,e){const a=he[t.kind]?.inputs.find(t=>t.name===e);if(null==a)return;const r=ce(t.kind,a),u=pe(t.kind,a);return null!=r&&void 0!==u?Ue(u,r):void 0}resolveSocket(t,e,a){const r=this.compileNode(t.nodeId).outputs[t.port];if(null==r)throw new ShaderGraphCompileError(`Node "${t.nodeId}" does not have output "${t.port}"`,e??t.nodeId,a??t.port);return r}expectType(t,e,a,r){if(!e.includes(t.type))throw new ShaderGraphCompileError(`Expected ${e.join(" or ")} but got ${t.type}`,a,r);return t}expectNumeric(t){if(!Pe(t.type))throw new ShaderGraphCompileError(`Expected a numeric value but got ${t.type}`);return t}toSampler(t,e){if("sampler2d"===t.type)return t;if("texture2d"===t.type){const a=t.value;if(null==a)throw new ShaderGraphCompileError("Texture input is empty",e);return{type:"sampler2d",value:wt(a)}}throw new ShaderGraphCompileError(`Expected texture2d or sampler2d but got ${t.type}`,e)}toColorOutput(t){switch(t.type){case"float":case"vec2":case"vec3":case"vec4":case"rgb":case"rgba":return t.value;case"boolean":{const e=ht(t.value,D(1),D(0));return lt(Bt(e,e,e),1)}case"mat4":throw new ShaderGraphCompileError("mat4 values cannot be used as color");case"texture2d":case"sampler2d":throw new ShaderGraphCompileError(`${t.type} must be sampled before it can be used as color`)}}toVec3Output(t,e){if("vec3"===t.type||"rgb"===t.type)return t.value;if("vec4"===t.type||"rgba"===t.type)return t.value.xyz;throw new ShaderGraphCompileError(`Output "${e}" expects vec3/rgb but got ${t.type}`)}toMat4Output(t,e){if("mat4"===t.type)return t.value;throw new ShaderGraphCompileError(`Output "${e}" expects mat4 but got ${t.type}`)}output(t,e){return{node:t,outputs:e}}}export function compileShaderGraph(t,e={}){return new ShaderGraphCompiler(t,e).compile()}export function compileShaderGraphPreview(t,e,a={}){if(null==e)return compileShaderGraph(t,a).output;const r=new ShaderGraphCompiler(t,a).compileNode(e),u=Object.values(r.outputs)[0];if(null==u)throw new ShaderGraphCompileError(`Node "${e}" has no previewable output`,e);return{color:Oe(u),transparent:"rgba"===u.type||"vec4"===u.type}}export function buildShaderGraphMaterial(t,a={}){if("postProcess"===t.target)return buildShaderGraphPostProcessMaterial(t,a);const r=null!=a.previewNodeId?compileShaderGraphPreview(t,a.previewNodeId,a):compileShaderGraph(t,a).output;if("sprite"===t.target)return new Vt({color:r.color,discard:r.discard,transparent:r.transparent??!0,position:kt(new f("rotation",0),new f("screenSpaceSize",0)),uniforms:{color:{value:new e(16777215)}}});if("trail"===t.target){const{position:e}=re.getTrailShaderNodes(a.trailBillboard??!1),u=new h({...r,position:e});return re.applyTrailShaderParameters(u),Se(u,t),u}if("decal"===t.target){const e=null!=r.discard?ee.or(r.discard):ee,a=new h({...r,transparent:!1,discard:e});return a.userData.isDecal=!0,Se(a,t),a}const u=new h({transparent:!1,...r});return Se(u,t),u}export function buildShaderGraphPostProcessMaterial(t,e={}){const a=null!=e.previewNodeId?Te(compileShaderGraphPreview(t,e.previewNodeId,e).color):compileShaderGraph(t,e).output,r=new h({color:a.color,transparent:!1,fog:!1,lights:!1,outputEncoding:!1});return r.depthWrite=!1,r.depthTest=!1,r.toneMapped=!1,r.userData.isPostProcessShaderGraph=!0,r}function Te(t,e){const a=te(Qt),r=Nt("hology_post_process_weight",1),u=ct(null!=e?r.multiply(e):r);return{color:at(a,t,u),transparent:!1,...null!=e?{opacity:e}:{}}}export function shaderGraphMaterialSideToThree(e){switch(e){case"back":return t;case"double":return a;default:return r}}function Ie(t){return"decal"!==t.target&&(t.materialOptions?.transparent??"sprite"===t.target)}function Se(t,e){"surface"===e.target&&(t.side=shaderGraphMaterialSideToThree(e.materialOptions?.side)),null!=e.materialOptions?.transparent&&(t.transparent=e.materialOptions.transparent),null!=e.materialOptions?.alphaTest&&0===t.alphaTest&&(t.alphaTest=e.materialOptions.alphaTest),null!=e.materialOptions?.bloom&&(t.userData.hasBloom=e.materialOptions.bloom)}function Oe(t){switch(t.type){case"float":return Me(t.value);case"vec2":{const e=t.value;return lt(Bt(e.x,e.y,0),1)}case"vec3":case"rgb":return lt(t.value,1);case"vec4":case"rgba":return t.value;case"boolean":return Me(ht(t.value,D(1),D(0)));case"mat4":throw new ShaderGraphCompileError("mat4 values cannot be previewed as color");case"texture2d":case"sampler2d":throw new ShaderGraphCompileError(`${t.type} nodes require a sampled output to preview`)}}function Me(t){return lt(Bt(t,t,t),1)}function Ce(t){return t instanceof p?Bt(t,t,t).rgb:t instanceof g?Bt(t.x,t.y,0).rgb:t}function Ne(t){return t.rgb}function Ee(t,e,a){const r=t.params?.[e];return void 0===r?a:r}function Ge(t,e,a){const r=Ee(t,e,a);return"number"==typeof r?r:Number(r??a)}function Ue(t,e){if(null!=(a=t)&&"object"==typeof a&&!Array.isArray(a)&&"value"in a)return Ue(t.value,t.valueType??e);var a;const r=e??function(t){if("boolean"==typeof t)return"boolean";if("number"==typeof t)return"float";if(Array.isArray(t))return 2===t.length?"vec2":3===t.length?"vec3":16===t.length?"mat4":"vec4";return"string"==typeof t?"rgb":"float"}(t);return{type:r,value:Be(t,r,"literal")}}function Be(t,a,r){switch(a){case"boolean":return t instanceof l?t:E(Boolean(t));case"float":return t instanceof p?t:D(je(t,0));case"vec2":return t instanceof g?t:Le(t);case"vec3":return t instanceof b?t:qe(t);case"vec4":return t instanceof x?t:function(t){const[e,a,r,u]=De(t,4,1);return $t(e,a,r,u)}(t);case"mat4":return t instanceof c?t:function(t){if(t instanceof u)return Z(t);const e=new u;Array.isArray(t)&&16===t.length&&e.fromArray(t.map(t=>je(t,0)));return Z(e)}(t);case"rgb":return t instanceof v?t:function(t){if("string"==typeof t||"number"==typeof t||t instanceof e)return pt(t);const[a,r,u]=De(t,3);return Bt(a,r,u).rgb}(t);case"rgba":return t instanceof y||t instanceof x?t:Fe(t);case"texture2d":return t;case"sampler2d":if(function(t){const e=t;return t instanceof m||t instanceof d||"function"==typeof e?.isSampler2D||!0===e?.isSampler2D}(t))return t;if(t instanceof i)return wt(t);throw new ShaderGraphCompileError(`Parameter "${r}" needs a texture value`)}}function $e(t,e,a,r){const u=`${a}Scalar`;if(e instanceof p&&"function"==typeof t[u])return t[u](e);if("function"==typeof t[a])return t[a](e);throw new ShaderGraphCompileError(`Node does not support ${a}`,r)}function ze(t,e,a){if(t===e)return t;if("rgb"===t&&"vec3"===e||"vec3"===t&&"rgb"===e)return"vec3";if("rgba"===t&&"vec4"===e||"vec4"===t&&"rgba"===e)return"vec4";if("float"===t&&Pe(e))return e;if("float"===e&&Pe(t))return t;throw new ShaderGraphCompileError(`Cannot mix ${t} and ${e}`,a)}function Ve(t,e,a){const r=t.subtract(a),u=yt(e),i=$(e);return Ut(i.multiply(r.x).subtract(u.multiply(r.y)).add(a.x),u.multiply(r.x).add(i.multiply(r.y)).add(a.y))}function ke(t,e,a){const r=t.value["u"===e?"x":"v"===e?"y":e];if(r instanceof p)return r;throw new ShaderGraphCompileError(`Component "${e}" is not available on ${t.type}`,a)}function Pe(t){return"float"===t||"vec2"===t||"vec3"===t||"vec4"===t||"rgb"===t||"rgba"===t}function Ae(t){return Number.isFinite(t)?Math.min(1,Math.max(0,t)):0}function je(t,e){if("number"==typeof t)return t;if("string"==typeof t){const a=parseFloat(t);return Number.isFinite(a)?a:e}return"boolean"==typeof t?t?1:0:e}function De(t,a,r=0){if(Array.isArray(t))return Array.from({length:a},(e,a)=>je(t[a],r));if(t instanceof o||t instanceof n||t instanceof s)return Array.from({length:a},(e,a)=>t.toArray()[a]??r);if(t instanceof e){const e=t.toArray();return Array.from({length:a},(t,a)=>e[a]??(3===a?1:r))}if(null!=t&&"object"==typeof t){const e=t,u=["x","y","z","w"];if(u.some(t=>null!=e[t]))return Array.from({length:a},(t,a)=>je(e[u[a]],r));const i=["r","g","b","a"];if(i.some(t=>null!=e[t]))return Array.from({length:a},(t,a)=>je(e[i[a]],3===a?1:r))}return Array.from({length:a},()=>je(t,r))}function Le(t){const[e,a]=De(t,2);return Ut(e,a)}function qe(t){const[e,a,r]=De(t,3);return Bt(e,a,r)}function Fe(t,a=1){if("string"==typeof t||"number"==typeof t||t instanceof e)return lt(t,a);if(t instanceof b)return lt(t,a);const[r,u,i,o]=De(t,4,a);return $t(r,u,i,o)}function Re(t,e){return e<=1?0:t/(e-1)}/*
1
+ import{BackSide as t,Color as e,DoubleSide as a,FrontSide as r,Matrix4 as u,Texture as i,Vector2 as o,Vector3 as n,Vector4 as s}from"three";import{BooleanNode as l,FloatNode as p,Mat4Node as c,NodeShaderMaterial as h,RgbNode as v,RgbaNode as y,Sampler2DNode as m,Texture2dLookupNode as d,UniformFloatNode as f,Vec2Node as g,Vec3Node as b,Vec4Node as x,abs as w,acos as T,asin as I,attributes as S,atan as O,atan2 as M,autoVarying as C,bulge as N,bool as E,ceil as G,clamp as U,colorToNormal as B,cos as $,cross as z,degrees as V,distance as k,dot as P,exp as A,exp2 as j,float as D,floor as L,fract as q,inversesqrt as F,batchingMatrix as R,colorGradientSampler as _,curveSampler as W,ifDefApply as H,sampleNamedEasingCurve as Y,length as J,LayerMixMode as K,log as Q,log2 as X,mat4 as Z,max as tt,min as et,mix as at,mixColorsByLayer as rt,particleUniforms as ut,mod as it,normalize as ot,pow as nt,radians as st,rgba as lt,rgb as pt,saturate as ct,select as ht,sign as vt,sin as yt,smoothstep as mt,sqrt as dt,standardMaterial as ft,scaleTransform as gt,step as bt,tan as xt,textureSampler2d as wt,timeUniforms as Tt,toonMaterial as It,translate as St,transformed as Ot,triplanarMapping as Mt,twirl as Ct,uniformFloat as Nt,uniforms as Et,varyingAttributes as Gt,vec2 as Ut,vec3 as Bt,vec4 as $t,getPaintedMaterialLayerWeight as zt}from"../../shader-nodes/index.js";import{SpriteNodeShaderMaterial as Vt,getSpritePosition as kt}from"../sprite-shader.js";import{oneMinus as Pt}from"../../shader-nodes/index.js";import{vectorToRadial as At,remap as jt,hueShift as Dt,blendColor as Lt,desaturateColor as qt}from"../../shader-nodes/math.js";import{rectangleFloat as Ft,roundedRectangleFloat as Rt}from"../../shader-nodes/shapes.js";import{edgeDepthEffect as _t,fresnelEffect as Wt,depthFadeEffect as Ht}from"../../shader-nodes/effects.js";import{fragmentLinearEyeDepth as Yt,sampleSceneDepth as Jt,sampleSceneLinearEyeDepth as Kt,screenUV as Qt,nearUniformName as Xt,farUniformName as Zt}from"../../shader-nodes/depth.js";import{sampleSceneColor as te}from"../../shader-nodes/scene-sample.js";import{decalDiscard as ee,decalUV as ae}from"../../shader-nodes/decal.js";import{Trail as re,trailUV as ue}from"../../effects/vfx/trail-renderer.js";import{SimplexNoiseNode as ie,Voronoi2d as oe,rotateAxis as ne}from"../../shader-nodes/index.js";import{flipbookUv as se}from"../../shader-nodes/texture-sequence.js";import{parallaxOcclusionMapping as le}from"../../shader-nodes/pom.js";import{defaultInlineLiteralValueForPort as pe,inlineLiteralTypeForPort as ce,SHADER_GRAPH_NODE_DEFINITIONS as he}from"./registry.js";import{shaderGraphParameterTypeToValueType as ve}from"./parameters.js";import{varying as ye,reflect as me,refract as de,dFdx as fe,dFdy as ge,fwidth as be}from"three-shader-graph";import{decalNormal as xe}from"../../shader-nodes/decal.js";import{Curve2 as we}from"../../utils/curve.js";export class ShaderGraphCompileError extends Error{constructor(t,e,a){super(t),this.nodeId=e,this.port=a,this.name="ShaderGraphCompileError"}}export const shaderGraphPostProcessWeightUniformName="hology_post_process_weight";export class ShaderGraphCompiler{constructor(t,e={}){this.graph=t,this.options=e,this.compiled=new Map,this.nodesById=new Map((t.nodes??[]).map(t=>[t.id,t]))}validate(){this.compile()}compile(){if(1!==this.graph.version)throw new ShaderGraphCompileError(`Unsupported shader graph version ${this.graph.version}`);return this.validateEdges(),{output:this.compileOutput(),nodes:this.compiled}}validateEdges(){for(const t of this.graph.edges??[]){if(!this.nodesById.has(t.from.nodeId))throw new ShaderGraphCompileError(`Edge references missing source node "${t.from.nodeId}"`,t.from.nodeId,t.from.port);if(!this.nodesById.has(t.to.nodeId))throw new ShaderGraphCompileError(`Edge references missing target node "${t.to.nodeId}"`,t.to.nodeId,t.to.port)}}compileOutput(){if("postProcess"===this.graph.target)return this.compilePostProcessOutput();const t=this.graph.outputs?.color,e={color:null!=t?this.toColorOutput(this.resolveOutputBinding(t,"color")):lt("#ffffff",1),transparent:Se(this.graph)},a=this.graph.outputs?.opacity;null!=a&&(e.opacity=this.expectType(this.resolveOutputBinding(a,"opacity"),["float"],"opacity").value);const r=this.graph.outputs?.roughness;null!=r&&(e.roughness=this.expectType(this.resolveOutputBinding(r,"roughness"),["float"],"roughness").value);const u=this.graph.outputs?.metalness;null!=u&&(e.metalness=this.floatOutput(u,"metalness"));const i=this.graph.outputs?.normal;null!=i&&(e.normal=this.toVec3Output(this.resolveOutputBinding(i,"normal"),"normal"));const o=this.graph.outputs?.emissive;null!=o&&(e.emissive=this.toVec3Output(this.resolveOutputBinding(o,"emissive"),"emissive"));const n=this.graph.outputs?.ambientOcclusion;null!=n&&(e.ambientOcclusion=this.floatOutput(n,"ambientOcclusion"));const s=this.graph.outputs?.ambientOcclusionIntensity;null!=s&&(e.ambientOcclusionIntensity=this.floatOutput(s,"ambientOcclusionIntensity"));const l=this.graph.outputs?.sheenColor;null!=l&&(e.sheenColor=this.toVec3Output(this.resolveOutputBinding(l,"sheenColor"),"sheenColor"));const p=this.graph.outputs?.sheenRoughness;null!=p&&(e.sheenRoughness=this.floatOutput(p,"sheenRoughness"));const c=this.graph.outputs?.anisotropy;null!=c&&(e.anisotropy=this.floatOutput(c,"anisotropy"));const h=this.graph.outputs?.anisotropyDirection;null!=h&&(e.anisotropyDirection=this.expectType(this.resolveOutputBinding(h,"anisotropyDirection"),["vec2"],"anisotropyDirection").value);const v=this.graph.outputs?.bakedLight;null!=v&&(e.bakedLight=this.toVec3Output(this.resolveOutputBinding(v,"bakedLight"),"bakedLight"));const y=this.graph.outputs?.transform;null!=y&&"decal"!==this.graph.target&&(e.transform=this.toMat4Output(this.resolveOutputBinding(y,"transform"),"transform"));const m=this.graph.outputs?.discard;null!=m&&(e.discard=this.expectType(this.resolveOutputBinding(m,"discard"),["boolean"],"discard").value);const d=this.graph.outputs?.transparent;null!=d&&null!=d.value&&(e.transparent=Boolean(d.value));const f=this.graph.outputs?.alphaTest;return null!=f&&null!=f.value&&(e.alphaTest=Number(f.value)),this.applyShadingModel(e)}compilePostProcessOutput(){const t=this.graph.outputs?.color,e=null!=t?this.toColorOutput(this.resolveOutputBinding(t,"color")):te(Qt),a=this.graph.outputs?.opacity;return Te(e,null!=a?this.expectType(this.resolveOutputBinding(a,"opacity"),["float"],"opacity").value:void 0)}applyShadingModel(t){const e=null!=t.opacity?function(t,e){if(t instanceof p)return lt(Bt(t,t,t),e);if(t instanceof g)return lt(Bt(t.x,t.y,0),e);if(t instanceof x)return lt(t.rgb,t.w.multiply(e));return lt(t,e)}(t.color,t.opacity):t.color;switch(this.graph.shadingModel??"standard"){case"standard":{const a={color:Ne(e),roughness:t.roughness??D(.5),...null!=t.metalness?{metalness:t.metalness}:{},..."decal"===this.graph.target?{normal:ot(ye(Et.normalMatrix).multiplyVec(xe))}:{},...null!=t.normal?{normal:t.normal}:{},...null!=t.emissive?{emissive:Ee(t.emissive)}:{},...null!=t.ambientOcclusion?{ambientOcclusion:t.ambientOcclusion}:{},...null!=t.ambientOcclusionIntensity?{ambientOcclusionIntensity:t.ambientOcclusionIntensity}:{},...null!=t.sheenColor?{sheenColor:t.sheenColor.rgb}:{},...null!=t.sheenRoughness?{sheenRoughness:t.sheenRoughness}:{},...null!=t.anisotropy?{anisotropy:t.anisotropy}:{},...null!=t.anisotropyDirection?{anisotropyDirection:t.anisotropyDirection}:{},...null!=t.bakedLight?{bakedLight:t.bakedLight}:{}};return{...t,color:ft(a)}}case"toon":{const a={color:Ne(e),...null!=t.normal?{normal:t.normal}:{},...null!=t.emissive?{emissive:Ee(t.emissive)}:{},...null!=t.ambientOcclusion?{ambientOcclusion:t.ambientOcclusion}:{},...null!=t.ambientOcclusionIntensity?{ambientOcclusionIntensity:t.ambientOcclusionIntensity}:{},...null!=t.bakedLight?{bakedLight:t.bakedLight}:{}};return{...t,color:It(a)}}case"unlit":return{...t,color:e}}}compileNode(t){const e=this.compiled.get(t);if(null!=e)return e;const a=this.nodesById.get(t);if(null==a)throw new ShaderGraphCompileError(`Missing shader graph node "${t}"`,t);if(null==he[a.kind])throw new ShaderGraphCompileError(`Unsupported shader graph node "${a.kind}"`,a.id);const r=this.compileNodeInternal(a);return this.compiled.set(t,r),r}compileNodeInternal(t){switch(t.kind){case"input.parameter":return this.output(t,this.compileParameterNode(t));case"input.slider":return this.output(t,{value:{type:"float",value:D(je(Ue(t,"value",.5)))}});case"constant.boolean":return this.output(t,{value:{type:"boolean",value:E(Boolean(Ge(t,"value",!1)))}});case"constant.float":return this.output(t,{value:{type:"float",value:D(Ue(t,"value",0))}});case"constant.vec2":return this.output(t,{value:{type:"vec2",value:qe(Ge(t,"value",[0,0]))}});case"constant.vec3":return this.output(t,{value:{type:"vec3",value:Fe(Ge(t,"value",[0,0,0]))}});case"constant.rgba":return this.output(t,{value:{type:"rgba",value:Re(Ge(t,"value","#ffffff"),Ue(t,"alpha",1))}});case"builtin.uv":{const e=this.defaultUV();return this.output(t,{value:{type:"vec2",value:!0===Ge(t,"flipY",!1)?Ut(e.x,Pt(e.y)):e},u:{type:"float",value:e.x},v:{type:"float",value:e.y}})}case"builtin.screenUv":return this.output(t,{value:{type:"vec2",value:Qt}});case"builtin.color":{const e=C(S.color);return this.output(t,{value:{type:"rgba",value:e},rgb:{type:"rgb",value:e.rgb},r:{type:"float",value:e.r},g:{type:"float",value:e.g},b:{type:"float",value:e.b},a:{type:"float",value:e.a}})}case"builtin.position":{const e=C(S.position);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.worldPosition":{const e=C(Ot.worldPosition);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.objectPosition":{let e=Et.instanceMatrix.multiplyVec($t(0,0,0,1));e=H("USE_BATCHING",e,t=>R.multiplyVec(t));const a=C(Et.modelMatrix.multiplyVec(e).xyz);return this.output(t,{value:{type:"vec3",value:a},x:{type:"float",value:a.x},y:{type:"float",value:a.y},z:{type:"float",value:a.z}})}case"builtin.viewDir":{const e=C(Ot.viewDir);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.normal":{const e=C(S.normal);return this.output(t,{value:{type:"vec3",value:e},x:{type:"float",value:e.x},y:{type:"float",value:e.y},z:{type:"float",value:e.z}})}case"builtin.time":return this.output(t,{value:{type:"float",value:Tt.elapsed}});case"builtin.camera":{const e=Nt(Xt),a=Nt(Zt),r=Et.cameraPosition;return this.output(t,{position:{type:"vec3",value:r},x:{type:"float",value:r.x},y:{type:"float",value:r.y},z:{type:"float",value:r.z},near:{type:"float",value:e},far:{type:"float",value:a}})}case"builtin.viewMatrix":return this.output(t,{value:{type:"mat4",value:Et.viewMatrix}});case"builtin.projectionMatrix":return this.output(t,{value:{type:"mat4",value:Et.projectionMatrix}});case"builtin.modelViewMatrix":return this.output(t,{value:{type:"mat4",value:Et.modelViewMatrix}});case"builtin.particle":return this.output(t,{energy:{type:"float",value:ut.energy},color:{type:"rgb",value:ut.color},opacity:{type:"float",value:ut.opacity},time:{type:"float",value:ut.time}});case"math.add":case"math.subtract":case"math.multiply":case"math.divide":return this.output(t,{value:this.compileBinaryMath(t)});case"math.oneMinus":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:e.type,value:Pt(e.value)}})}case"math.abs":return this.output(t,{value:this.compileUnaryMath(t,w)});case"math.sign":return this.output(t,{value:this.compileUnaryMath(t,vt)});case"math.floor":return this.output(t,{value:this.compileUnaryMath(t,L)});case"math.ceil":return this.output(t,{value:this.compileUnaryMath(t,G)});case"math.fract":return this.output(t,{value:this.compileUnaryMath(t,q)});case"math.sin":return this.output(t,{value:this.compileUnaryMath(t,yt)});case"math.cos":return this.output(t,{value:this.compileUnaryMath(t,$)});case"math.tan":return this.output(t,{value:this.compileUnaryMath(t,xt)});case"math.asin":return this.output(t,{value:this.compileUnaryMath(t,I)});case"math.acos":return this.output(t,{value:this.compileUnaryMath(t,T)});case"math.atan":return this.output(t,{value:this.compileUnaryMath(t,O)});case"math.atan2":return this.output(t,{value:this.compileAtan2(t)});case"math.radians":return this.output(t,{value:this.compileUnaryMath(t,st)});case"math.degrees":return this.output(t,{value:this.compileUnaryMath(t,V)});case"math.sqrt":return this.output(t,{value:this.compileUnaryMath(t,dt)});case"math.inverseSqrt":return this.output(t,{value:this.compileUnaryMath(t,F)});case"math.exp":return this.output(t,{value:this.compileUnaryMath(t,A)});case"math.exp2":return this.output(t,{value:this.compileUnaryMath(t,j)});case"math.log":return this.output(t,{value:this.compileUnaryMath(t,Q)});case"math.log2":return this.output(t,{value:this.compileUnaryMath(t,X)});case"math.saturate":return this.output(t,{value:this.compileUnaryMath(t,ct)});case"math.length":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:"float",value:J(e.value)}})}case"math.normalize":return this.output(t,{value:this.compileUnaryMath(t,ot)});case"math.clamp":{const e=this.expectNumeric(this.input(t,"value")),a=this.expectNumeric(this.input(t,"min",{type:"float",value:D(0)})),r=this.expectNumeric(this.input(t,"max",{type:"float",value:D(1)}));return this.output(t,{value:{type:e.type,value:U(e.value,a.value,r.value)}})}case"math.min":return this.output(t,{value:this.compileBinaryFunction(t,et)});case"math.max":return this.output(t,{value:this.compileBinaryFunction(t,tt)});case"math.pow":return this.output(t,{value:this.compileBinaryFunction(t,nt)});case"math.mod":return this.output(t,{value:this.compileBinaryFunction(t,it)});case"math.step":return this.output(t,{value:this.compileBinaryFunction(t,bt,!0)});case"math.smoothstep":{const e=this.expectNumeric(this.input(t,"edge0",{type:"float",value:D(0)})),a=this.expectNumeric(this.input(t,"edge1",{type:"float",value:D(1)})),r=this.expectNumeric(this.input(t,"value"));return this.output(t,{value:{type:r.type,value:mt(e.value,a.value,r.value)}})}case"math.mix":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b")),r=this.expectNumeric(this.input(t,"t",{type:"float",value:D(.5)})),u=Ve(e.type,a.type,t.id);return this.output(t,{value:{type:u,value:at(e.value,a.value,r.value)}})}case"math.remap":{const e=this.expectType(this.input(t,"value"),["float"],t.id,"value").value,a=this.floatInput(t,"inMin",-1),r=this.floatInput(t,"inMax",1),u=this.floatInput(t,"outMin",0),i=this.floatInput(t,"outMax",1);return this.output(t,{value:{type:"float",value:jt(e,a,r,u,i)}})}case"math.select":{const e=this.boolInput(t,"condition",!1),a=this.expectNumeric(this.input(t,"a")),r=this.expectNumeric(this.input(t,"b")),u=Ve(a.type,r.type,t.id);return this.output(t,{value:{type:u,value:ht(e,a.value,r.value)}})}case"math.reflect":{const e=this.expectType(this.input(t,"incident"),["vec2","vec3","vec4","rgb","rgba"],t.id,"incident"),a=this.expectType(this.input(t,"normal"),["vec2","vec3","vec4","rgb","rgba"],t.id,"normal");return this.output(t,{value:{type:e.type,value:me(e.value,a.value)}})}case"math.refract":{const e=this.expectType(this.input(t,"incident"),["vec2","vec3","vec4","rgb","rgba"],t.id,"incident"),a=this.expectType(this.input(t,"normal"),["vec2","vec3","vec4","rgb","rgba"],t.id,"normal"),r=this.floatInput(t,"ior",1.5);return this.output(t,{value:{type:e.type,value:de(e.value,a.value,r)}})}case"math.derivative":{const e=this.expectNumeric(this.input(t,"value")),a=String(Ge(t,"mode","fwidth"));let r;return r="dFdx"===a?fe(e.value):"dFdy"===a?ge(e.value):be(e.value),this.output(t,{value:{type:e.type,value:r}})}case"layer.mixPainted":return this.output(t,{value:this.compilePaintedLayerMix(t)});case"math.dot":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b"));return Ve(e.type,a.type,t.id),this.output(t,{value:{type:"float",value:P(e.value,a.value)}})}case"math.distance":{const e=this.expectNumeric(this.input(t,"a")),a=this.expectNumeric(this.input(t,"b"));return Ve(e.type,a.type,t.id),this.output(t,{value:{type:"float",value:k(e.value,a.value)}})}case"math.cross":{const e=this.expectType(this.input(t,"a"),["vec3","rgb"],t.id,"a"),a=this.expectType(this.input(t,"b"),["vec3","rgb"],t.id,"b");return this.output(t,{value:{type:"vec3",value:z(e.value,a.value)}})}case"compare.greaterThan":case"compare.greaterThanOrEqual":case"compare.lessThan":case"compare.lessThanOrEqual":case"compare.equal":case"compare.notEqual":return this.output(t,{value:{type:"boolean",value:this.compileComparison(t)}});case"boolean.not":{const e=this.boolInput(t,"value",!1);return this.output(t,{value:{type:"boolean",value:ht(e,E(!1),E(!0))}})}case"boolean.and":return this.output(t,{value:{type:"boolean",value:this.compileBooleanBinary(t,"and")}});case"boolean.or":return this.output(t,{value:{type:"boolean",value:this.compileBooleanBinary(t,"or")}});case"compose.vec2":return this.output(t,{value:{type:"vec2",value:Ut(this.floatInput(t,"x",0),this.floatInput(t,"y",0))}});case"compose.vec3":return this.output(t,{value:{type:"vec3",value:Bt(this.floatInput(t,"x",0),this.floatInput(t,"y",0),this.floatInput(t,"z",0))}});case"compose.vec4":return this.output(t,{value:{type:"vec4",value:$t(this.floatInput(t,"x",0),this.floatInput(t,"y",0),this.floatInput(t,"z",0),this.floatInput(t,"w",0))}});case"compose.rgba":return this.output(t,{value:{type:"rgba",value:$t(this.floatInput(t,"r",1),this.floatInput(t,"g",1),this.floatInput(t,"b",1),this.floatInput(t,"a",1))}});case"decompose.component":{const e=this.expectNumeric(this.input(t,"value")),a=String(Ge(t,"component","x"));return this.output(t,{value:{type:"float",value:Pe(e,a,t.id)}})}case"decompose.split":{const e=this.expectNumeric(this.input(t,"value"));return this.output(t,function(t,e){const a={},r=(r,u)=>{a[r]={type:"float",value:Pe(t,u,e)}};switch(t.type){case"vec2":return r("x","x"),r("y","y"),r("u","x"),r("v","y"),a;case"vec3":return r("x","x"),r("y","y"),r("z","z"),a;case"rgb":return r("r","r"),r("g","g"),r("b","b"),r("x","x"),r("y","y"),r("z","z"),a;case"vec4":return r("x","x"),r("y","y"),r("z","z"),r("w","w"),a;case"rgba":return r("r","r"),r("g","g"),r("b","b"),r("a","a"),r("x","x"),r("y","y"),r("z","z"),r("w","w"),a;case"float":return a.x={type:"float",value:t.value},a}}(e,t.id))}case"color.gradient":{const e=this.expectType(this.input(t,"t",{type:"float",value:D(.5)}),["float"],t.id,"t"),a=_(function(t){const e=Ge(t,"stops",[]);if(!Array.isArray(e))return[];const a=e.map((t,a)=>{if(null==t||"object"!=typeof t||Array.isArray(t))return;const r=t,u="string"==typeof r.color?r.color:"#ffffff";return{position:De(r.position,_e(a,e.length)),color:u,alpha:De(r.alpha,1)}}).filter(t=>null!=t);return a.length>0?a:[]}(t)).sample(e.value);return this.output(t,{value:{type:"rgba",value:a}})}case"utility.curve":{const e=this.expectType(this.input(t,"t",{type:"float",value:D(.5)}),["float"],t.id,"t"),a=Ge(t,"curve","Linear"),r=Y(a,e.value)??W(we.decode(a)).sample(e.value);return this.output(t,{value:{type:"float",value:r}})}case"color.hueShift":{const e=this.expectType(this.input(t,"color"),["rgba","rgb","vec4","vec3"],t.id,"color"),a=e.value,r="rgba"===e.type||"vec4"===e.type?a.rgb??a.xyz:a,u=this.floatInput(t,"shift",0),i=Dt(r,u);return"rgba"===e.type||"vec4"===e.type?this.output(t,{value:{type:e.type,value:$t(i,a.a??a.w)}}):this.output(t,{value:{type:e.type,value:i}})}case"color.blend":{const e=this.expectType(this.input(t,"base"),["rgba","rgb","vec4","vec3"],t.id,"base"),a=this.expectType(this.input(t,"blend"),["rgba","rgb","vec4","vec3"],t.id,"blend"),r=String(Ge(t,"mode","multiply")),u=e.value,i=a.value,o="rgba"===e.type||"vec4"===e.type?u.rgb??u.xyz:u,n="rgba"===a.type||"vec4"===a.type?i.rgb??i.xyz:i;let s=Lt(o,n,r);if("rgba"===a.type||"vec4"===a.type){const t=i.a??i.w;s=at(o,s,t)}if("rgba"===e.type||"vec4"===e.type){const a=u.a??u.w;return this.output(t,{value:{type:e.type,value:$t(s,a)}})}return this.output(t,{value:{type:e.type,value:s}})}case"color.desaturate":{const e=this.expectType(this.input(t,"color"),["rgba","rgb","vec4","vec3"],t.id,"color"),a=e.value,r="rgba"===e.type||"vec4"===e.type?a.rgb??a.xyz:a,u=this.floatInput(t,"fraction",1),i=qt(r,u);return"rgba"===e.type||"vec4"===e.type?this.output(t,{value:{type:e.type,value:$t(i,a.a??a.w)}}):this.output(t,{value:{type:e.type,value:i}})}case"color.unpackNormal":{const e=this.expectType(this.input(t,"color"),["vec3","vec4","rgb","rgba"],t.id,"color"),a=this.floatInput(t,"scale",1),r=this.optionalInput(t,"normal");return this.output(t,{value:{type:"vec3",value:B(e.value,a,r?this.expectType(r,["vec3"],t.id,"normal").value:void 0)}})}case"texture.sampler2d":{const e=this.input(t,"texture");return this.output(t,{value:this.toSampler(e,t.id)})}case"texture.sample2d":{const e=this.toSampler(this.input(t,"sampler"),t.id),a=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv"),r=e.value.sample(a.value);return this.output(t,{rgba:{type:"rgba",value:r},rgb:{type:"rgb",value:r.rgb},r:{type:"float",value:r.r},g:{type:"float",value:r.g},b:{type:"float",value:r.b},a:{type:"float",value:r.a}})}case"texture.triplanarMapping":{const e=this.input(t,"sampler"),a=this.toSampler(e,t.id),r=this.expectType(this.input(t,"scale",{type:"float",value:D(1)}),["float"],t.id,"scale"),u=this.expectType(this.input(t,"normal",{type:"vec3",value:Gt.normal}),["vec3"],t.id,"normal"),i=this.expectType(this.input(t,"position",{type:"vec3",value:Gt.position}),["vec3"],t.id,"position"),o=Mt(a.value,r.value,u.value,i.value);return this.output(t,{rgba:{type:"rgba",value:o},rgb:{type:"rgb",value:o.rgb},r:{type:"float",value:o.r},g:{type:"float",value:o.g},b:{type:"float",value:o.b},a:{type:"float",value:o.a}})}case"scene.sampleColor":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:Qt}),["vec2"],t.id,"uv"),a=te(e.value);return this.output(t,{rgba:{type:"rgba",value:a},rgb:{type:"rgb",value:a.rgb},r:{type:"float",value:a.r},g:{type:"float",value:a.g},b:{type:"float",value:a.b},a:{type:"float",value:a.a}})}case"scene.sampleDepth":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:Qt}),["vec2"],t.id,"uv");return this.output(t,{depth:{type:"float",value:Jt(e.value)},linearEyeDepth:{type:"float",value:Kt(e.value)}})}case"scene.fragmentDepth":return this.output(t,{linearEyeDepth:{type:"float",value:Yt}});case"transform.translate":{const e=this.expectType(this.input(t,"offset",{type:"vec3",value:Bt(0,0,0)}),["vec3","rgb"],t.id,"offset");return this.output(t,{value:{type:"mat4",value:St(e.value)}})}case"transform.scale":{const e=this.expectType(this.input(t,"scale",{type:"vec3",value:Bt(1,1,1)}),["vec3","rgb"],t.id,"scale").value;return this.output(t,{value:{type:"mat4",value:gt(e.x,e.y,e.z)}})}case"transform.rotateAxis":{const e=this.expectType(this.input(t,"axis",{type:"vec3",value:Bt(0,1,0)}),["vec3","rgb"],t.id,"axis"),a=this.expectType(this.input(t,"angle",{type:"float",value:D(0)}),["float"],t.id,"angle");return this.output(t,{value:{type:"mat4",value:ne(e.value,a.value)}})}case"uv.rotate":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"angle",{type:"float",value:D(0)}),["float"],t.id,"angle").value,r=this.expectType(this.input(t,"center",{type:"vec2",value:Ut(.5,.5)}),["vec2"],t.id,"center").value;return this.output(t,{value:{type:"vec2",value:ke(e,a,r)}})}case"uv.twirl":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"strength",{type:"float",value:D(1)}),["float"],t.id,"strength").value,r=this.expectType(this.input(t,"center",{type:"vec2",value:Ut(.5,.5)}),["vec2"],t.id,"center").value,u=this.expectType(this.input(t,"offset",{type:"vec2",value:Ut(0,0)}),["vec2"],t.id,"offset").value;return this.output(t,{value:{type:"vec2",value:Ct(e,a,r,u)}})}case"uv.radial":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=At(e.subtractScalar(.5));return this.output(t,{coords:{type:"vec2",value:a.coords},radius:{type:"float",value:a.radius},angle:{type:"float",value:a.angle}})}case"uv.bulge":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.expectType(this.input(t,"center",{type:"vec2",value:Ut(.5,.5)}),["vec2"],t.id,"center").value,r=this.expectType(this.input(t,"power",{type:"float",value:D(1)}),["float"],t.id,"power").value;return this.output(t,{value:{type:"vec2",value:N(e,a,r)}})}case"uv.flipbook":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"columns",Ue(t,"columns",1)),r=this.floatInput(t,"rows",Ue(t,"rows",1)),u=this.floatInput(t,"fps",Ue(t,"fps",60)),i=this.expectType(this.input(t,"time",{type:"float",value:Tt.elapsed}),["float"],t.id,"time").value,o=String(Ge(t,"mode","clamp"));return this.output(t,{value:{type:"vec2",value:se(e,a,r,i,u,o)}})}case"uv.pom":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.input(t,"heightMap"),r=this.toSampler(a,t.id).value,u=this.floatInput(t,"heightScale",.05),i=Ue(t,"minLayers",8),o=Ue(t,"maxLayers",24);return this.output(t,{value:{type:"vec2",value:le(e,r,u,i,o)}})}case"shape.rectangle":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value;return this.output(t,{value:{type:"float",value:Ft(e,this.floatInput(t,"width",.5),this.floatInput(t,"height",.5))}})}case"shape.roundedRectangle":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value;return this.output(t,{value:{type:"float",value:Rt(e,this.floatInput(t,"width",.5),this.floatInput(t,"height",.5),this.floatInput(t,"radius",.1))}})}case"noise.simplex":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"scale",8);return this.output(t,{value:{type:"float",value:new ie(e.multiplyScalar(a))}})}case"noise.voronoi2d":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv").value,a=this.floatInput(t,"scale",8);return this.output(t,{value:{type:"float",value:new oe(e.multiplyScalar(a))}})}case"effect.fresnel":return this.output(t,{value:{type:"float",value:C(Wt(this.floatInput(t,"power",1)))}});case"effect.edgeDepth":{const e=this.floatInput(t,"power",1);return this.output(t,{value:{type:"float",value:_t(e)}})}case"effect.depthFade":{const e=this.floatInput(t,"distance",1);return this.output(t,{value:{type:"float",value:Ht(e)}})}case"util.panner":{const e=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"coord"),a=this.expectType(this.input(t,"speed",{type:"vec2",value:Ut(0,0)}),["vec2"],t.id,"speed"),r=this.expectType(this.input(t,"tile",{type:"vec2",value:Ut(1,1)}),["vec2"],t.id,"tile"),u=this.expectType(this.input(t,"time",{type:"float",value:Tt.elapsed}),["float"],t.id,"time");return this.output(t,{value:{type:"vec2",value:e.value.multiply(r.value).add(a.value.multiplyScalar(u.value))}})}}}compileParameterNode(t){const e=String(Ge(t,"parameter","")),a=this.graph.parameters?.find(t=>t.name===e||t.id===e);if(null==a)throw new ShaderGraphCompileError(`Parameter "${e}" does not exist`,t.id);const r=ve(a.type),u={type:r,value:$e(this.options.parameters?.[a.name]??a.defaultValue,r,a.name)};if("sampler2d"!==r)return{value:u};const i=this.expectType(this.input(t,"uv",{type:"vec2",value:this.defaultUV()}),["vec2"],t.id,"uv"),o=u.value.sample(i.value);return{value:{type:"rgba",value:o},rgb:{type:"rgb",value:o.rgb},r:{type:"float",value:o.r},g:{type:"float",value:o.g},b:{type:"float",value:o.b},a:{type:"float",value:o.a},sampler:u}}compileBinaryMath(t){const e=this.expectBinaryMathValue(this.input(t,"a")),a=this.expectBinaryMathValue(this.input(t,"b")),r=t.kind.split(".")[1];if("mat4"===e.type||"mat4"===a.type)return function(t,e,a,r){if("mat4"===t.type&&"mat4"===e.type&&"divide"!==a)return{type:"mat4",value:ze(t.value,e.value,a,r)};if("mat4"===t.type&&"float"===e.type&&("multiply"===a||"divide"===a))return{type:"mat4",value:ze(t.value,e.value,a,r)};if("float"===t.type&&"mat4"===e.type&&"multiply"===a)return{type:"mat4",value:ze(e.value,t.value,a,r)};if("mat4"===t.type&&"vec4"===e.type&&"multiply"===a)return{type:"vec4",value:t.value.multiplyVec(e.value)};throw new ShaderGraphCompileError(`Cannot ${a} ${t.type} and ${e.type}`,r)}(e,a,r,t.id);if(e.type===a.type)return{type:e.type,value:ze(e.value,a.value,r,t.id)};if("float"===e.type&&"float"!==a.type&&"multiply"===r)return{type:a.type,value:ze(a.value,e.value,r,t.id)};if("float"!==e.type&&"float"===a.type)return{type:e.type,value:ze(e.value,a.value,r,t.id)};throw new ShaderGraphCompileError(`Cannot ${r} ${e.type} and ${a.type}`,t.id)}expectBinaryMathValue(t){if(!Ae(t.type)&&"mat4"!==t.type)throw new ShaderGraphCompileError(`Expected a numeric value but got ${t.type}`);return t}compileUnaryMath(t,e){const a=this.expectNumeric(this.input(t,"value"));return{type:a.type,value:e(a.value)}}compileAtan2(t){const e=this.expectNumeric(this.input(t,"y")),a=this.expectNumeric(this.input(t,"x"));return{type:function(t,e,a){if(t===e)return t;if("rgb"===t&&"vec3"===e||"vec3"===t&&"rgb"===e)return"vec3";if("rgba"===t&&"vec4"===e||"vec4"===t&&"rgba"===e)return"vec4";throw new ShaderGraphCompileError(`Cannot mix ${t} and ${e}`,a)}(e.type,a.type,t.id),value:M(e.value,a.value)}}compileBinaryFunction(t,e,a=!1){const r=this.expectNumeric(this.input(t,"a")),u=this.expectNumeric(this.input(t,"b"));return{type:a&&"float"===u.type?r.type:Ve(r.type,u.type,t.id),value:e(r.value,u.value)}}compilePaintedLayerMix(t){const e=this.expectNumeric(this.input(t,"base")),a=[e.value],r=[zt(0)];let u=e.type;for(let e=1;e<=8;e++){const i=this.optionalInput(t,`layer${e}`);if(null==i)continue;const o=this.expectNumeric(i);u=Ve(u,o.type,t.id),a.push(o.value),r.push(zt(e))}return 1===a.length?e:{type:u,value:rt({layerColors:a,layerWeights:r,enableNoise:Boolean(Ge(t,"enableNoise",!0)),noiseScale:this.floatInput(t,"noiseScale",Ue(t,"noiseScale",.1)),noiseAmount:this.floatInput(t,"noiseAmount",Ue(t,"noiseAmount",.5)),decay:this.floatInput(t,"softness",Ue(t,"softness",.3)),mode:"hard"===String(Ge(t,"mode","soft"))?K.hard:K.soft})}}defaultUV(){return"trail"===this.graph.target?ue:"decal"===this.graph.target?ae:C(S.uv)}input(t,e,a){const r=t.inputs?.[e];if(null!=r)return this.resolveInput(r,t.id,e);const u=(this.graph.edges??[]).find(a=>a.to.nodeId===t.id&&a.to.port===e);if(null!=u)return this.resolveSocket(u.from,t.id,e);if(null!=a)return a;const i=this.inlineLiteralFallback(t,e);if(null!=i)return i;throw new ShaderGraphCompileError(`Missing input "${e}"`,t.id,e)}optionalInput(t,e){const a=t.inputs?.[e];if(null!=a)return this.resolveInput(a,t.id,e);const r=(this.graph.edges??[]).find(a=>a.to.nodeId===t.id&&a.to.port===e);return null!=r?this.resolveSocket(r.from,t.id,e):void 0}floatInput(t,e,a){return this.expectType(this.input(t,e,{type:"float",value:D(a)}),["float"],t.id,e).value}boolInput(t,e,a){return this.expectType(this.input(t,e,{type:"boolean",value:E(a)}),["boolean"],t.id,e).value}compileComparison(t){const e=this.expectType(this.input(t,"a"),["float"],t.id,"a").value,a=this.expectType(this.input(t,"b"),["float"],t.id,"b").value;switch(t.kind){case"compare.greaterThan":return e.gt(a);case"compare.greaterThanOrEqual":return e.gte(a);case"compare.lessThan":return e.lt(a);case"compare.lessThanOrEqual":return e.lte(a);case"compare.equal":return e.equals(a);case"compare.notEqual":return e.notEquals(a)}throw new ShaderGraphCompileError(`Unsupported comparison node "${t.kind}"`,t.id)}compileBooleanBinary(t,e){const a=this.boolInput(t,"a",!1),r=this.boolInput(t,"b",!1);return"and"===e?a.and(r):a.or(r)}resolveOutputBinding(t,e){if(null!=t.input)return this.resolveSocket(t.input,void 0,e);if(void 0!==t.value)return Be(t.value);throw new ShaderGraphCompileError(`Output "${e}" is missing an input or value`)}floatOutput(t,e){return this.expectType(this.resolveOutputBinding(t,e),["float"],e).value}resolveInput(t,e,a){return function(t){return null!=t.nodeId}(t)?this.resolveSocket(t,e,a):Be(t.value,t.valueType)}inlineLiteralFallback(t,e){const a=he[t.kind]?.inputs.find(t=>t.name===e);if(null==a)return;const r=ce(t.kind,a),u=pe(t.kind,a);return null!=r&&void 0!==u?Be(u,r):void 0}resolveSocket(t,e,a){const r=this.compileNode(t.nodeId).outputs[t.port];if(null==r)throw new ShaderGraphCompileError(`Node "${t.nodeId}" does not have output "${t.port}"`,e??t.nodeId,a??t.port);return r}expectType(t,e,a,r){if(!e.includes(t.type))throw new ShaderGraphCompileError(`Expected ${e.join(" or ")} but got ${t.type}`,a,r);return t}expectNumeric(t){if(!Ae(t.type))throw new ShaderGraphCompileError(`Expected a numeric value but got ${t.type}`);return t}toSampler(t,e){if("sampler2d"===t.type)return t;if("texture2d"===t.type){const a=t.value;if(null==a)throw new ShaderGraphCompileError("Texture input is empty",e);return{type:"sampler2d",value:wt(a)}}throw new ShaderGraphCompileError(`Expected texture2d or sampler2d but got ${t.type}`,e)}toColorOutput(t){switch(t.type){case"float":case"vec2":case"vec3":case"vec4":case"rgb":case"rgba":return t.value;case"boolean":{const e=ht(t.value,D(1),D(0));return lt(Bt(e,e,e),1)}case"mat4":throw new ShaderGraphCompileError("mat4 values cannot be used as color");case"texture2d":case"sampler2d":throw new ShaderGraphCompileError(`${t.type} must be sampled before it can be used as color`)}}toVec3Output(t,e){if("vec3"===t.type||"rgb"===t.type)return t.value;if("vec4"===t.type||"rgba"===t.type)return t.value.xyz;throw new ShaderGraphCompileError(`Output "${e}" expects vec3/rgb but got ${t.type}`)}toMat4Output(t,e){if("mat4"===t.type)return t.value;throw new ShaderGraphCompileError(`Output "${e}" expects mat4 but got ${t.type}`)}output(t,e){return{node:t,outputs:e}}}export function compileShaderGraph(t,e={}){return new ShaderGraphCompiler(t,e).compile()}export function compileShaderGraphPreview(t,e,a={}){if(null==e)return compileShaderGraph(t,a).output;const r=new ShaderGraphCompiler(t,a).compileNode(e),u=Object.values(r.outputs)[0];if(null==u)throw new ShaderGraphCompileError(`Node "${e}" has no previewable output`,e);return{color:Me(u),transparent:"rgba"===u.type||"vec4"===u.type}}export function buildShaderGraphMaterial(t,a={}){if("postProcess"===t.target)return buildShaderGraphPostProcessMaterial(t,a);const r=null!=a.previewNodeId?compileShaderGraphPreview(t,a.previewNodeId,a):compileShaderGraph(t,a).output;if("sprite"===t.target)return new Vt({color:r.color,discard:r.discard,transparent:r.transparent??!0,position:kt(new f("rotation",0),new f("screenSpaceSize",0)),uniforms:{color:{value:new e(16777215)}}});if("trail"===t.target){const{position:e}=re.getTrailShaderNodes(a.trailBillboard??!1),u=new h({...r,position:e});return re.applyTrailShaderParameters(u),Oe(u,t),u}if("decal"===t.target){const e=null!=r.discard?ee.or(r.discard):ee,a=new h({...r,transparent:!1,discard:e});return a.userData.isDecal=!0,Oe(a,t),a}const u=new h({transparent:!1,...r});return Oe(u,t),u}export function buildShaderGraphPostProcessMaterial(t,e={}){const a=null!=e.previewNodeId?Te(compileShaderGraphPreview(t,e.previewNodeId,e).color):compileShaderGraph(t,e).output,r=new h({color:a.color,transparent:!1,fog:!1,lights:!1,outputEncoding:!1});return r.depthWrite=!1,r.depthTest=!1,r.toneMapped=!1,r.userData.isPostProcessShaderGraph=!0,r}function Te(t,e){const a=te(Qt),r=Nt("hology_post_process_weight",1),u=ct(null!=e?r.multiply(e):r);return{color:at(a.rgb,Ie(t),u),transparent:!1,...null!=e?{opacity:e}:{}}}function Ie(t){return t instanceof p?Bt(t,t,t):t instanceof g?Bt(t.x,t.y,0):t instanceof x?t.xyz:t}export function shaderGraphMaterialSideToThree(e){switch(e){case"back":return t;case"double":return a;default:return r}}function Se(t){return"decal"!==t.target&&(t.materialOptions?.transparent??"sprite"===t.target)}function Oe(t,e){"surface"===e.target&&(t.side=shaderGraphMaterialSideToThree(e.materialOptions?.side)),null!=e.materialOptions?.transparent&&(t.transparent=e.materialOptions.transparent),null!=e.materialOptions?.alphaTest&&0===t.alphaTest&&(t.alphaTest=e.materialOptions.alphaTest),null!=e.materialOptions?.bloom&&(t.userData.hasBloom=e.materialOptions.bloom)}function Me(t){switch(t.type){case"float":return Ce(t.value);case"vec2":{const e=t.value;return lt(Bt(e.x,e.y,0),1)}case"vec3":case"rgb":return lt(t.value,1);case"vec4":case"rgba":return t.value;case"boolean":return Ce(ht(t.value,D(1),D(0)));case"mat4":throw new ShaderGraphCompileError("mat4 values cannot be previewed as color");case"texture2d":case"sampler2d":throw new ShaderGraphCompileError(`${t.type} nodes require a sampled output to preview`)}}function Ce(t){return lt(Bt(t,t,t),1)}function Ne(t){return t instanceof p?Bt(t,t,t).rgb:t instanceof g?Bt(t.x,t.y,0).rgb:t}function Ee(t){return t.rgb}function Ge(t,e,a){const r=t.params?.[e];return void 0===r?a:r}function Ue(t,e,a){const r=Ge(t,e,a);return"number"==typeof r?r:Number(r??a)}function Be(t,e){if(null!=(a=t)&&"object"==typeof a&&!Array.isArray(a)&&"value"in a)return Be(t.value,t.valueType??e);var a;const r=e??function(t){if("boolean"==typeof t)return"boolean";if("number"==typeof t)return"float";if(Array.isArray(t))return 2===t.length?"vec2":3===t.length?"vec3":16===t.length?"mat4":"vec4";return"string"==typeof t?"rgb":"float"}(t);return{type:r,value:$e(t,r,"literal")}}function $e(t,a,r){switch(a){case"boolean":return t instanceof l?t:E(Boolean(t));case"float":return t instanceof p?t:D(De(t,0));case"vec2":return t instanceof g?t:qe(t);case"vec3":return t instanceof b?t:Fe(t);case"vec4":return t instanceof x?t:function(t){const[e,a,r,u]=Le(t,4,1);return $t(e,a,r,u)}(t);case"mat4":return t instanceof c?t:function(t){if(t instanceof u)return Z(t);const e=new u;Array.isArray(t)&&16===t.length&&e.fromArray(t.map(t=>De(t,0)));return Z(e)}(t);case"rgb":return t instanceof v?t:function(t){if("string"==typeof t||"number"==typeof t||t instanceof e)return pt(t);const[a,r,u]=Le(t,3);return Bt(a,r,u).rgb}(t);case"rgba":return t instanceof y||t instanceof x?t:Re(t);case"texture2d":return t;case"sampler2d":if(function(t){const e=t;return t instanceof m||t instanceof d||"function"==typeof e?.isSampler2D||!0===e?.isSampler2D}(t))return t;if(t instanceof i)return wt(t);throw new ShaderGraphCompileError(`Parameter "${r}" needs a texture value`)}}function ze(t,e,a,r){const u=`${a}Scalar`;if(e instanceof p&&"function"==typeof t[u])return t[u](e);if("function"==typeof t[a])return t[a](e);throw new ShaderGraphCompileError(`Node does not support ${a}`,r)}function Ve(t,e,a){if(t===e)return t;if("rgb"===t&&"vec3"===e||"vec3"===t&&"rgb"===e)return"vec3";if("rgba"===t&&"vec4"===e||"vec4"===t&&"rgba"===e)return"vec4";if("float"===t&&Ae(e))return e;if("float"===e&&Ae(t))return t;throw new ShaderGraphCompileError(`Cannot mix ${t} and ${e}`,a)}function ke(t,e,a){const r=t.subtract(a),u=yt(e),i=$(e);return Ut(i.multiply(r.x).subtract(u.multiply(r.y)).add(a.x),u.multiply(r.x).add(i.multiply(r.y)).add(a.y))}function Pe(t,e,a){const r=t.value["u"===e?"x":"v"===e?"y":e];if(r instanceof p)return r;throw new ShaderGraphCompileError(`Component "${e}" is not available on ${t.type}`,a)}function Ae(t){return"float"===t||"vec2"===t||"vec3"===t||"vec4"===t||"rgb"===t||"rgba"===t}function je(t){return Number.isFinite(t)?Math.min(1,Math.max(0,t)):0}function De(t,e){if("number"==typeof t)return t;if("string"==typeof t){const a=parseFloat(t);return Number.isFinite(a)?a:e}return"boolean"==typeof t?t?1:0:e}function Le(t,a,r=0){if(Array.isArray(t))return Array.from({length:a},(e,a)=>De(t[a],r));if(t instanceof o||t instanceof n||t instanceof s)return Array.from({length:a},(e,a)=>t.toArray()[a]??r);if(t instanceof e){const e=t.toArray();return Array.from({length:a},(t,a)=>e[a]??(3===a?1:r))}if(null!=t&&"object"==typeof t){const e=t,u=["x","y","z","w"];if(u.some(t=>null!=e[t]))return Array.from({length:a},(t,a)=>De(e[u[a]],r));const i=["r","g","b","a"];if(i.some(t=>null!=e[t]))return Array.from({length:a},(t,a)=>De(e[i[a]],3===a?1:r))}return Array.from({length:a},()=>De(t,r))}function qe(t){const[e,a]=Le(t,2);return Ut(e,a)}function Fe(t){const[e,a,r]=Le(t,3);return Bt(e,a,r)}function Re(t,a=1){if("string"==typeof t||"number"==typeof t||t instanceof e)return lt(t,a);if(t instanceof b)return lt(t,a);const[r,u,i,o]=Le(t,4,a);return $t(r,u,i,o)}function _e(t,e){return e<=1?0:t/(e-1)}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,25 +1,30 @@
1
1
  import 'reflect-metadata';
2
- import { Type } from '../utils/type.js';
2
+ import { AbstractType, Type } from '../utils/type.js';
3
3
  import { BaseActor } from '../gameplay/actors/actor.js';
4
4
  import { Color, Euler, Material, Object3D, Texture, Vector2, Vector3, Vector4, AnimationClip } from 'three';
5
5
  import { BooleanNode, FloatNode, RgbNode, Sampler2DNode, Vec2Node, Vec3Node, Vec4Node } from '../shader-nodes/index.js';
6
6
  import { VisualEffect } from '../effects/vfx/vfx-param.js';
7
7
  import { Prefab, PrefabOf } from '../scene/objects/prefab.js';
8
+ import { DataAssetRef } from '../scene/objects/data-asset.js';
8
9
  import { Curve2 } from '../utils/curve.js';
9
10
  import type { ColorLayer, MaskLayer } from './color-layer.js';
10
11
  import type { Sequence } from '../effects/sequence/sequence-data.js';
11
- export type ParameterType = Type<FloatNode | Number | Texture | Sampler2DNode | Boolean | BooleanNode | Vector2 | Vec2Node | Vector3 | Vec3Node | Vector4 | Vec4Node | Color | RgbNode | String | BaseActor | Euler | Object3D | Material | AnimationClip | VisualEffect | Sequence | Prefab | PrefabOf<BaseActor> | Curve2 | ColorLayer | MaskLayer>;
12
+ export type KnownParameterType = Type<FloatNode | Number | Texture | Sampler2DNode | Boolean | BooleanNode | Vector2 | Vec2Node | Vector3 | Vec3Node | Vector4 | Vec4Node | Color | RgbNode | String | BaseActor | Euler | Object3D | Material | AnimationClip | VisualEffect | Sequence | Prefab | PrefabOf<BaseActor> | DataAssetRef | Curve2 | ColorLayer | MaskLayer>;
13
+ export type ParameterType = Type<any> | AbstractType<any>;
14
+ export type ParameterTypeResolver = () => ParameterType;
12
15
  export type ParameterOption<T> = {
13
16
  name: string;
14
17
  value: T;
15
18
  };
19
+ export type ParameterEnum = Record<string, string | number>;
16
20
  export interface ParameterOptions {
17
21
  range?: [number, number];
18
22
  precision?: number;
19
23
  stepSize?: number;
20
- type?: ParameterType;
24
+ type?: ParameterType | ParameterTypeResolver;
21
25
  defaultValue?: unknown;
22
26
  options?: ParameterOption<unknown>[];
27
+ enum?: ParameterEnum;
23
28
  array?: boolean;
24
29
  /** The field name in the editor. It will otherwise be derived from the property name. */
25
30
  label?: string;
@@ -48,6 +53,11 @@ export interface ParameterOptions {
48
53
  * prefab: PrefabOf<BaseActor>
49
54
  */
50
55
  prefabOf?: Type<BaseActor>;
56
+ /**
57
+ * Restrict selectable data assets to definitions assignable to the given
58
+ * data asset definition class. Use together with DataAssetRef<T>.
59
+ */
60
+ dataAssetOf?: ParameterType | ParameterTypeResolver;
51
61
  /**
52
62
  * When set, the parameter can bind to a VFX asset-level input instead of using a constant value.
53
63
  * `spawn` means the bound value is sampled when particles are created.
@@ -59,8 +69,59 @@ export interface PropertyParameter {
59
69
  name: string;
60
70
  type: ParameterType;
61
71
  options: ParameterOptions;
72
+ definition?: ParameterDefinitionInfo;
73
+ }
74
+ export interface ParameterDefinitionInfo {
75
+ id: string;
76
+ type: ParameterType;
77
+ abstract?: boolean;
78
+ }
79
+ export interface AssignableParameterDefinitionInfo extends ParameterDefinitionInfo {
80
+ label: string;
81
+ }
82
+ export interface DataAssetDefinitionInfo {
83
+ id: string;
84
+ type: ParameterType;
85
+ abstract?: boolean;
86
+ }
87
+ export interface AssignableDataAssetDefinitionInfo extends DataAssetDefinitionInfo {
88
+ label: string;
89
+ }
90
+ export interface ParameterDefinitionOptions {
91
+ abstract?: boolean;
92
+ }
93
+ export interface GetAssignableParameterDefinitionsOptions {
94
+ includeAbstract?: boolean;
62
95
  }
63
96
  export declare function shaderParameterUniformName(parameterName: string): string;
97
+ /**
98
+ * Define a custom parameter type
99
+ * @param id A unique identifier for the parameter type used for serialization. The class name can change but this id should remain to ensure existing data can still be mapped to this class.
100
+ */
101
+ export declare function ParameterDefinition(id?: string, options?: ParameterDefinitionOptions): (targetConstructor: ParameterType) => void;
102
+ /**
103
+ * Define a reusable data asset root schema. Data asset definitions are kept
104
+ * separate from ParameterDefinition so inline structs do not automatically
105
+ * become creatable asset types.
106
+ */
107
+ export declare function DataAssetDefinition(id?: string, options?: ParameterDefinitionOptions): (targetConstructor: ParameterType) => void;
108
+ export declare function registerParameterDefinition(id: string, type: ParameterType, options?: ParameterDefinitionOptions): void;
109
+ export declare function getParameterDefinitionType(id: string): ParameterType | undefined;
110
+ export declare function registerDataAssetDefinition(id: string, type: ParameterType, options?: ParameterDefinitionOptions): void;
111
+ export declare function getDataAssetDefinitionType(id: string): ParameterType | undefined;
112
+ export declare function getAssignableDataAssetDefinitions(baseType: ParameterType | undefined | null, options?: GetAssignableParameterDefinitionsOptions): AssignableDataAssetDefinitionInfo[];
113
+ export declare function getDataAssetDefinitions(options?: GetAssignableParameterDefinitionsOptions): AssignableDataAssetDefinitionInfo[];
114
+ export declare function getAssignableParameterDefinitions(baseType: ParameterType | undefined | null, options?: GetAssignableParameterDefinitionsOptions): AssignableParameterDefinitionInfo[];
115
+ export declare function isParameterDefinitionAssignableTo(type: ParameterType | undefined | null, baseType: ParameterType | undefined | null): boolean;
116
+ export declare function isParameterDefinitionStructAssignableTo(structId: string | undefined | null, baseStructId: string | undefined | null): boolean;
117
+ export declare function isParameterDefinitionAbstract(typeOrId: ParameterType | string | undefined | null): boolean;
118
+ export declare function isDataAssetDefinitionAbstract(typeOrId: ParameterType | string | undefined | null): boolean;
119
+ export declare function getParameterDefinitionDisplayName(type: ParameterType | string): string;
120
+ export declare function getParameterDefinitionId(type: ParameterType | undefined | null): string | undefined;
121
+ export declare function getDataAssetDefinitionId(type: ParameterType | undefined | null): string | undefined;
122
+ export declare function getParameterDefinitionInfo(type: ParameterType | undefined | null): ParameterDefinitionInfo | undefined;
123
+ export declare function resolveParameterType(type: ParameterOptions['type']): ParameterType | undefined;
124
+ export declare function getDataAssetDefinitionInfo(type: ParameterType | undefined | null): DataAssetDefinitionInfo | undefined;
64
125
  export declare function Parameter(options?: ParameterOptions): (target: Object, propertyName: string | symbol, index?: unknown) => void;
65
126
  export declare function ParameterCategory(name: string): void;
66
127
  //# sourceMappingURL=parameter.d.ts.map
@@ -1,4 +1,4 @@
1
- import"reflect-metadata";import{reflect as t,decorateProperty as e}from"@plumier/reflect";import{ArrayMap as r}from"../utils/collections.js";Symbol("format");export function shaderParameterUniformName(t){return`pu_${t}`}class a{constructor(t){this.options=t,this.isParameterDecorator=!0}}new Map;const o=new r;export function Parameter(t){return function(r,n,p){if(null!=r){o.push(r.constructor,{name:n,options:t??{}});try{e(new a(t))(r,n,p)}catch(t){console.warn("Failed to decorate method ",r,n,p)}}}}export function extractShaderParameters(t){if(null==t)return[];const e=o.get(t).map(({name:e,options:r})=>{const a=Reflect.getMetadata("design:type",t.prototype,e),o=r.type??a,n=Reflect.getMetadata("prefab:type",t.prototype,e);return r.prefabOf??(r.prefabOf=n),r.array=a===Array,{name:e,type:o,options:r}});return[...extractShaderParameters(Object.getPrototypeOf(t)).filter(t=>e.every(e=>e.name!==t.name)),...e]}export function ParameterCategory(t){}/*
1
+ import"reflect-metadata";import{reflect as e,decorateProperty as t}from"@plumier/reflect";import{ArrayMap as n}from"../utils/collections.js";Symbol("format");const r=Symbol("parameterDefinition"),a=Symbol("dataAssetDefinition");export function shaderParameterUniformName(e){return`pu_${e}`}class i{constructor(e){this.options=e,this.isParameterDecorator=!0}}new Map;const o=new n,s=new Map,f=new Map,l=new WeakMap,p=new Map,u=new Map,c=new WeakMap;export function ParameterDefinition(e,t={}){return function(n){registerParameterDefinition(e??n.name,n,t)}}export function DataAssetDefinition(e,t={}){return function(n){registerDataAssetDefinition(e??n.name,n,t)}}export function registerParameterDefinition(e,t,n={}){if(null==e||""===e.trim())throw new Error("Parameter definition id must be a non-empty string");const a=s.get(e);null!=a&&a!==t&&console.warn(`Replacing parameter definition "${e}"`,{existing:a,type:t}),s.set(e,t),f.set(e,{id:e,type:t,...!0===n.abstract?{abstract:!0}:{}}),l.set(t,e),Reflect.defineMetadata(r,f.get(e),t)}export function getParameterDefinitionType(e){return s.get(e)}export function registerDataAssetDefinition(e,t,n={}){if(null==e||""===e.trim())throw new Error("Data asset definition id must be a non-empty string");const r=p.get(e);null!=r&&r!==t&&console.warn(`Replacing data asset definition "${e}"`,{existing:r,type:t}),p.set(e,t),u.set(e,{id:e,type:t,...!0===n.abstract?{abstract:!0}:{}}),c.set(t,e),Reflect.defineMetadata(a,u.get(e),t)}export function getDataAssetDefinitionType(e){return p.get(e)}export function getAssignableDataAssetDefinitions(e,t={}){if(null==e)return[];const n=getDataAssetDefinitionId(e);return Array.from(p.entries()).filter(([,t])=>isParameterDefinitionAssignableTo(t,e)).filter(([e])=>!0===t.includeAbstract||!isDataAssetDefinitionAbstract(e)).map(([e,t])=>({id:e,type:t,label:getParameterDefinitionDisplayName(t)})).sort((e,t)=>e.id===n?-1:t.id===n?1:e.label.localeCompare(t.label))}export function getDataAssetDefinitions(e={}){return Array.from(p.entries()).filter(([t])=>!0===e.includeAbstract||!isDataAssetDefinitionAbstract(t)).map(([e,t])=>({id:e,type:t,label:getParameterDefinitionDisplayName(t)})).sort((e,t)=>e.label.localeCompare(t.label))}export function getAssignableParameterDefinitions(e,t={}){if(null==e)return[];const n=getParameterDefinitionId(e);return Array.from(s.entries()).filter(([,t])=>isParameterDefinitionAssignableTo(t,e)).filter(([e])=>!0===t.includeAbstract||!isParameterDefinitionAbstract(e)).map(([e,t])=>({id:e,type:t,label:getParameterDefinitionDisplayName(t)})).sort((e,t)=>e.id===n?-1:t.id===n?1:e.label.localeCompare(t.label))}export function isParameterDefinitionAssignableTo(e,t){return null!=e&&null!=t&&(e===t||e.prototype instanceof t)}export function isParameterDefinitionStructAssignableTo(e,t){return null!=e&&null!=t&&(e===t||isParameterDefinitionAssignableTo(getParameterDefinitionType(e),getParameterDefinitionType(t)))}export function isParameterDefinitionAbstract(e){if(null==e)return!1;const t="string"==typeof e?f.get(e):getParameterDefinitionInfo(e);return!0===t?.abstract}export function isDataAssetDefinitionAbstract(e){if(null==e)return!1;const t="string"==typeof e?u.get(e):getDataAssetDefinitionInfo(e);return!0===t?.abstract}export function getParameterDefinitionDisplayName(e){return("string"==typeof e?e:e.name).replace(/Definition$/,"").replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1 $2").replace(/[_-]+/g," ").trim().split(/\s+/).filter(e=>e.length>0).map(e=>e.length<=2&&e===e.toUpperCase()?e:e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}export function getParameterDefinitionId(e){if(null!=e)return l.get(e)??Reflect.getMetadata(r,e)?.id}export function getDataAssetDefinitionId(e){if(null!=e)return c.get(e)??Reflect.getMetadata(a,e)?.id}export function getParameterDefinitionInfo(e){if(null==e)return;const t=getParameterDefinitionId(e);return null!=t?f.get(t)??Reflect.getMetadata(r,e)??{id:t,type:e}:void 0}export function resolveParameterType(e){if(null!=e)return"function"==typeof e&&null==e.prototype?e():e}function m(e,t){const{enum:n,...r}=e,a=n??t;if(null==a||r.options?.length>0)return r;const i=function(e){return Object.entries(e).filter(([e])=>!function(e){return""!==e.trim()&&String(Number(e))===e}(e)).map(([e,t])=>({name:getParameterDefinitionDisplayName(e),value:t}))}(a);return{...r,type:r.type??g(i),defaultValue:void 0!==r.defaultValue?r.defaultValue:i[0]?.value,options:i}}function g(e){const t=new Set(e.map(e=>typeof e.value));if(1===t.size)return t.has("number")?Number:t.has("string")?String:void 0}export function getDataAssetDefinitionInfo(e){if(null==e)return;const t=getDataAssetDefinitionId(e);return null!=t?u.get(t)??Reflect.getMetadata(a,e)??{id:t,type:e}:void 0}export function Parameter(e){return function(n,r,a){if(null!=n){o.push(n.constructor,{name:r,options:e??{}});try{t(new i(e))(n,r,a)}catch(e){console.warn("Failed to decorate method ",n,r,a)}}}}export function extractShaderParameters(e){if(null==e)return[];const t=o.get(e).map(({name:t,options:n})=>{const r=Reflect.getMetadata("parameter:enum",e.prototype,t),a=Reflect.getMetadata("parameter:array",e.prototype,t),i=Reflect.getMetadata("parameter:arrayElementType",e.prototype,t),o=Reflect.getMetadata("parameter:dataAssetOf",e.prototype,t),s=m(n,r),f=Reflect.getMetadata("design:type",e.prototype,t),l=!0===s.array||!0===a||f===Array,p=resolveParameterType(s.type)??(l?i:void 0)??f,u=Reflect.getMetadata("prefab:type",e.prototype,t);return s.prefabOf??(s.prefabOf=u),s.dataAssetOf??(s.dataAssetOf=o),s.array=l,{name:t,type:p,options:s,definition:getParameterDefinitionInfo(p)}});return[...extractShaderParameters(Object.getPrototypeOf(e)).filter(e=>t.every(t=>t.name!==e.name)),...t]}export function ParameterCategory(e){}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data-asset-definition.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{__decorate as e,__metadata as t}from"tslib";import{describe as a,expect as s,it as i,vi as o}from"vitest";o.hoisted(()=>{if("undefined"==typeof HTMLCanvasElement)return;const e=new Proxy({},{get:(e,t)=>(t in e||(e[t]=("string"!=typeof t||!t.startsWith("is"))&&o.fn()),e[t]),set:(e,t,a)=>(e[t]=a,!0)});Object.defineProperty(HTMLCanvasElement.prototype,"getContext",{configurable:!0,value:()=>e}),"undefined"==typeof AudioBuffer&&Object.defineProperty(globalThis,"AudioBuffer",{configurable:!0,value:class{}})}),o.mock("../gameplay/actors/builtin/index.js",()=>({default:{}})),o.mock("../effects/vfx/vfx-actor.js",()=>({VfxActor:class{}})),o.mock("../effects/vfx/vfx-param.js",()=>({VisualEffect:class{}})),o.mock("../rendering.js",()=>({RenderingView:class{},setRenderingPaused:o.fn()}));import{prepareClassParameters as n,prepareCustomParamsFromType as r,materializeDataAssetRef as d}from"../scene/materializer.js";import{SerializedParamType as m}from"../scene/model.js";import{DataAssetRef as l}from"../scene/objects/data-asset.js";import{DataAssetDefinition as p,getAssignableDataAssetDefinitions as c,getDataAssetDefinitionId as f,getDataAssetDefinitions as u,getDataAssetDefinitionType as y,isDataAssetDefinitionAbstract as v,Parameter as g,ParameterDefinition as B}from"../shader/parameter.js";let w=class{constructor(){this.amount=1}};e([g({type:Number}),t("design:type",Object)],w.prototype,"amount",void 0),w=e([B("test.data.statModifier")],w);let b=class{constructor(){this.displayName="Item"}};e([g({type:String}),t("design:type",Object)],b.prototype,"displayName",void 0),b=e([p("test.data.item",{abstract:!0})],b);let A=class extends b{constructor(){super(...arguments),this.damage=5,this.modifier=new w}};e([g({type:Number}),t("design:type",Object)],A.prototype,"damage",void 0),e([g({type:()=>w}),t("design:type",Object)],A.prototype,"modifier",void 0),A=e([p("test.data.weapon")],A);let h=class extends b{constructor(){super(...arguments),this.charges=1}};e([g({type:Number}),t("design:type",Object)],h.prototype,"charges",void 0),h=e([p("test.data.consumable")],h);class j{constructor(){this.item=null,this.items=[]}}e([g({type:()=>l,dataAssetOf:()=>b}),t("design:type",l)],j.prototype,"item",void 0),e([g({type:()=>l,dataAssetOf:()=>b,array:!0}),t("design:type",Array)],j.prototype,"items",void 0);class N{constructor(){this.items=[]}}function D(e){const t=new Map(e.map(e=>[e.id,e]));return{getAsset:o.fn(async e=>t.get(e)??null),getAssets:o.fn(async()=>e)}}e([g(),t("design:type",Array)],N.prototype,"items",void 0),Reflect.defineMetadata("design:type",Array,N.prototype,"items"),Reflect.defineMetadata("parameter:arrayElementType",l,N.prototype,"items"),Reflect.defineMetadata("parameter:dataAssetOf",b,N.prototype,"items"),a("data asset definitions",()=>{i("registers data asset definitions separately from parameter definitions",()=>{s(y("test.data.item")).toBe(b),s(f(A)).toBe("test.data.weapon"),s(v(b)).toBe(!0),s(v("test.data.item")).toBe(!0);const e=c(b);s(e.map(e=>e.id)).toEqual(["test.data.consumable","test.data.weapon"]);const t=u({includeAbstract:!0});s(t.some(e=>"test.data.item"===e.id)).toBe(!0),s(t.some(e=>"test.data.statModifier"===e.id)).toBe(!1),s(y("test.data.statModifier")).toBeUndefined()}),i("serializes data asset references as asset ids, including arrays",()=>{const e=r(j,{}),t=e.item,a=e.items;s(t.type).toBe(m.DataAsset),s(t.value).toBeNull(),s(a.type).toBe(m.Array),s(a.element).toBe(m.DataAsset),s(a.value).toEqual([])}),i("uses reflected metadata for data asset reference arrays",()=>{const e=r(N,{}).items;s(e.type).toBe(m.Array),s(e.element).toBe(m.DataAsset),s(e.value).toEqual([])}),i("materializes a data asset reference into a wrapper with nested inline structs",async()=>{const e={id:"asset.weapon",name:"Bronze Sword",type:"data",dataAsset:{definition:"test.data.weapon",params:{displayName:{type:m.String,value:"Bronze Sword"},damage:{type:m.Number,value:12},modifier:{type:m.Struct,struct:"test.data.statModifier",value:{amount:{type:m.Number,value:3}}}}}},t=D([e]),a=await n({item:{type:m.DataAsset,value:e.id},items:{type:m.Array,element:m.DataAsset,value:[e.id]}},j,t,{}),i=a.item;s(i).toBeInstanceOf(l),s(i.id).toBe(e.id),s(i.name).toBe("Bronze Sword"),s(i.asset).toBe(e),s(i.definitionId).toBe("test.data.weapon"),s(i.value).toBeInstanceOf(A),s(i.value.displayName).toBe("Bronze Sword"),s(i.value.damage).toBe(12),s(i.value.modifier).toBeInstanceOf(w),s(i.value.modifier.amount).toBe(3),s(a.items).toHaveLength(1),s(a.items[0].value.damage).toBe(12)}),i("resolves missing and invalid data asset references safely",async()=>{const e=o.spyOn(console,"warn").mockImplementation(()=>{}),t=D([{id:"asset.notData",name:"Texture pretending",type:"texture"},{id:"asset.unknownDefinition",name:"Unknown Definition",type:"data",dataAsset:{definition:"test.data.unknown",params:{}}},{id:"asset.abstractDefinition",name:"Abstract Definition",type:"data",dataAsset:{definition:"test.data.item",params:{}}},{id:"asset.invalidParams",name:"Invalid Params",type:"data",dataAsset:{definition:"test.data.weapon",params:"bad"}}]);await s(d("asset.missing",t,{})).resolves.toBeNull(),await s(d("asset.notData",t,{})).resolves.toBeNull(),await s(d("asset.unknownDefinition",t,{})).resolves.toBeNull(),await s(d("asset.abstractDefinition",t,{})).resolves.toBeNull(),await s(d("asset.invalidParams",t,{})).resolves.toBeNull();const a=await n({item:{type:m.DataAsset,value:"asset.missing"}},j,t,{});s(a.item).toBeUndefined(),s(e).toHaveBeenCalled(),e.mockRestore()})});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parameter-definition.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{__decorate as t,__metadata as e}from"tslib";import{describe as a,expect as s,it as o,vi as i}from"vitest";i.hoisted(()=>{if("undefined"==typeof HTMLCanvasElement)return;const t=new Proxy({},{get:(t,e)=>(e in t||(t[e]=("string"!=typeof e||!e.startsWith("is"))&&i.fn()),t[e]),set:(t,e,a)=>(t[e]=a,!0)});Object.defineProperty(HTMLCanvasElement.prototype,"getContext",{configurable:!0,value:()=>t}),"undefined"==typeof AudioBuffer&&Object.defineProperty(globalThis,"AudioBuffer",{configurable:!0,value:class{}})}),i.mock("../gameplay/actors/builtin/index.js",()=>({default:{}})),i.mock("../effects/vfx/vfx-actor.js",()=>({VfxActor:class{}})),i.mock("../effects/vfx/vfx-param.js",()=>({VisualEffect:class{}})),i.mock("../rendering.js",()=>({RenderingView:class{},setRenderingPaused:i.fn()}));import{convertConfiguredParamValueToRuntimeType as r}from"../scene/custom-param-runtime-types.js";import{prepareClassParameters as n,prepareCustomParamsFromType as c}from"../scene/materializer.js";import{SerializedParamType as l}from"../scene/model.js";import{extractShaderParameters as u,getAssignableParameterDefinitions as p,isParameterDefinitionAbstract as m,Parameter as y,ParameterDefinition as d}from"../shader/parameter.js";let b=class{constructor(){this.damage=10,this.label="Slash"}kind(){return"attack"}};t([y({type:Number}),e("design:type",Object)],b.prototype,"damage",void 0),t([y({type:String}),e("design:type",Object)],b.prototype,"label",void 0),b=t([d("test.attack")],b);let g=class extends b{constructor(){super(...arguments),this.manaCost=5}kind(){return"magic"}};t([y({type:Number}),e("design:type",Object)],g.prototype,"manaCost",void 0),g=t([d("test.magicAttack")],g);let v=class{constructor(){this.amount=20}};t([y({type:Number}),e("design:type",Object)],v.prototype,"amount",void 0),v=t([d("test.heal")],v);class f{constructor(){this.attacks=[]}}t([y({type:()=>b,array:!0}),e("design:type",Array)],f.prototype,"attacks",void 0);class k{constructor(){this.attacks=[]}}t([y(),e("design:type",Array)],k.prototype,"attacks",void 0),Reflect.defineMetadata("design:type",Array,k.prototype,"attacks"),Reflect.defineMetadata("parameter:arrayElementType",b,k.prototype,"attacks");class B{constructor(){this.primaryAttack=new b}}t([y({type:()=>b}),e("design:type",Object)],B.prototype,"primaryAttack",void 0);let h=class{constructor(){this.cooldown=1}};t([y({type:Number}),e("design:type",Object)],h.prototype,"cooldown",void 0),h=t([d("test.ability",{abstract:!0})],h);let A=class extends h{constructor(){super(...arguments),this.manaCost=6}kind(){return"magicAbility"}};t([y({type:Number}),e("design:type",Object)],A.prototype,"manaCost",void 0),A=t([d("test.magicAbility")],A);class S{constructor(){this.ability=void 0}}t([y({type:()=>h}),e("design:type",h)],S.prototype,"ability",void 0);class j{constructor(){this.abilities=[]}}t([y({type:()=>h,array:!0}),e("design:type",Array)],j.prototype,"abilities",void 0);class w{constructor(){this.value=void 0}}var O,N;t([y({type:String}),e("design:type",Object)],w.prototype,"value",void 0),function(t){t[t.good=0]="good",t[t.bad=1]="bad"}(O||(O={})),function(t){t.good="good",t.bad="bad"}(N||(N={}));class C{constructor(){this.faction=O.bad,this.stringFaction=N.good}}t([y({enum:O}),e("design:type",Object)],C.prototype,"faction",void 0),t([y({enum:N}),e("design:type",Object)],C.prototype,"stringFaction",void 0);class E{}t([y({enum:N}),e("design:type",String)],E.prototype,"stringFaction",void 0);class z{constructor(){this.faction=O.good}}t([y(),e("design:type",Number)],z.prototype,"faction",void 0),Reflect.defineMetadata("parameter:enum",O,z.prototype,"faction"),a("parameter definitions",()=>{o("generates editor options from enum decorator options",()=>{const t=u(C),e=t.find(t=>"faction"===t.name),a=t.find(t=>"stringFaction"===t.name);s(e?.type).toBe(Number),s(e?.options.options).toEqual([{name:"Good",value:O.good},{name:"Bad",value:O.bad}]),s(a?.type).toBe(String),s(a?.options.options).toEqual([{name:"Good",value:N.good},{name:"Bad",value:N.bad}])}),o("prepares enum params as number or string custom values",()=>{const t=c(C,{});s(t.faction).toMatchObject({type:l.Number,value:O.bad}),s(t.stringFaction).toMatchObject({type:l.String,value:N.good})}),o("uses the first enum option as the default when no initializer is set",()=>{const t=c(E,{});s(t.stringFaction).toMatchObject({type:l.String,value:N.good})}),o("uses reflected enum metadata for direct enum parameter annotations",()=>{const[t]=u(z),e=c(z,{});s(t.type).toBe(Number),s(t.options.options).toEqual([{name:"Good",value:O.good},{name:"Bad",value:O.bad}]),s(e.faction).toMatchObject({type:l.Number,value:O.good})}),o("lists assignable parameter definitions with display labels",()=>{const t=p(b);s(t.map(t=>t.id)).toEqual(["test.attack","test.magicAttack"]),s(t.map(t=>t.label)).toEqual(["Attack","Magic Attack"]),s(t.some(t=>"test.heal"===t.id)).toBe(!1)}),o("lists concrete assignable definitions for abstract bases",()=>{const t=p(h);s(m(h)).toBe(!0),s(m("test.ability")).toBe(!0),s(t.map(t=>t.id)).toEqual(["test.magicAbility"]),s(t.map(t=>t.label)).toEqual(["Magic Ability"])}),o("serializes arrays of nested parameter definitions with stable definition ids",()=>{const t=c(f,{}).attacks;s(t.type).toBe(l.Array),s(t.element).toBe(l.Struct),s(t.elementStruct).toBe("test.attack"),s(t.value).toEqual([])}),o("uses reflected array element type metadata for parameter arrays",()=>{const[t]=u(k),e=c(k,{}).attacks;s(t.type).toBe(b),s(t.options.array).toBe(!0),s(e.type).toBe(l.Array),s(e.element).toBe(l.Struct),s(e.elementStruct).toBe("test.attack"),s(e.value).toEqual([])}),o("serializes nested parameter definition defaults",()=>{const t=c(B,{}).primaryAttack;s(t.type).toBe(l.Struct),s(t.struct).toBe("test.attack"),s(t.value.damage.value).toBe(10),s(t.value.label.value).toBe("Slash")}),o("uses an empty string for string parameters without explicit defaults",()=>{const t=c(w,{}).value;s(t.type).toBe(l.String),s(t.value).toBe("")}),o("serializes nested subclass defaults with concrete definition ids",()=>{class a{constructor(){this.primaryAttack=new g}}t([y({type:()=>b}),e("design:type",Object)],a.prototype,"primaryAttack",void 0);const o=c(a,{}).primaryAttack;s(o.type).toBe(l.Struct),s(o.struct).toBe("test.magicAttack"),s(o.value.damage.value).toBe(10),s(o.value.label.value).toBe("Slash"),s(o.value.manaCost.value).toBe(5)}),o("serializes abstract parameter definitions as unselected structs",()=>{const t=c(S,{}).ability;s(t.type).toBe(l.Struct),s(t.struct).toBe("test.ability"),s(t.value).toEqual({})}),o("serializes abstract base defaults with concrete subclass ids",()=>{class a{constructor(){this.ability=new A}}t([y({type:()=>h}),e("design:type",Object)],a.prototype,"ability",void 0);const o=c(a,{}).ability;s(o.type).toBe(l.Struct),s(o.struct).toBe("test.magicAbility"),s(o.value.cooldown.value).toBe(1),s(o.value.manaCost.value).toBe(6)}),o("preserves previously selected concrete definition ids when preparing params",()=>{const t=c(B,{primaryAttack:{type:l.Struct,struct:"test.magicAttack",value:{damage:{type:l.Number,value:22},manaCost:{type:l.Number,value:7}}}}).primaryAttack;s(t.struct).toBe("test.magicAttack"),s(t.value.damage.value).toBe(22),s(t.value.manaCost.value).toBe(7)}),o("materializes nested parameter definitions as class instances",async()=>{const t=await n({attacks:{type:l.Array,element:l.Struct,elementStruct:"test.attack",value:[{damage:{type:l.Number,value:25},label:{type:l.String,value:"Heavy Slash"}}]}},f,{},{});s(t.attacks).toHaveLength(1),s(t.attacks[0]).toBeInstanceOf(b),s(t.attacks[0].damage).toBe(25),s(t.attacks[0].label).toBe("Heavy Slash")}),o("materializes a selected subclass for a non-array base parameter",async()=>{const t=await n({primaryAttack:{type:l.Struct,struct:"test.magicAttack",value:{damage:{type:l.Number,value:30},label:{type:l.String,value:"Arcane Slash"},manaCost:{type:l.Number,value:12}}}},B,{},{});s(t.primaryAttack).toBeInstanceOf(g),s(t.primaryAttack.kind()).toBe("magic"),s(t.primaryAttack.damage).toBe(30),s(t.primaryAttack.manaCost).toBe(12)}),o("materializes a selected subclass for an abstract base parameter",async()=>{const t=await n({ability:{type:l.Struct,struct:"test.magicAbility",value:{cooldown:{type:l.Number,value:2},manaCost:{type:l.Number,value:9}}}},S,{},{});s(t.ability).toBeInstanceOf(A),s(t.ability.cooldown).toBe(2),s(t.ability.manaCost).toBe(9),s(t.ability.kind()).toBe("magicAbility")}),o("does not instantiate abstract parameter definitions",async()=>{const t=i.spyOn(console,"warn").mockImplementation(()=>{}),e=await n({ability:{type:l.Struct,struct:"test.ability",value:{}}},S,{},{});s(e.ability).toBeUndefined(),s(t).toHaveBeenCalledWith('Can not instantiate abstract parameter definition "test.ability"'),t.mockRestore()}),o("materializes compact and tagged struct array elements",async()=>{const t=await n({attacks:{type:l.Array,element:l.Struct,elementStruct:"test.attack",value:[{damage:{type:l.Number,value:15},label:{type:l.String,value:"Quick Slash"}},{struct:"test.magicAttack",value:{damage:{type:l.Number,value:45},label:{type:l.String,value:"Meteor"},manaCost:{type:l.Number,value:18}}}]}},f,{},{});s(t.attacks).toHaveLength(2),s(t.attacks[0]).toBeInstanceOf(b),s(t.attacks[0]).not.toBeInstanceOf(g),s(t.attacks[1]).toBeInstanceOf(g),s(t.attacks[1].damage).toBe(45),s(t.attacks[1].manaCost).toBe(18)}),o("materializes tagged struct array elements for abstract bases",async()=>{const t=await n({abilities:{type:l.Array,element:l.Struct,elementStruct:"test.ability",value:[{struct:"test.magicAbility",value:{cooldown:{type:l.Number,value:3},manaCost:{type:l.Number,value:11}}}]}},j,{},{});s(t.abilities).toHaveLength(1),s(t.abilities[0]).toBeInstanceOf(A),s(t.abilities[0].cooldown).toBe(3),s(t.abilities[0].manaCost).toBe(11)}),o("preserves compatible selected subclass ids during runtime normalization",()=>{const t=r({type:l.Struct,struct:"test.magicAttack",value:{manaCost:{type:l.Number,value:9}}},{type:l.Struct,struct:"test.attack"});s(t.struct).toBe("test.magicAttack")})});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,4 +1,4 @@
1
- import{beforeAll as e,describe as t,expect as a,it as o,vi as r}from"vitest";import{BoxGeometry as s,Color as l,Euler as n,Mesh as i,ShaderMaterial as p,Vector3 as u}from"three";import{createMaterialSubTrack as m,createPropertyKeyframe as c,createPropertySubTrack as y,createSpawnTrack as f}from"../effects/sequence/sequence-data.js";import{canTrackAddSubTrack as v}from"../effects/sequence/sequence-definitions.js";import{evaluateCustomParamValueKeyframes as g}from"../effects/sequence/sequence-value-lane.js";import{SerializedParamType as d}from"../scene/model.js";import{shaderParameterUniformName as b}from"../shader/parameter.js";let B;function T(){return new B}r.mock("../gameplay/actors/builtin/index.js",()=>({builtInActors:{},default:{}})),r.mock("../gameplay/actors/index.js",()=>({CharacterAnimationComponent:class{},CharacterMovementComponent:class{}})),r.mock("../effects/vfx/vfx-actor.js",()=>({VfxActor:class{}})),r.mock("../effects/vfx/vfx-param.js",()=>({VisualEffect:class{}})),r.mock("../effects/vfx/vfx-service.js",()=>({VfxService:class{}})),r.mock("../gameplay/services/render.js",()=>({})),r.hoisted(()=>{if("undefined"==typeof HTMLCanvasElement)return;const e=new Proxy({},{get:(e,t)=>(t in e||(e[t]=r.fn()),e[t]),set:(e,t,a)=>(e[t]=a,!0)});Object.defineProperty(HTMLCanvasElement.prototype,"getContext",{configurable:!0,value:()=>e})}),e(async()=>{const e=await import("../effects/sequence/sequence-player.js");B=e.SequencePlayer},1e4),t("sequence property parameter tracks",()=>{o("allows multiple property sub-tracks on spawn tracks but rejects duplicate property paths",()=>{const e=f(),t=y({propertyPath:"settings.globalGain",propertyType:d.Vector3});a(v(e,"property",{propertyPath:"settings.globalGain"})).toBe(!0),e.subTracks.push(t),a(v(e,"property",{propertyPath:"settings.globalGain"})).toBe(!1),a(v(e,"property",{propertyPath:"settings.globalGamma"})).toBe(!0)}),o("creates material sub-tracks for uniform-backed parameters and rejects duplicates",()=>{const e=f(),t={materialAssetId:"mat-1",parameterName:"dissolveAmount",uniformName:b("dissolveAmount"),uniformType:d.FloatNode,valueType:d.Number,label:"Dissolve Amount",defaultValue:{type:d.Number,value:0}},o=m(t);a(o).toMatchObject({type:"material",materialAssetId:"mat-1",parameterName:"dissolveAmount",uniformName:"pu_dissolveAmount",uniformType:d.FloatNode,valueType:d.Number,label:"Dissolve Amount"}),a(v(e,"material",{material:t})).toBe(!0),e.subTracks.push(o),a(v(e,"material",{material:t})).toBe(!1),a(v(e,"material",{material:{...t,parameterName:"rimPower",uniformName:b("rimPower")}})).toBe(!0)}),o("interpolates number, vector, color, and Euler property keyframes",()=>{const e=g([c(0,{type:d.Number,value:0}),c(1,{type:d.Number,value:10})],.5);a(e?.value).toBeCloseTo(5);const t=g([c(0,{type:d.Vector3,value:[0,0,0]}),c(1,{type:d.Vector3,value:[2,4,6]})],.5,{min:0,max:3});a(t?.value).toEqual([1,2,3]);const o=g([c(0,{type:d.Color,value:"#000000"}),c(1,{type:d.Color,value:"#ffffff"})],.5);a(o?.value).toBe(`#${new l("#000000").lerp(new l("#ffffff"),.5).getHexString()}`);const r=g([c(0,{type:d.Euler,value:[0,0,0,"XYZ"]}),c(1,{type:d.Euler,value:[1,2,3,"XYZ"]})],.5);a(r?.value).toEqual([.5,1,1.5,"XYZ"])}),o("uses step evaluation for booleans and options-backed values",()=>{const e=g([c(0,{type:d.Boolean,value:!1}),c(1,{type:d.Boolean,value:!0})],.5,{stepOnly:!0});a(e?.value).toBe(!1);const t=g([c(0,{type:d.Number,value:1}),c(1,{type:d.Number,value:2})],.5,{stepOnly:!0});a(t?.value).toBe(1)}),o("applies nested property paths and restores an original undefined value",async()=>{const e={settings:{globalGain:void 0}},t=y({propertyPath:"settings.globalGain",propertyType:d.Vector3}),o=await T();o.applyResolvedPropertyValue(t,e,{type:d.Vector3,value:[1,2,3]}),a(e.settings.globalGain).toBeInstanceOf(u),a(e.settings.globalGain?.toArray()).toEqual([1,2,3]),o.stop(),a(Object.prototype.hasOwnProperty.call(e.settings,"globalGain")).toBe(!0),a(e.settings.globalGain).toBeUndefined()}),o("mutates existing mutable values and restores their original value",async()=>{const e=new u(9,8,7),t=new l("#112233"),o=new n(.1,.2,.3,"XYZ"),r={settings:{globalGain:e,colorTint:t,rotation:o}},s=await T();s.applyResolvedPropertyValue(y({propertyPath:"settings.globalGain",propertyType:d.Vector3}),r,{type:d.Vector3,value:[1,2,3]}),s.applyResolvedPropertyValue(y({propertyPath:"settings.colorTint",propertyType:d.Color}),r,{type:d.Color,value:"#ffffff"}),s.applyResolvedPropertyValue(y({propertyPath:"settings.rotation",propertyType:d.Euler}),r,{type:d.Euler,value:[1,2,3,"XYZ"]}),a(r.settings.globalGain).toBe(e),a(r.settings.globalGain.toArray()).toEqual([1,2,3]),a(r.settings.colorTint).toBe(t),a(r.settings.colorTint.getHexString()).toBe("ffffff"),a(r.settings.rotation).toBe(o),a(r.settings.rotation.toArray()).toEqual([1,2,3,"XYZ"]),s.stop(),a(r.settings.globalGain).toBe(e),a(r.settings.globalGain.toArray()).toEqual([9,8,7]),a(r.settings.colorTint).toBe(t),a(r.settings.colorTint.getHexString()).toBe("112233"),a(r.settings.rotation).toBe(o),a(r.settings.rotation.toArray()).toEqual([.1,.2,.3,"XYZ"])}),o("clones matched materials before animating uniforms and restores originals",async()=>{const e=b("dissolveAmount"),t=new p({uniforms:{[e]:{value:0}}});t.userData.assetId="mat-1";const o=new i(new s,t),r=m({materialAssetId:"mat-1",parameterName:"dissolveAmount",uniformName:e,uniformType:d.FloatNode,valueType:d.Number});r.keyframes=[c(0,{type:d.Number,value:0}),c(1,{type:d.Number,value:1})];const l=await T();l.evaluateParameterSubTrack(r,o,.5),a(o.material).not.toBe(t),a(t.uniforms[e].value).toBe(0),a(o.material.uniforms[e].value).toBeCloseTo(.5),l.stop(),a(o.material).toBe(t)}),o("applies color material keyframes to vec3 uniform storage",async()=>{const e=b("rimColor"),t=new p({uniforms:{[e]:{value:new u(0,0,0)}}});t.userData.assetId="mat-1";const o=new i(new s,t),r=m({materialAssetId:"mat-1",parameterName:"rimColor",uniformName:e,uniformType:d.RgbNode,valueType:d.Color});(await T()).applyResolvedMaterialValue(r,o,{type:d.Color,value:"#336699"});const n=o.material.uniforms[e].value,c=new l("#336699");a(n.x).toBeCloseTo(c.r),a(n.y).toBeCloseTo(c.g),a(n.z).toBeCloseTo(c.b)}),o("step-evaluates boolean material keyframes",async()=>{const e=b("enabled"),t=new p({uniforms:{[e]:{value:!1}}});t.userData.assetId="mat-1";const o=new i(new s,t),r=m({materialAssetId:"mat-1",parameterName:"enabled",uniformName:e,uniformType:d.BooleanNode,valueType:d.Boolean});r.keyframes=[c(0,{type:d.Boolean,value:!1}),c(1,{type:d.Boolean,value:!0})];(await T()).evaluateParameterSubTrack(r,o,.5),a(o.material.uniforms[e].value).toBe(!1)})});/*
1
+ import{beforeAll as e,describe as a,expect as t,it as o,vi as r}from"vitest";import{BoxGeometry as s,Color as l,Euler as n,Mesh as i,Object3D as m,ShaderMaterial as u,Vector3 as p}from"three";import{createMaterialSubTrack as c,createPropertyKeyframe as f,createPropertySubTrack as y,createSpawnTrack as v}from"../effects/sequence/sequence-data.js";import{canTrackAddSubTrack as d}from"../effects/sequence/sequence-definitions.js";import{evaluateCustomParamValueKeyframes as b}from"../effects/sequence/sequence-value-lane.js";import{SerializedParamType as g}from"../scene/model.js";import{shaderParameterUniformName as w}from"../shader/parameter.js";let B;function N(){return new B}r.mock("../gameplay/actors/builtin/index.js",()=>({builtInActors:{},default:{}})),r.mock("../gameplay/actors/index.js",()=>({CharacterAnimationComponent:class{},CharacterMovementComponent:class{}})),r.mock("../effects/vfx/vfx-actor.js",()=>({VfxActor:class{}})),r.mock("../effects/vfx/vfx-param.js",()=>({VisualEffect:class{}})),r.mock("../effects/vfx/vfx-service.js",()=>({VfxService:class{}})),r.mock("../gameplay/services/render.js",()=>({})),r.hoisted(()=>{if("undefined"==typeof HTMLCanvasElement)return;const e=new Proxy({},{get:(e,a)=>(a in e||(e[a]=r.fn()),e[a]),set:(e,a,t)=>(e[a]=t,!0)});Object.defineProperty(HTMLCanvasElement.prototype,"getContext",{configurable:!0,value:()=>e})}),e(async()=>{const e=await import("../effects/sequence/sequence-player.js");B=e.SequencePlayer},1e4),a("sequence property parameter tracks",()=>{o("allows multiple property sub-tracks on spawn tracks but rejects duplicate property paths",()=>{const e=v(),a=y({propertyPath:"settings.globalGain",propertyType:g.Vector3});t(d(e,"property",{propertyPath:"settings.globalGain"})).toBe(!0),e.subTracks.push(a),t(d(e,"property",{propertyPath:"settings.globalGain"})).toBe(!1),t(d(e,"property",{propertyPath:"settings.globalGamma"})).toBe(!0)}),o("creates material sub-tracks for uniform-backed parameters and rejects duplicates",()=>{const e=v(),a={materialAssetId:"mat-1",parameterName:"dissolveAmount",uniformName:w("dissolveAmount"),uniformType:g.FloatNode,valueType:g.Number,label:"Dissolve Amount",defaultValue:{type:g.Number,value:0}},o=c(a);t(o).toMatchObject({type:"material",materialMatchMode:"asset",materialAssetId:"mat-1",parameterName:"dissolveAmount",uniformName:"pu_dissolveAmount",uniformType:g.FloatNode,valueType:g.Number,label:"Dissolve Amount"}),t(d(e,"material",{material:a})).toBe(!0),e.subTracks.push(o),t(d(e,"material",{material:a})).toBe(!1),t(d(e,"material",{material:{...a,parameterName:"rimPower",uniformName:w("rimPower")}})).toBe(!0)}),o("allows name-matched material sub-tracks as an alternative to asset-specific material tracks",()=>{const e=v(),a={materialAssetId:"mat-1",parameterName:"hitGlow",uniformName:w("hitGlow"),uniformType:g.FloatNode,valueType:g.Number},o={...a,materialAssetId:null,materialMatchMode:"parameterName"},r=c(o);t(r).toMatchObject({type:"material",materialMatchMode:"parameterName",materialAssetId:null,parameterName:"hitGlow"}),t(d(e,"material",{material:o})).toBe(!0),e.subTracks.push(r),t(d(e,"material",{material:a})).toBe(!1),t(d(e,"material",{material:{...a,parameterName:"rimPower",uniformName:w("rimPower")}})).toBe(!0);const s=v();s.subTracks.push(c(a)),t(d(s,"material",{material:{...a,materialAssetId:"mat-2"}})).toBe(!0),t(d(s,"material",{material:o})).toBe(!1)}),o("interpolates number, vector, color, and Euler property keyframes",()=>{const e=b([f(0,{type:g.Number,value:0}),f(1,{type:g.Number,value:10})],.5);t(e?.value).toBeCloseTo(5);const a=b([f(0,{type:g.Vector3,value:[0,0,0]}),f(1,{type:g.Vector3,value:[2,4,6]})],.5,{min:0,max:3});t(a?.value).toEqual([1,2,3]);const o=b([f(0,{type:g.Color,value:"#000000"}),f(1,{type:g.Color,value:"#ffffff"})],.5);t(o?.value).toBe(`#${new l("#000000").lerp(new l("#ffffff"),.5).getHexString()}`);const r=b([f(0,{type:g.Euler,value:[0,0,0,"XYZ"]}),f(1,{type:g.Euler,value:[1,2,3,"XYZ"]})],.5);t(r?.value).toEqual([.5,1,1.5,"XYZ"])}),o("uses step evaluation for booleans and options-backed values",()=>{const e=b([f(0,{type:g.Boolean,value:!1}),f(1,{type:g.Boolean,value:!0})],.5,{stepOnly:!0});t(e?.value).toBe(!1);const a=b([f(0,{type:g.Number,value:1}),f(1,{type:g.Number,value:2})],.5,{stepOnly:!0});t(a?.value).toBe(1)}),o("applies nested property paths and restores an original undefined value",async()=>{const e={settings:{globalGain:void 0}},a=y({propertyPath:"settings.globalGain",propertyType:g.Vector3}),o=await N();o.applyResolvedPropertyValue(a,e,{type:g.Vector3,value:[1,2,3]}),t(e.settings.globalGain).toBeInstanceOf(p),t(e.settings.globalGain?.toArray()).toEqual([1,2,3]),o.stop(),t(Object.prototype.hasOwnProperty.call(e.settings,"globalGain")).toBe(!0),t(e.settings.globalGain).toBeUndefined()}),o("mutates existing mutable values and restores their original value",async()=>{const e=new p(9,8,7),a=new l("#112233"),o=new n(.1,.2,.3,"XYZ"),r={settings:{globalGain:e,colorTint:a,rotation:o}},s=await N();s.applyResolvedPropertyValue(y({propertyPath:"settings.globalGain",propertyType:g.Vector3}),r,{type:g.Vector3,value:[1,2,3]}),s.applyResolvedPropertyValue(y({propertyPath:"settings.colorTint",propertyType:g.Color}),r,{type:g.Color,value:"#ffffff"}),s.applyResolvedPropertyValue(y({propertyPath:"settings.rotation",propertyType:g.Euler}),r,{type:g.Euler,value:[1,2,3,"XYZ"]}),t(r.settings.globalGain).toBe(e),t(r.settings.globalGain.toArray()).toEqual([1,2,3]),t(r.settings.colorTint).toBe(a),t(r.settings.colorTint.getHexString()).toBe("ffffff"),t(r.settings.rotation).toBe(o),t(r.settings.rotation.toArray()).toEqual([1,2,3,"XYZ"]),s.stop(),t(r.settings.globalGain).toBe(e),t(r.settings.globalGain.toArray()).toEqual([9,8,7]),t(r.settings.colorTint).toBe(a),t(r.settings.colorTint.getHexString()).toBe("112233"),t(r.settings.rotation).toBe(o),t(r.settings.rotation.toArray()).toEqual([.1,.2,.3,"XYZ"])}),o("clones matched materials before animating uniforms and restores originals",async()=>{const e=w("dissolveAmount"),a=new u({uniforms:{[e]:{value:0}}});a.userData.assetId="mat-1";const o=new i(new s,a),r=c({materialAssetId:"mat-1",parameterName:"dissolveAmount",uniformName:e,uniformType:g.FloatNode,valueType:g.Number});r.keyframes=[f(0,{type:g.Number,value:0}),f(1,{type:g.Number,value:1})];const l=await N();l.evaluateParameterSubTrack(r,o,.5),t(o.material).not.toBe(a),t(a.uniforms[e].value).toBe(0),t(o.material.uniforms[e].value).toBeCloseTo(.5),l.stop(),t(o.material).toBe(a)}),o("can match material tracks by parameter name across different material assets",async()=>{const e=w("hitGlow"),a=new u({uniforms:{[e]:{value:0}}});a.userData.assetId="mat-1";const o=new u({uniforms:{[e]:{value:0}}});o.userData.assetId="mat-2";const r=new u({uniforms:{[w("otherGlow")]:{value:0}}});r.userData.assetId="mat-3";const l=new i(new s,a),n=new i(new s,o),p=new i(new s,r),f=new m;f.add(l,n,p);const y=c({materialMatchMode:"parameterName",parameterName:"hitGlow",uniformName:e,uniformType:g.FloatNode,valueType:g.Number}),v=await N();v.applyResolvedMaterialValue(y,f,{type:g.Number,value:.75}),t(l.material).not.toBe(a),t(n.material).not.toBe(o),t(p.material).toBe(r),t(a.uniforms[e].value).toBe(0),t(o.uniforms[e].value).toBe(0),t(l.material.uniforms[e].value).toBeCloseTo(.75),t(n.material.uniforms[e].value).toBeCloseTo(.75),v.stop(),t(l.material).toBe(a),t(n.material).toBe(o)}),o("interpolates string-backed number material keyframes before applying uniforms",async()=>{const e=w("dissolveAmount"),a=new u({uniforms:{[e]:{value:0}}});a.userData.assetId="mat-1";const o=new i(new s,a),r=c({materialAssetId:"mat-1",parameterName:"dissolveAmount",uniformName:e,uniformType:g.FloatNode,valueType:g.Number});r.keyframes=[f(0,{type:g.Number,value:"0"}),f(1,{type:g.Number,value:"1"})];(await N()).evaluateParameterSubTrack(r,o,.5),t(o.material.uniforms[e].value).toBeCloseTo(.5)}),o("applies color material keyframes to vec3 uniform storage",async()=>{const e=w("rimColor"),a=new u({uniforms:{[e]:{value:new p(0,0,0)}}});a.userData.assetId="mat-1";const o=new i(new s,a),r=c({materialAssetId:"mat-1",parameterName:"rimColor",uniformName:e,uniformType:g.RgbNode,valueType:g.Color});(await N()).applyResolvedMaterialValue(r,o,{type:g.Color,value:"#336699"});const n=o.material.uniforms[e].value,m=new l("#336699");t(n.x).toBeCloseTo(m.r),t(n.y).toBeCloseTo(m.g),t(n.z).toBeCloseTo(m.b)}),o("step-evaluates boolean material keyframes",async()=>{const e=w("enabled"),a=new u({uniforms:{[e]:{value:!1}}});a.userData.assetId="mat-1";const o=new i(new s,a),r=c({materialAssetId:"mat-1",parameterName:"enabled",uniformName:e,uniformType:g.BooleanNode,valueType:g.Boolean});r.keyframes=[f(0,{type:g.Boolean,value:!1}),f(1,{type:g.Boolean,value:!0})];(await N()).evaluateParameterSubTrack(r,o,.5),t(o.material.uniforms[e].value).toBe(!1)})});/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sequence-vfx.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import*as e from"three";import{describe as s,expect as t,it as a,vi as n}from"vitest";import{createSequenceData as c,createVfxClipInstance as r,createVfxTrack as o}from"../effects/sequence/sequence-data.js";import{SequencePlayer as l}from"../effects/sequence/sequence-player.js";function i(){return{object:new e.Object3D,restart:n.fn(),play:n.fn(),pause:n.fn(),stop:n.fn(),getParticleCount:n.fn(()=>0)}}async function f(){await Promise.resolve(),await Promise.resolve()}n.mock("../gameplay/actors/builtin/index.js",()=>({builtInActors:{},default:{}})),n.mock("../gameplay/actors/index.js",()=>({CharacterAnimationComponent:class{},CharacterMovementComponent:class{}})),n.mock("../effects/vfx/vfx-actor.js",()=>({VfxActor:class{}})),n.mock("../effects/vfx/vfx-param.js",()=>({VisualEffect:class{}})),n.mock("../effects/vfx/vfx-service.js",()=>({VfxService:class{}})),n.hoisted(()=>{if("undefined"==typeof HTMLCanvasElement)return;const e=new Proxy({},{get:(e,s)=>(s in e||(e[s]=("string"!=typeof s||!s.startsWith("is"))&&n.fn()),e[s]),set:(e,s,t)=>(e[s]=t,!0)});Object.defineProperty(HTMLCanvasElement.prototype,"getContext",{configurable:!0,value:()=>e})}),s("sequence VFX tracks",()=>{a("restarts an already-active VFX clip when seeking backwards within the clip",async()=>{const s=i(),a=new l;a.setWorld({scene:new e.Scene}),a.setVfxService({createFromAssetId:n.fn(async()=>s)});const p=c();p.duration=2;const m=o(),d=r("vfx-asset",0,1.5);m.clips.push(d),p.tracks.push(m),a.load(p),a.play(),await f(),a.seek(1),s.restart.mockClear(),s.play.mockClear(),a.seek(.25),t(s.restart).toHaveBeenCalledTimes(1),t(s.play).toHaveBeenCalledTimes(1)}),a("restarts active VFX clips when a looping sequence wraps to the start",async()=>{const s=i(),a=new l;a.setWorld({scene:new e.Scene}),a.setVfxService({createFromAssetId:n.fn(async()=>s)});const p=c();p.duration=1,p.loop=!0;const m=o(),d=r("vfx-asset",0,1);m.clips.push(d),p.tracks.push(m),a.load(p),a.play(),await f(),s.restart.mockClear(),s.play.mockClear(),a.update(1.1),t(s.restart).toHaveBeenCalledTimes(1),t(s.play).toHaveBeenCalledTimes(1)}),a("clears VFX particles when seeking backwards before the clip starts",async()=>{const s=i(),a=new l;a.setWorld({scene:new e.Scene}),a.setVfxService({createFromAssetId:n.fn(async()=>s)});const p=c();p.duration=2;const m=o(),d=r("vfx-asset",.5,1);m.clips.push(d),p.tracks.push(m),a.load(p),a.play(),a.seek(.75),await f(),s.restart.mockClear(),s.stop.mockClear(),s.pause.mockClear(),a.seek(.25),t(s.restart).toHaveBeenCalledTimes(1),t(s.stop).toHaveBeenCalled(),t(s.pause).toHaveBeenCalledTimes(1)})});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,4 +1,4 @@
1
- import{afterEach as e,beforeEach as t,describe as a,expect as r,it as o,vi as s}from"vitest";import{createRequire as i}from"node:module";import*as n from"node:fs/promises";import*as c from"node:os";import*as w from"node:path";import{firstValueFrom as d}from"rxjs";const l=i(import.meta.url);let f,m,p;async function g(){const{ObjectStorage:e}=await import("../scene/storage/storage.js"),t=new e("asset");return t.setBasePath("data"),t}a("ObjectStorage case-insensitive file collisions",()=>{t(async()=>{s.resetModules(),m=window.require,p=window.process,f=await n.mkdtemp(w.join(c.tmpdir(),"hology-storage-")),await n.writeFile(w.join(f,"vite.config.ts"),"hologyBuild()"),Object.defineProperty(window,"require",{configurable:!0,value:e=>"chokidar"===e?{watch:()=>({on:()=>{},close:()=>{}})}:l(e)}),Object.defineProperty(window,"process",{configurable:!0,value:{argv:[`--path=${f}`]}})}),e(async()=>{await n.rm(f,{recursive:!0,force:!0}),Object.defineProperty(window,"require",{configurable:!0,value:m}),Object.defineProperty(window,"process",{configurable:!0,value:p})}),o("rejects create names that only differ by case",async()=>{const e=await g();await e.create({name:"dirt"}),await r(e.create({name:"Dirt"})).rejects.toThrow(/differs beyond letter casing/),await r(e.getAll()).resolves.toHaveLength(1)}),o("rejects prepared saves that only differ by case",async()=>{const e=await g();await e.create({name:"dirt"});const t=e.prepareCreate({name:"Dirt"});await r(e.save(t)).rejects.toThrow(/differs beyond letter casing/),await r(e.getAll()).resolves.toHaveLength(1)}),o("rejects renames that only differ by case from another object",async()=>{const e=await g();await e.create({name:"dirt"});const t=await e.create({name:"sand"});await r(e.rename(t,"Dirt")).rejects.toThrow(/differs beyond letter casing/),await r(e.get(t.id)).resolves.toMatchObject({name:"sand"})}),o("waits for the base path before watching folders",async()=>{const{ObjectStorage:e}=await import("../scene/storage/storage.js"),t=new e("asset"),a=d(t.watchFolders());t.setBasePath("data"),await r(a).resolves.toEqual([])})});/*
1
+ import{afterEach as e,beforeEach as t,describe as a,expect as r,it as s,vi as o}from"vitest";import{createRequire as i}from"node:module";import*as n from"node:fs/promises";import*as c from"node:os";import*as w from"node:path";import{firstValueFrom as d}from"rxjs";const l=i(import.meta.url);let m,f,p;async function g(){const{ObjectStorage:e}=await import("../scene/storage/storage.js"),t=new e("asset");return t.setBasePath("data"),t}a("ObjectStorage case-insensitive file collisions",()=>{t(async()=>{o.resetModules(),f=window.require,p=window.process,m=await n.mkdtemp(w.join(c.tmpdir(),"hology-storage-")),await n.writeFile(w.join(m,"vite.config.ts"),"hologyBuild()"),Object.defineProperty(window,"require",{configurable:!0,value:e=>"chokidar"===e?{watch:()=>({on:()=>{},close:()=>{}})}:l(e)}),Object.defineProperty(window,"process",{configurable:!0,value:{argv:[`--path=${m}`]}})}),e(async()=>{await n.rm(m,{recursive:!0,force:!0}),Object.defineProperty(window,"require",{configurable:!0,value:f}),Object.defineProperty(window,"process",{configurable:!0,value:p})}),s("rejects create names that only differ by case",async()=>{const e=await g();await e.create({name:"dirt"}),await r(e.create({name:"Dirt"})).rejects.toThrow(/differs beyond letter casing/),await r(e.getAll()).resolves.toHaveLength(1)}),s("rejects prepared saves that only differ by case",async()=>{const e=await g();await e.create({name:"dirt"});const t=e.prepareCreate({name:"Dirt"});await r(e.save(t)).rejects.toThrow(/differs beyond letter casing/),await r(e.getAll()).resolves.toHaveLength(1)}),s("rejects renames that only differ by case from another object",async()=>{const e=await g();await e.create({name:"dirt"});const t=await e.create({name:"sand"});await r(e.rename(t,"Dirt")).rejects.toThrow(/differs beyond letter casing/),await r(e.get(t.id)).resolves.toMatchObject({name:"sand"})}),s("waits for the base path before watching folders",async()=>{const{ObjectStorage:e}=await import("../scene/storage/storage.js"),t=new e("asset"),a=d(t.watchFolders());t.setBasePath("data"),await r(a).resolves.toEqual([])}),s("loads pre-existing nested assets into the index",async()=>{const e=w.join(m,"data","asset");await n.mkdir(w.join(e,"weapons","swords"),{recursive:!0}),await n.mkdir(w.join(e,"materials"),{recursive:!0}),await n.writeFile(w.join(e,"weapons","swords","Iron_Sword.json"),JSON.stringify({id:"iron-sword",name:"Iron Sword"})),await n.writeFile(w.join(e,"materials","Steel.json"),JSON.stringify({id:"steel",name:"Steel"}));const t=await g();await r(t.get("iron-sword")).resolves.toMatchObject({id:"iron-sword",path:w.join("weapons","swords")}),await r(t.get("steel")).resolves.toMatchObject({id:"steel",path:"materials"})})});/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,2 @@
1
+ import "reflect-metadata";
2
+ //# sourceMappingURL=world-lifecycle.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{__decorate as t}from"tslib";import"reflect-metadata";import{expect as e,test as o,vi as n}from"vitest";n.mock("../gameplay/services/render.js",()=>({ViewController:class{}})),n.mock("../gameplay/services/physics/physics-system.js",()=>({PhysicsSystem:class{}})),n.mock("../rendering.js",()=>({RenderingView:class{}}));import{Scene as i}from"three";import{Subject as r}from"rxjs";import{Container as s}from"typedi";import{Actor as d,BaseActor as a}from"../gameplay/actors/actor.js";import{ActorComponent as c,Component as l}from"../gameplay/actors/component.js";import{ActorFactory as m}from"../gameplay/actors/factory.js";import{World as y}from"../gameplay/services/world.js";function u(t){const e=Object.create(y.prototype);return e.actorFactory=t,e.physics={removeActor(){}},e.actors=[],e.actorAdded=new r,e.actorRemoved=new r,e.scene=new i,e}o("world begin and end play skip runtime-only components in editor",async()=>{const t=new m(s.of("world-lifecycle-editor"),{inEditor:!0}),o=await t.create(p),n=u(t);n.addActor(o),n.removeActor(o),e(o.beginCount).toBe(1),e(o.endCount).toBe(1),e(o.runtimeOnly.beginCount).toBe(0),e(o.runtimeOnly.endCount).toBe(0),e(o.runtimeOnly.actor).toBeUndefined(),e(o.inEditor.beginCount).toBe(1),e(o.inEditor.endCount).toBe(1),e(o.inEditor.actor).toBe(o),e(o.editorOnly.beginCount).toBe(1),e(o.editorOnly.endCount).toBe(1),e(o.editorOnly.actor).toBe(o)}),o("world begin and end play skip editor-only components at runtime",async()=>{const t=new m(s.of("world-lifecycle-runtime"),{inEditor:!1}),o=await t.create(p),n=u(t);n.addActor(o),n.removeActor(o),e(o.beginCount).toBe(1),e(o.endCount).toBe(1),e(o.runtimeOnly.beginCount).toBe(1),e(o.runtimeOnly.endCount).toBe(1),e(o.runtimeOnly.actor).toBe(o),e(o.inEditor.beginCount).toBe(1),e(o.inEditor.endCount).toBe(1),e(o.inEditor.actor).toBe(o),e(o.editorOnly.beginCount).toBe(0),e(o.editorOnly.endCount).toBe(0),e(o.editorOnly.actor).toBeUndefined()});let p=class extends a{constructor(){super(...arguments),this.beginCount=0,this.endCount=0,this.runtimeOnly=this.attach(g),this.inEditor=this.attach(B),this.editorOnly=this.attach(h)}onBeginPlay(){this.beginCount++}onEndPlay(){this.endCount++}};p=t([d()],p);class C extends c{constructor(){super(...arguments),this.beginCount=0,this.endCount=0}onBeginPlay(){this.beginCount++}onEndPlay(){this.endCount++}}let g=class extends C{};g=t([l()],g);let B=class extends C{};B=t([l({inEditor:!0})],B);let h=class extends C{};h=t([l({inEditor:!0,editorOnly:!0})],h);/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,6 +1,6 @@
1
1
  export interface Type<T> extends Function {
2
2
  new (...args: any[]): T;
3
3
  }
4
- export type AbstractType<T> = abstract new (...args: any[]) => T;
4
+ export type AbstractType<T> = (abstract new (...args: any[]) => T) & Function;
5
5
  export declare function assertType<T, K extends T>(value: T, type: Type<K>): asserts value is K;
6
6
  //# sourceMappingURL=type.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hology/core",
3
- "version": "0.0.205",
3
+ "version": "0.0.207",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",