@hology/core 0.0.212 → 0.0.213
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.
- package/dist/effects/sequence/index.d.ts +1 -0
- package/dist/effects/sequence/index.js +1 -1
- package/dist/effects/sequence/sequence-action.d.ts +5 -0
- package/dist/effects/sequence/sequence-actor.d.ts +7 -0
- package/dist/effects/sequence/sequence-actor.js +1 -1
- package/dist/effects/sequence/sequence-animation-retiming.js +1 -1
- package/dist/effects/sequence/sequence-data.d.ts +9 -0
- package/dist/effects/sequence/sequence-data.js +1 -1
- package/dist/effects/sequence/sequence-player.d.ts +12 -1
- package/dist/effects/sequence/sequence-player.js +1 -1
- package/dist/effects/sequence/sequence-transform.d.ts +10 -0
- package/dist/effects/sequence/sequence-transform.js +4 -0
- package/dist/effects/sequence/sequence-value-lane.d.ts +2 -0
- package/dist/effects/sequence/sequence-value-lane.js +1 -1
- package/dist/effects/vfx/vfx-actor.d.ts +5 -0
- package/dist/effects/vfx/vfx-actor.js +1 -1
- package/dist/effects/vfx/vfx-asset.d.ts +2 -1
- package/dist/effects/vfx/vfx-asset.js +1 -1
- package/dist/effects/vfx/vfx-materializer.js +1 -1
- package/dist/effects/vfx/vfx-renderers.d.ts +1 -0
- package/dist/effects/vfx/vfx-renderers.js +1 -1
- package/dist/gameplay/actors/actor.d.ts +3 -5
- package/dist/gameplay/actors/actor.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-animation.d.ts +3 -0
- package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-movement-like.d.ts +2 -0
- package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +13 -0
- package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/net-character-movement-protocol.d.ts +4 -1
- package/dist/gameplay/actors/builtin/components/character/net-character-movement-protocol.js +1 -1
- package/dist/gameplay/actors/builtin/components/mesh-component.d.ts +1 -0
- package/dist/gameplay/actors/builtin/components/mesh-component.js +1 -1
- package/dist/gameplay/actors/builtin/components/tween-component.js +1 -1
- package/dist/gameplay/actors/builtin/navmesh-actor.d.ts +2 -0
- package/dist/gameplay/actors/builtin/navmesh-actor.js +1 -1
- package/dist/gameplay/actors/builtin/trigger-volume.d.ts +3 -3
- package/dist/gameplay/actors/builtin/trigger-volume.js +1 -1
- package/dist/gameplay/actors/camera/camera-component.d.ts +1 -3
- package/dist/gameplay/actors/camera/camera-component.js +1 -1
- package/dist/gameplay/actors/component.d.ts +3 -0
- package/dist/gameplay/actors/component.js +1 -1
- package/dist/gameplay/actors/type-registry.d.ts +10 -0
- package/dist/gameplay/actors/type-registry.js +4 -0
- package/dist/gameplay/animation/retarget.d.ts +50 -0
- package/dist/gameplay/animation/retarget.js +4 -0
- package/dist/gameplay/animation/root-motion.js +1 -1
- package/dist/gameplay/event-graph/actor-transform-properties.d.ts +6 -0
- package/dist/gameplay/event-graph/actor-transform-properties.js +4 -0
- package/dist/gameplay/event-graph/asset-actor-types.d.ts +3 -0
- package/dist/gameplay/event-graph/asset-actor-types.js +4 -0
- package/dist/gameplay/event-graph/asset-references.d.ts +12 -0
- package/dist/gameplay/event-graph/asset-references.js +4 -0
- package/dist/gameplay/event-graph/compiler.d.ts +107 -0
- package/dist/gameplay/event-graph/compiler.js +4 -0
- package/dist/gameplay/event-graph/decorators.d.ts +74 -0
- package/dist/gameplay/event-graph/decorators.js +4 -0
- package/dist/gameplay/event-graph/document-compiler.d.ts +107 -0
- package/dist/gameplay/event-graph/document-compiler.js +4 -0
- package/dist/gameplay/event-graph/event-graph-demo.d.ts +2 -0
- package/dist/gameplay/event-graph/event-graph-demo.js +4 -0
- package/dist/gameplay/event-graph/graph.d.ts +106 -0
- package/dist/gameplay/event-graph/graph.js +4 -0
- package/dist/gameplay/event-graph/index.d.ts +13 -0
- package/dist/gameplay/event-graph/index.js +4 -0
- package/dist/gameplay/event-graph/model.d.ts +71 -0
- package/dist/gameplay/event-graph/model.js +4 -0
- package/dist/gameplay/event-graph/nodes/execution-nodes.d.ts +115 -0
- package/dist/gameplay/event-graph/nodes/execution-nodes.js +4 -0
- package/dist/gameplay/event-graph/nodes/gameplay-nodes.d.ts +208 -0
- package/dist/gameplay/event-graph/nodes/gameplay-nodes.js +4 -0
- package/dist/gameplay/event-graph/nodes/index.d.ts +4 -0
- package/dist/gameplay/event-graph/nodes/index.js +4 -0
- package/dist/gameplay/event-graph/nodes/value-nodes.d.ts +53 -0
- package/dist/gameplay/event-graph/nodes/value-nodes.js +4 -0
- package/dist/gameplay/event-graph/registry.d.ts +33 -0
- package/dist/gameplay/event-graph/registry.js +4 -0
- package/dist/gameplay/event-graph/runtime-assets.d.ts +21 -0
- package/dist/gameplay/event-graph/runtime-assets.js +4 -0
- package/dist/gameplay/event-graph/runtime.d.ts +160 -0
- package/dist/gameplay/event-graph/runtime.js +4 -0
- package/dist/gameplay/event-graph/type-inference.d.ts +41 -0
- package/dist/gameplay/event-graph/type-inference.js +4 -0
- package/dist/gameplay/event-graph/types.d.ts +77 -0
- package/dist/gameplay/event-graph/types.js +4 -0
- package/dist/gameplay/index.d.ts +15 -2
- package/dist/gameplay/index.js +1 -1
- package/dist/gameplay/initiate.js +1 -1
- package/dist/gameplay/input/input.d.ts +22 -17
- package/dist/gameplay/input/input.js +1 -1
- package/dist/gameplay/net/service/net-decorator.d.ts +1 -1
- package/dist/gameplay/net/service/net-decorator.js +1 -1
- package/dist/gameplay/net/service/net-serializer.js +1 -1
- package/dist/gameplay/net/service/net-service.d.ts +6 -6
- package/dist/gameplay/net/service/net-service.js +1 -1
- package/dist/gameplay/net/service/rpc-decorator.js +1 -1
- package/dist/gameplay/services/asset-loader.d.ts +7 -0
- package/dist/gameplay/services/asset-loader.js +1 -1
- package/dist/gameplay/services/physics/physics-system.d.ts +14 -0
- package/dist/gameplay/services/physics/physics-system.js +1 -1
- package/dist/gameplay/services/world.d.ts +12 -0
- package/dist/gameplay/services/world.js +1 -1
- package/dist/rendering.js +1 -1
- package/dist/scene/asset-resource-loader.d.ts +7 -1
- package/dist/scene/asset-resource-loader.js +1 -1
- package/dist/scene/custom-param-deserialize.js +1 -1
- package/dist/scene/custom-param-runtime-types.js +1 -1
- package/dist/scene/materializer.d.ts +25 -0
- package/dist/scene/materializer.js +1 -1
- package/dist/scene/model.d.ts +114 -2
- package/dist/scene/model.js +1 -1
- package/dist/scene/objects/prefab.js +1 -1
- package/dist/shader/graph/compiler.d.ts +3 -0
- package/dist/shader/graph/compiler.js +1 -1
- package/dist/shader/graph/model.d.ts +1 -1
- package/dist/shader/graph/registry.js +1 -1
- package/dist/test/animation-retarget.test.d.ts +2 -0
- package/dist/test/animation-retarget.test.js +4 -0
- package/dist/test/event-graph-generated-code.test.d.ts +2 -0
- package/dist/test/event-graph-generated-code.test.js +4 -0
- package/dist/test/event-graph-types.test.d.ts +2 -0
- package/dist/test/event-graph-types.test.js +4 -0
- package/dist/test/event-graph.test.d.ts +2 -0
- package/dist/test/event-graph.test.js +4 -0
- package/dist/test/input.test.d.ts +2 -0
- package/dist/test/input.test.js +4 -0
- package/dist/test/net-character-movement.test.js +1 -1
- package/dist/test/prefab-instance-params.test.js +1 -1
- package/dist/test/sequence-camera-control.test.js +1 -1
- package/dist/test/sequence-scene-binding.test.d.ts +2 -0
- package/dist/test/sequence-scene-binding.test.js +4 -0
- package/dist/test/sequence-transform.test.d.ts +2 -0
- package/dist/test/sequence-transform.test.js +4 -0
- package/dist/test/shader-graph.test.js +1 -1
- package/package.json +10 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{AnimationClip as e,AnimationMixer as n,Bone as t,LoopOnce as o,Matrix4 as r,Quaternion as i,QuaternionKeyframeTrack as a,Skeleton as s,SkinnedMesh as l,Vector3 as u,VectorKeyframeTrack as c}from"three";import*as d from"three/addons/utils/SkeletonUtils.js";export const ANIMATION_RETARGET_GENERATOR_VERSION=9;export function resolveAnimationRigBasisRotation(e){const n=e.basisPreset??"yUp";let t;t="custom"===n&&null!=e.basisRotation?(new i).fromArray(e.basisRotation).normalize():"yUp"===n?new i:"unrealZUp"===n?(new i).setFromAxisAngle(new u(1,0,0),-Math.PI/2):detectAnimationRigBasisRotation(e);const o=(e.basisYawDegrees??0)*Math.PI/180;return(new i).setFromAxisAngle(new u(0,1,0),o).multiply(t).normalize()}export function detectAnimationRigBasisRotation(e){const n=x(e,{}),t=e.bones.findIndex(n=>n.id===e.pelvisBoneId),o=e.bones.findIndex(n=>n.id===e.chains.find(e=>"neck"===e.role)?.endBoneId),r=e.chains.filter(e=>"leftLeg"===e.role||"rightLeg"===e.role).map(n=>e.bones.findIndex(e=>e.id===n.endBoneId)).filter(e=>e>=0);let a=new u;if(o>=0&&r.length>0){const e=r.reduce((e,t)=>e.add(n.worldPositions[t]),new u).multiplyScalar(1/r.length);a.copy(n.worldPositions[o]).sub(e)}else t>=0&&o>=0&&a.copy(n.worldPositions[o]).sub(n.worldPositions[t]);if(a.lengthSq()<1e-8)return new i;a.normalize();const s=[new u(Math.sign(a.x)||1,0,0),new u(0,Math.sign(a.y)||1,0),new u(0,0,Math.sign(a.z)||1)].sort((e,n)=>Math.abs(n.dot(a))-Math.abs(e.dot(a)))[0];return(new i).setFromUnitVectors(s,new u(0,1,0))}export function extractAnimationRigs(e){const n=[],o=new Set,r=new Set;e.updateMatrixWorld(!0),e.traverse(e=>{if($(e)){for(const n of e.skeleton.bones)r.add(n);o.has(e.skeleton)||(o.add(e.skeleton),n.push({name:e.name,mesh:e,skeleton:e.skeleton}))}}),e.traverse(e=>{if(!(e instanceof t)||e.parent instanceof t)return;const o=[];e.traverse(e=>{e instanceof t&&!r.has(e)&&o.push(e)}),0!==o.length&&n.push({name:e.name,skeleton:new s(o)})});const i=new Map;for(const e of n){const n=f(e.skeleton),t=m(e.skeleton);i.set(n,Math.min(i.get(n)??Number.POSITIVE_INFINITY,t))}const a=[],l=[],u=[];for(const{name:e,mesh:t,skeleton:o}of n){const n=m(o);if(n>(i.get(f(o))??n))continue;const r=g(t,o),s=a.findIndex(e=>e.topologyFingerprint===r.topologyFingerprint&&e.bindPoseFingerprint===r.bindPoseFingerprint);s>=0?n<u[s]&&(a[s]=r,l[s]=e,u[s]=n):(a.push(r),l.push(e),u.push(n))}return{rigs:a,skinnedMeshNames:l}}export function areAnimationRigsCompatible(e,n){return e.topologyFingerprint===n.topologyFingerprint&&e.bindPoseFingerprint===n.bindPoseFingerprint}export function validateAnimationRig(e){const n=[],t=new Set(e.bones.map(e=>e.id)),o=new Map;for(const n of e.bones)o.set(n.name,(o.get(n.name)??0)+1);const r=[...o].filter(([,e])=>e>1).map(([e])=>e);r.length>0&&n.push({severity:"error",code:"duplicate-bone-names",message:`Bone names must be unique for animation tracks. Duplicates: ${r.join(", ")}`});for(const o of e.chains)t.has(o.startBoneId)&&t.has(o.endBoneId)?0===v(e,o).length&&n.push({severity:"error",code:"invalid-chain-hierarchy",message:`Chain "${o.name}" does not follow a parent-to-child hierarchy.`}):n.push({severity:"error",code:"invalid-chain-bone",message:`Chain "${o.name}" references a missing start or end bone.`});return null!=e.retargetRootBoneId&&t.has(e.retargetRootBoneId)||n.push({severity:"error",code:"missing-retarget-root",message:"Select a valid retarget root bone."}),null!=e.pelvisBoneId&&t.has(e.pelvisBoneId)||n.push({severity:"warning",code:"missing-pelvis",message:"Select a pelvis bone for reliable root-motion and height scaling."}),n}export function validateAnimationRetargeter(e,n,t){const o=[...validateAnimationRig(n).map(e=>({...e,message:`Source rig: ${e.message}`})),...validateAnimationRig(t).map(e=>({...e,message:`Target rig: ${e.message}`}))];e.sourceRigFingerprint?.topology===n.topologyFingerprint&&e.sourceRigFingerprint?.bindPose===n.bindPoseFingerprint||o.push({severity:"error",code:"source-rig-changed",message:"The source rig hierarchy or bind pose changed. Review mappings and explicitly accept the new fingerprints."}),e.targetRigFingerprint?.topology===t.topologyFingerprint&&e.targetRigFingerprint?.bindPose===t.bindPoseFingerprint||o.push({severity:"error",code:"target-rig-changed",message:"The target rig hierarchy or bind pose changed. Review mappings and explicitly accept the new fingerprints."});for(const r of e.chainMappings)!1!==r.enabled&&(n.chains.some(e=>e.id===r.sourceChainId)||o.push({severity:"error",code:"missing-source-chain",message:`Mapped source chain "${r.sourceChainId}" no longer exists.`}),t.chains.some(e=>e.id===r.targetChainId)||o.push({severity:"error",code:"missing-target-chain",message:`Mapped target chain "${r.targetChainId}" no longer exists.`}));return o}export function createDefaultAnimationRetargeter(e,n,t,o){const r=new Map(o.chains.map(e=>[e.role,e])),i=t.chains.flatMap(e=>{const n=r.get(e.role);return null==n?[]:[{sourceChainId:e.id,targetChainId:n.id,enabled:!0,rotationMode:"interpolated",translationMode:"root"===e.role?"scaled":"none"}]});return{version:1,solverVersion:9,sourceRigId:e,targetRigId:n,sourceRigFingerprint:{topology:t.topologyFingerprint,bindPose:t.bindPoseFingerprint},targetRigFingerprint:{topology:o.topologyFingerprint,bindPose:o.bindPoseFingerprint},sourcePoseId:t.defaultPoseId,targetPoseId:o.defaultPoseId,chainMappings:i,rootSettings:{scaleTranslation:!0,translationAxes:[!0,!0,!0],translationAxisMap:[1,2,3],scaleMultiplier:1},bakeSettings:{framesPerSecond:60},generatedOutputs:{}}}export function createAutoAlignedRetargetPose(e,n,t,o="auto-aligned",r="Auto Aligned"){const a=P(e,t.sourcePoseId),s=P(n,t.targetPoseId),l={...s?.rotationOffsets??{}},u=R(e,a?.rotationOffsets??{}),c=h(e,n,t),d=new Map(e.bones.map((e,n)=>[e.name,n]));new Map(n.bones.map((e,n)=>[e.name,n]));let p=R(n,l);for(let e=0;e<n.bones.length;e++){const t=n.bones[e],o=c[t.name],r=null==o?null:d.get(o);if(null==r)continue;const a=n.bones.map((e,n)=>({bone:e,index:n})).filter(n=>n.bone.parentIndex===e&&null!=c[n.bone.name]);if(1!==a.length)continue;const s=a[0],g=c[s.bone.name],m=null==g?null:d.get(g);if(null==m)continue;const f=u.worldPositions[m].clone().sub(u.worldPositions[r]),h=p.worldPositions[s.index].clone().sub(p.worldPositions[e]);if(f.lengthSq()<1e-8||h.lengthSq()<1e-8)continue;f.normalize(),h.normalize();const w=(new i).setFromUnitVectors(h,f).multiply(p.worldQuaternions[e]),b=(t.parentIndex>=0?p.worldQuaternions[t.parentIndex].clone().invert():new i).multiply(w);l[t.id]=(new i).fromArray(t.quaternion).invert().multiply(b).normalize().toArray(),p=R(n,l)}return{id:o,name:r,rotationOffsets:l,rootOffset:null==s?.rootOffset?void 0:[...s.rootOffset]}}export function bakeRetargetedAnimationClip(r){const p=validateAnimationRetargeter(r.retargeter,r.sourceRig,r.targetRig).filter(e=>"error"===e.severity);if(p.length>0)throw new Error(p.map(e=>e.message).join(" "));const g=S(r.sourceObject,r.sourceRig),m=S(r.targetObject,r.targetRig);if(null==g)throw new Error("The source model does not contain a skinned mesh.");if(null==m)throw new Error("The target model does not contain a skinned mesh.");r.sourceObject.updateMatrixWorld(!0);const f=F(r.sourceRig,r.sourceRig.retargetRootBoneId)??g.skeleton.bones[0]?.name;if(null==f)throw new Error("The source rig has no retarget root.");const w=g.skeleton.getBoneByName(f),b=w?.parent?.getWorldQuaternion(new i)??new i,y=function(e){const n=new l;n.name="RetargetSourceRig";const o=e.bones.map(e=>{const n=new t;return n.name=e.name,n.position.fromArray(e.position),n.quaternion.fromArray(e.quaternion),n.scale.fromArray(e.scale),n});for(let t=0;t<o.length;t++){const r=e.bones[t].parentIndex;r>=0?o[r].add(o[t]):n.add(o[t])}return n.bind(new s(o)),n}(r.sourceRig),I=y,x=d.clone(r.targetObject);I.quaternion.copy(resolveAnimationRigBasisRotation(r.sourceRig)).multiply(b),x.quaternion.premultiply(resolveAnimationRigBasisRotation(r.targetRig)),I.updateMatrixWorld(!0),x.updateMatrixWorld(!0);const R=S(x,r.targetRig);if(null==R)throw new Error("Failed to clone the target skeleton.");A(y,r.sourceRig,P(r.sourceRig,r.retargeter.sourcePoseId)),A(R,r.targetRig,P(r.targetRig,r.retargeter.targetPoseId));const v=h(r.sourceRig,r.targetRig,r.retargeter),$=function(t,r,s,l,u,c,d){const p=P(s,u.sourcePoseId),g=P(l,u.targetPoseId),m=new Map(t.skeleton.bones.map(e=>[e.name,e]));A(t,s,p),A(r,l,g);const f=new Map;for(const e of t.skeleton.bones)f.set(e.name,e.getWorldQuaternion(new i));const h=new Map,w=new Map;for(const e of r.skeleton.bones)h.set(e.name,e.getWorldQuaternion(new i)),w.set(e.name,{position:e.position.clone(),quaternion:e.quaternion.clone(),scale:e.scale.clone()});const b=r.skeleton.bones.flatMap(e=>{const n=d[e.name],t=null==n?null:m.get(n),o=null==n?null:f.get(n),r=h.get(e.name);return null==t||null==o||null==r?[]:[{targetBone:e,sourceBone:t,sourceReference:o,targetReference:r,times:[],values:[],previous:null}]}),y=Math.max(60,u.bakeSettings.framesPerSecond),I=Math.max(1,Math.ceil(c.duration*y)),x=I+1,R=new n(t),v=R.clipAction(c);v.setLoop(o,1),v.clampWhenFinished=!0,v.play();const k=new i,F=new i,S=new i,$=new i,O=new i;for(let e=0;e<x;e++){const n=c.duration*e/I;M(t,s),R.setTime(n),B(t,s,p),t.updateMatrixWorld(!0);for(const e of r.skeleton.bones){const n=w.get(e.name);null!=n&&(e.position.copy(n.position),e.quaternion.copy(n.quaternion),e.scale.copy(n.scale))}r.updateMatrixWorld(!0);for(const e of b)e.sourceBone.getWorldQuaternion(F),k.copy(F).multiply($.copy(e.sourceReference).invert()),S.copy(k).multiply(e.targetReference),null!=e.targetBone.parent?(e.targetBone.parent.getWorldQuaternion($).invert(),O.copy($).multiply(S)):O.copy(S),O.normalize(),null!=e.previous&&e.previous.dot(O)<0&&O.set(-O.x,-O.y,-O.z,-O.w),e.targetBone.quaternion.copy(O),e.targetBone.updateMatrixWorld(!0),e.times.push(n),e.values.push(O.x,O.y,O.z,O.w),e.previous??(e.previous=new i),e.previous.copy(O)}return R.stopAllAction(),R.uncacheRoot(t),new e(c.name,c.duration,b.map(e=>new a(`.bones[${e.targetBone.name}].quaternion`,e.times,e.values)))}(y,R,r.sourceRig,r.targetRig,r.retargeter,r.clip,v),O=F(r.targetRig,r.targetRig.retargetRootBoneId);return null!=O&&function(e,n,t,o,r,a,s,l,d){const p=e.tracks.find(e=>e instanceof c&&z(e.name,t)),g=F(r,r.pelvisBoneId),m=F(a,a.pelvisBoneId),f=null==g||g===t?void 0:e.tracks.find(e=>e instanceof c&&z(e.name,g));if(null==p&&null==f)return;const h=k(r),w=k(a),b=s.rootSettings.scaleTranslation&&h>0?w/h*s.rootSettings.scaleMultiplier:s.rootSettings.scaleMultiplier,y=Math.max(60,s.bakeSettings.framesPerSecond),I=Math.max(2,Math.ceil(e.duration*y)+1),x=new Float32Array(I),R=p?.createInterpolant(),v=null==R?null:Float32Array.from(R.evaluate(0)),M=f?.createInterpolant();A(l,r,P(r,s.sourcePoseId)),A(d,a,P(a,s.targetPoseId));const B=l.skeleton.getBoneByName(t),S=d.skeleton.getBoneByName(o),$=B?.parent?.getWorldQuaternion(new i)??new i,O=(S?.parent?.getWorldQuaternion(new i)??new i).invert(),q=null==g?void 0:l.skeleton.getBoneByName(g),C=null==m?void 0:d.skeleton.getBoneByName(m),N=q?.parent?.getWorldQuaternion(new i)??new i,W=(C?.parent?.getWorldQuaternion(new i)??new i).invert(),T=P(a,s.targetPoseId)?.rootOffset??[0,0,0],Q=a.bones.find(e=>e.name===o),E=(Q?.position??[0,0,0]).map((e,n)=>e+T[n]),j=null==m?void 0:a.bones.find(e=>e.name===m),D=m===o?E:j?.position??[0,0,0],L=null!=p||null!=f&&m===o?new Float32Array(3*I):null,_=null!=f&&null!=m&&m!==o?new Float32Array(3*I):null,U=new u,G=new u,H=new u,V=new u,Y=(e,n,t)=>{G.copy(e).applyQuaternion(n),H.set(0,0,0);for(let e=0;e<3;e++)if(s.rootSettings.translationAxes[e]){const n=s.rootSettings.translationAxisMap?.[e]??e+1,t=Math.max(0,Math.min(2,Math.abs(n)-1));H.setComponent(e,G.getComponent(t)*Math.sign(n||1))}return V.copy(H).applyQuaternion(t).multiplyScalar(b)};for(let n=0;n<I;n++){const t=Math.min(e.duration,n/y);if(x[n]=t,null!=L&&(L.set(E,3*n),null!=R&&null!=v)){const e=R.evaluate(t);U.set(e[0]-v[0],e[1]-v[1],e[2]-v[2]);const o=Y(U,$,O);L[3*n]+=o.x,L[3*n+1]+=o.y,L[3*n+2]+=o.z}if(null!=M&&null!=q&&null!=m){const e=M.evaluate(t);U.set(e[0]-q.position.x,e[1]-q.position.y,e[2]-q.position.z);const r=m===o,i=Y(U,N,r?O:W),a=r?L:_;null!=a&&(r||a.set(D,3*n),a[3*n]+=i.x,a[3*n+1]+=i.y,a[3*n+2]+=i.z)}}const Z=new Set([null==L?null:o,null==_?null:m].filter(e=>null!=e));n.tracks=n.tracks.filter(e=>!(e instanceof c&&[...Z].some(n=>z(e.name,n)))),null!=L&&n.tracks.push(new c(`.bones[${o}].position`,x,L));null!=_&&null!=m&&n.tracks.push(new c(`.bones[${m}].position`,x,_))}(r.clip,$,f,O,r.sourceRig,r.targetRig,r.retargeter,y,R),$.name=r.clip.name,$.optimize(),$}export function getAnimationRigIdFromObject(e){if(null==e)return;let n=e.userData?.animationRigId;return null!=n||e.traverse(e=>{n??(n=e.userData?.animationRigId)}),n}export function getAnimationRigDataFromObject(e){if(null==e)return;let n=e.userData?.animationRig;return null!=n||e.traverse(e=>{n??(n=e.userData?.animationRig)}),n}export function getAnimationRigChainBoneNames(e,n){if(null==e)return[];const t=e.chains.find(e=>e.role===n);return null==t?[]:v(e,t).map(e=>e.name)}export function getAnimationClipBoneNames(e){const n=new Set;for(const t of e.tracks){const e=t.name.match(/\.bones\[([^\]]+)\]\./);if(null!=e?.[1]){n.add(e[1]);continue}const o=t.name.lastIndexOf(".");o>0&&n.add(t.name.slice(0,o))}return[...n]}export function isAnimationClipCompatibleWithRig(e,n){const t=new Set(n.bones.map(e=>e.name));return getAnimationClipBoneNames(e).some(e=>t.has(e))}export function getAnimationClipRigId(e){return null==e?void 0:Q.get(e)}export function setAnimationClipRigId(e,n){null==n?Q.delete(e):Q.set(e,n)}export function findGeneratedAnimationOutput(e,n,t){for(const o of e){const r=o.animationRetargeter;if("animationRetargeter"===o.type&&r?.targetRigId===t&&null!=r.generatedOutputs[n]){const t=r.generatedOutputs[n];return e.find(e=>e.id===t)}}}export function resolveAnimationClipAssetForTarget(e,n,t){if(null==t||e.anim?.rigId===t)return e;if(null==e.anim?.rigId){const n=`${e.id}|${t}`;return p.has(n)||(p.add(n),console.warn(`Animation clip "${e.name}" (${e.id}) has no rig assigned, while the target uses rig ${t}. Playing the legacy source clip without rig compatibility validation.`)),e}const o=findGeneratedAnimationOutput(n,e.id,t);if(null==o)throw new Error(`Animation clip "${e.name}" (${e.id}) targets rig ${e.anim?.rigId??"unassigned"}, but the bound sequence actor uses rig ${t}. Generate this source/target output in an Animation Retargeter before playback.`);if(o.anim?.rigId!==t)throw new Error(`Generated animation clip "${o.name}" (${o.id}) is indexed for rig ${t}, but its clip metadata targets ${o.anim?.rigId??"no rig"}. Regenerate the output.`);return o}const p=new Set;function g(e,n){const o=new Map(n.bones.map((e,n)=>[e,n])),a=new Set(n.bones.filter(e=>function(e,n,o){const r=e.parent;if(!(r instanceof t&&r.name===e.name&&o.has(r)))return!1;if(e.position.lengthSq()>1e-12||Math.abs(e.quaternion.x)>1e-6||Math.abs(e.quaternion.y)>1e-6||Math.abs(e.quaternion.z)>1e-6||Math.abs(Math.abs(e.quaternion.w)-1)>1e-6||e.scale.distanceTo(new u(1,1,1))>1e-6)return!1;const i=n.boneInverses[o.get(e)],a=n.boneInverses[o.get(r)];return null!=i&&null!=a&&(s=i,l=a,s.elements.every((e,n)=>Math.abs(e-l.elements[n])<=1e-6));var s,l}(e,n,o))),s=n.bones.filter(e=>!a.has(e)),l=new Map(s.map((e,n)=>[e,n])),c=[];for(let e=0;e<s.length;e++){const a=s[e],d=o.get(a)??e;let p=a.parent;for(;p instanceof t&&!l.has(p);)p=p.parent;const g=p instanceof t?l.get(p)??-1:-1,m=a.name||`bone_${e}`,f=g<0?m:`${c[g].id}/${m}`,h=new u,w=new i,b=new u;a.matrix.decompose(h,w,b),c.push({id:f,name:m,parentIndex:g,position:h.toArray(),quaternion:w.toArray(),scale:b.toArray(),inverseBindMatrix:(n.boneInverses[d]??new r).toArray()})}const d=T(c.map(e=>[e.name,e.parentIndex])),p=T(c.map(e=>[e.name,e.parentIndex,...W(e.position),...W(e.quaternion),...W(e.scale),...W(e.inverseBindMatrix)])),g=function(e){const n=[{role:"spine",start:["spine"],end:["chest","spine2","spine_02","spine3"]},{role:"neck",start:["neck"],end:["head"]},{role:"leftArm",side:"left",start:["upperarm","arm"],end:["hand","wrist"]},{role:"rightArm",side:"right",start:["upperarm","arm"],end:["hand","wrist"]},{role:"leftLeg",side:"left",start:["upleg","thigh","upperleg"],end:["foot","ankle"]},{role:"rightLeg",side:"right",start:["upleg","thigh","upperleg"],end:["foot","ankle"]}],t=[];for(const o of n){const n=o.side?q(e,o.side,o.start):O(e,o.start),r=o.side?q(e,o.side,o.end):O(e,o.end);null!=n&&null!=r&&t.push({id:o.role,name:N(o.role),role:o.role,startBoneId:n.id,endBoneId:r.id})}return t}(c),m=O(c,["root","armature"]),f=O(c,["hips","hip","pelvis"]),h=q(c,"left",["hand","wrist"]),w=q(c,"right",["hand","wrist"]);return{version:1,basisPreset:"auto",basisYawDegrees:0,skinnedMeshName:e?.name||void 0,bones:c,topologyFingerprint:d,bindPoseFingerprint:p,retargetRootBoneId:m?.id??f?.id??c[0]?.id,pelvisBoneId:f?.id,leftHandBoneId:h?.id,rightHandBoneId:w?.id,chains:g,poses:[{id:"default",name:"Default",rotationOffsets:{}}],defaultPoseId:"default"}}function m(e){const n=new Set(e.bones);return e.bones.filter(e=>e.parent instanceof t&&!n.has(e.parent)).length}function f(e){return[...new Set(e.bones.map(e=>e.name))].sort().join("\n")}function h(e,n,t){const o={};for(const r of t.chainMappings){if(!1===r.enabled)continue;const t=e.chains.find(e=>e.id===r.sourceChainId),i=n.chains.find(e=>e.id===r.targetChainId);if(null==t||null==i)continue;const a=v(e,t),s=v(n,i);if(0!==a.length&&0!==s.length)for(let e=0;e<s.length;e++){const n=1===s.length?0:e/(s.length-1),t=Math.round(n*(a.length-1));o[s[e].name]=a[t].name}}return w(o,e,n,"retargetRootBoneId"),w(o,e,n,"pelvisBoneId"),w(o,e,n,"leftHandBoneId"),w(o,e,n,"rightHandBoneId"),b(o,e,n,"leftHandBoneId"),b(o,e,n,"rightHandBoneId"),o}function w(e,n,t,o){const r=F(n,n[o]),i=F(t,t[o]);null!=r&&null!=i&&(e[i]=r)}function b(e,n,t,o){const r=n.bones.findIndex(e=>e.id===n[o]),i=t.bones.findIndex(e=>e.id===t[o]);if(r<0||i<0)return;const a=new Map;for(const e of y(n,r)){const n=I(e.name);null!=n&&a.set(n,e)}for(const n of y(t,i)){const t=I(n.name),o=null==t?null:a.get(t);null!=o&&(e[n.name]=o.name)}}function y(e,n){return e.bones.filter((t,o)=>{let r=e.bones[o].parentIndex;for(;r>=0;){if(r===n)return!0;r=e.bones[r].parentIndex}return!1})}function I(e){const n=e.toLowerCase();if(n.includes("base"))return null;const t=["thumb","index","middle","ring","pinky"].find(e=>n.includes(e));if(null==t)return null;const o=n.slice(n.indexOf(t)+t.length),r=o.match(/\d+/)?.[0];return null==r?null:`${t}:${Number(r)}`}function x(e,n){const t=[],o=[],a=[];for(let s=0;s<e.bones.length;s++){const l=e.bones[s],c=(new i).fromArray(l.quaternion),d=n[l.id];null!=d&&c.multiply((new i).fromArray(d)).normalize();const p=(new r).compose((new u).fromArray(l.position),c,(new u).fromArray(l.scale));l.parentIndex>=0&&p.premultiply(t[l.parentIndex]),t.push(p),o.push((new u).setFromMatrixPosition(p)),a.push((new i).setFromRotationMatrix(p))}return{worldPositions:o,worldQuaternions:a}}function R(e,n){const t=x(e,n),o=resolveAnimationRigBasisRotation(e);for(const e of t.worldPositions)e.applyQuaternion(o);for(const e of t.worldQuaternions)e.premultiply(o);return t}function v(e,n){const t=e.bones.findIndex(e=>e.id===n.startBoneId),o=e.bones.findIndex(e=>e.id===n.endBoneId);if(t<0||o<0)return[];const r=[];let i=o;for(;i>=0;){if(r.push(e.bones[i]),i===t)return r.reverse();i=e.bones[i].parentIndex}return[]}function A(e,n,t){M(e,n),B(e,n,t),e.updateMatrixWorld(!0)}function M(e,n){const t=new Map(e.skeleton.bones.map(e=>[e.name,e]));for(const e of n.bones){const n=t.get(e.name);null!=n&&(n.position.fromArray(e.position),n.quaternion.fromArray(e.quaternion),n.scale.fromArray(e.scale))}}function B(e,n,t){if(null==t)return;const o=new Map(e.skeleton.bones.map(e=>[e.name,e]));for(const[e,r]of Object.entries(t.rotationOffsets)){const t=n.bones.find(n=>n.id===e),a=null==t?void 0:o.get(t.name);null!=a&&a.quaternion.multiply((new i).fromArray(r)).normalize()}const r=F(n,n.retargetRootBoneId),a=null==r?void 0:o.get(r);null!=a&&null!=t.rootOffset&&a.position.add((new u).fromArray(t.rootOffset))}function k(e){const n=e.bones.map(()=>new r),t=e.bones.map(()=>new u);for(let o=0;o<e.bones.length;o++){const r=e.bones[o];n[o].compose((new u).fromArray(r.position),(new i).fromArray(r.quaternion),(new u).fromArray(r.scale)),r.parentIndex>=0&&n[o].premultiply(n[r.parentIndex]),t[o].setFromMatrixPosition(n[o])}const o=e.bones.findIndex(n=>n.id===e.pelvisBoneId),a=e.bones.findIndex(n=>n.id===e.chains.find(e=>"neck"===e.role)?.endBoneId),s=e.chains.filter(e=>"leftLeg"===e.role||"rightLeg"===e.role).map(n=>e.bones.findIndex(e=>e.id===n.endBoneId)).filter(e=>e>=0);if(o>=0&&a>=0&&s.length>0){const e=t[o].distanceTo(t[a]),n=Math.max(...s.map(e=>t[o].distanceTo(t[e])));if(e+n>1e-4)return e+n}let l=0;for(let e=0;e<t.length;e++)for(let n=e+1;n<t.length;n++)l=Math.max(l,t[e].distanceTo(t[n]));return Math.max(1e-4,l)}function P(e,n){return e.poses.find(e=>e.id===n)}function F(e,n){return null==n?void 0:e.bones.find(e=>e.id===n)?.name}function S(e,n){const t=[];if(e.traverse(e=>{$(e)&&t.push(e)}),null==n)return t[0];const o=null==n.skinnedMeshName?void 0:t.find(e=>e.name===n.skinnedMeshName);if(null!=o)return o;const r=t.map(e=>({candidate:e,rig:g(e,e.skeleton)}));return r.find(e=>e.rig.topologyFingerprint===n.topologyFingerprint&&e.rig.bindPoseFingerprint===n.bindPoseFingerprint)?.candidate??r.find(e=>e.rig.topologyFingerprint===n.topologyFingerprint)?.candidate??t[0]}function $(e){return e instanceof l||!0===e.isSkinnedMesh}function O(e,n){return e.find(e=>n.some(n=>C(e.name)===C(n)))??e.find(e=>n.some(n=>C(e.name).includes(C(n))))}function q(e,n,t){const o="left"===n?["left","_l",".l"]:["right","_r",".r"];return e.find(e=>{const n=e.name.toLowerCase(),r=C(n);return o.some(e=>n.includes(e))&&t.some(e=>r.includes(C(e)))})}function C(e){return e.toLowerCase().replace(/^mixamorig[:_]?/,"").replace(/^bip0*1[_:]?/,"").replace(/[^a-z0-9]/g,"")}function N(e){return e.replace(/([a-z])([A-Z])/g,"$1 $2").replace(/^./,e=>e.toUpperCase())}function W(e){return e.map(e=>Math.round(1e5*e)/1e5)}function T(e){const n=JSON.stringify(e);let t=2166136261;for(let e=0;e<n.length;e++)t^=n.charCodeAt(e),t=Math.imul(t,16777619);return(t>>>0).toString(16).padStart(8,"0")}function z(e,n){return e===`${n}.position`||e===`.bones[${n}].position`||e.endsWith(`[${n}].position`)}const Q=new WeakMap;/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{AnimationClip as o,Vector3 as t}from"three";export class RootMotionClip extends o{constructor(){super(...arguments),this.displacement=0,this.fixedInPlace=!1}static fromClip(o,
|
|
1
|
+
import{AnimationClip as o,Vector3 as t}from"three";import{getAnimationClipRigId as e,setAnimationClipRigId as n}from"./retarget.js";export class RootMotionClip extends o{constructor(){super(...arguments),this.displacement=0,this.fixedInPlace=!1}static fromClip(o,i=!1,r){const s=new RootMotionClip(o.name,o.duration,o.tracks.slice(),o.blendMode);if(s.fixedInPlace=i,s.rootBone=r,s.source=o,s.uuid=o.uuid,n(s,e(o)),s.motionTrack=null!=r?o.tracks.find(o=>o.name===`${r.name}.position`):o.tracks.find(o=>o.name.endsWith(".position")),s.motionTrack){s.tracks.splice(s.tracks.indexOf(s.motionTrack),1);const o=(new t).fromArray(s.motionTrack.values,0),e=(new t).fromArray(s.motionTrack.values,s.motionTrack.values.length-3),n=s.motionTrack.clone();for(let o=0;o<s.motionTrack.values.length;o+=3)n.values[o+0]=0,n.values[o+2]=0;s.tracks.push(n),s.displacement=e.distanceTo(o)}else console.error("Could not find root motion track",o,r);return s}static fromClipWithDistance(o,t){const i=new RootMotionClip(o.name,o.duration,o.tracks.slice(),o.blendMode);return i.fixedInPlace=!0,i.source=o,i.uuid=o.uuid,n(i,e(o)),i.displacement=t,i}clone(){const o=RootMotionClip.fromClip(this.source.clone(),this.fixedInPlace,this.rootBone);return o.displacement=this.displacement,o}}let i=53912381;export class BoneLayer{constructor(){this.uuid=i++,this.order=0,this.boneMask=[]}}/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EventGraphPropertyInfo } from './decorators.js';
|
|
2
|
+
export type EventGraphActorTransformProperty = 'position' | 'rotation' | 'scale';
|
|
3
|
+
export declare const EVENT_GRAPH_ACTOR_TRANSFORM_PROPERTIES: readonly EventGraphPropertyInfo[];
|
|
4
|
+
export declare function getEventGraphActorTransformPropertyInfo(property: string): EventGraphPropertyInfo | undefined;
|
|
5
|
+
export declare function isEventGraphActorTransformProperty(property: string): property is EventGraphActorTransformProperty;
|
|
6
|
+
//# sourceMappingURL=actor-transform-properties.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{EVENT_GRAPH_ROTATION_TYPE as e,EVENT_GRAPH_VECTOR3_TYPE as t}from"./types.js";export const EVENT_GRAPH_ACTOR_TRANSFORM_PROPERTIES=Object.freeze([Object.freeze({propertyName:"position",label:"Position",type:t,writable:!0}),Object.freeze({propertyName:"rotation",label:"Rotation",type:e,writable:!0}),Object.freeze({propertyName:"scale",label:"Scale",type:t,writable:!0})]);export function getEventGraphActorTransformPropertyInfo(e){return EVENT_GRAPH_ACTOR_TRANSFORM_PROPERTIES.find(t=>t.propertyName===e)}export function isEventGraphActorTransformProperty(e){return"position"===e||"rotation"===e||"scale"===e}/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EventGraphAssetReference, EventGraphDocument } from './model.js';
|
|
2
|
+
export interface EventGraphAssetReferenceLocation {
|
|
3
|
+
reference: EventGraphAssetReference;
|
|
4
|
+
path: readonly (string | number)[];
|
|
5
|
+
nodeId?: string;
|
|
6
|
+
portId?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Visits every tagged asset reference persisted in an event graph. */
|
|
9
|
+
export declare function visitEventGraphAssetReferences(graph: EventGraphDocument, visit: (location: EventGraphAssetReferenceLocation) => void): void;
|
|
10
|
+
export declare function collectEventGraphAssetReferences(graph: EventGraphDocument): EventGraphAssetReferenceLocation[];
|
|
11
|
+
export declare function isEventGraphAssetReference(value: unknown): value is EventGraphAssetReference;
|
|
12
|
+
//# sourceMappingURL=asset-references.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export function visitEventGraphAssetReferences(s,t){for(let n=0;n<(s.variables?.length??0);n++){const r=s.variables[n].defaultValue;void 0!==r&&e(r,["variables",n,"defaultValue"],t)}for(const n of s.nodes){null!=n.params&&e(n.params,["nodes",n.id,"params"],e=>t({...e,nodeId:n.id}));for(const[s,r]of Object.entries(n.inputs??{}))"value"in r&&e(r.value,["nodes",n.id,"inputs",s,"value"],e=>{t({...e,nodeId:n.id,portId:s})})}}export function collectEventGraphAssetReferences(e){const s=[];return visitEventGraphAssetReferences(e,e=>s.push(e)),s}export function isEventGraphAssetReference(e){if(null==e||Array.isArray(e)||"object"!=typeof e)return!1;const s=e;return"string"==typeof s.assetId&&s.assetId.length>0&&("prefab"===s.assetType||"vfx"===s.assetType||"sequence"===s.assetType)}function e(s,t,n){if(isEventGraphAssetReference(s))n({reference:s,path:t});else if(Array.isArray(s))s.forEach((s,r)=>e(s,[...t,r],n));else if(null!=s&&"object"==typeof s)for(const[r,a]of Object.entries(s))e(a,[...t,r],n)}/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { DataOutput, ExecutionNode, PureNode, type DataCompileResult, type ValueInput } from './graph.js';
|
|
2
|
+
export type CompiledStatement = {
|
|
3
|
+
kind: 'code';
|
|
4
|
+
code: string;
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'if';
|
|
7
|
+
condition: string;
|
|
8
|
+
whenTrue: CompileBlock;
|
|
9
|
+
whenFalse: CompileBlock;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'switch';
|
|
12
|
+
expression: string;
|
|
13
|
+
cases: ReadonlyArray<{
|
|
14
|
+
match: string;
|
|
15
|
+
block: CompileBlock;
|
|
16
|
+
}>;
|
|
17
|
+
defaultCase?: CompileBlock;
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'parallel';
|
|
20
|
+
branches: ReadonlyArray<CompileBlock>;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'forEach';
|
|
23
|
+
arrayExpression: string;
|
|
24
|
+
arrayVariable: string;
|
|
25
|
+
indexVariable: string;
|
|
26
|
+
elementOutput: string;
|
|
27
|
+
indexOutput: string;
|
|
28
|
+
body: CompileBlock;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'forLoop';
|
|
31
|
+
firstIndexExpression: string;
|
|
32
|
+
lastIndexExpression: string;
|
|
33
|
+
firstIndexVariable: string;
|
|
34
|
+
lastIndexVariable: string;
|
|
35
|
+
indexVariable: string;
|
|
36
|
+
indexOutput: string;
|
|
37
|
+
body: CompileBlock;
|
|
38
|
+
} | {
|
|
39
|
+
kind: 'try';
|
|
40
|
+
attempt: string;
|
|
41
|
+
catchVariable: string;
|
|
42
|
+
recover?: string;
|
|
43
|
+
succeeded: string;
|
|
44
|
+
success: CompileBlock;
|
|
45
|
+
error: CompileBlock;
|
|
46
|
+
} | {
|
|
47
|
+
kind: 'completion';
|
|
48
|
+
actorExpression: string;
|
|
49
|
+
eventNodeId: string;
|
|
50
|
+
body: CompileBlock;
|
|
51
|
+
} | {
|
|
52
|
+
kind: 'runtimeCallback';
|
|
53
|
+
callee: string;
|
|
54
|
+
arguments: readonly string[];
|
|
55
|
+
eventNodeId: string;
|
|
56
|
+
body: CompileBlock;
|
|
57
|
+
callbackValueOutput?: string;
|
|
58
|
+
returnValueOutput?: string;
|
|
59
|
+
};
|
|
60
|
+
export interface CompiledExecution {
|
|
61
|
+
source: string;
|
|
62
|
+
async: boolean;
|
|
63
|
+
}
|
|
64
|
+
export declare class CompileBlock {
|
|
65
|
+
readonly statements: CompiledStatement[];
|
|
66
|
+
readonly resolving: Set<PureNode>;
|
|
67
|
+
private values;
|
|
68
|
+
constructor(parent?: CompileBlock);
|
|
69
|
+
emit(code: string): void;
|
|
70
|
+
getValue(node: PureNode): DataCompileResult | undefined;
|
|
71
|
+
setValue(node: PureNode, result: DataCompileResult): void;
|
|
72
|
+
invalidateValues(): void;
|
|
73
|
+
fork(): CompileBlock;
|
|
74
|
+
}
|
|
75
|
+
export declare class CompilationContext {
|
|
76
|
+
private readonly compiler;
|
|
77
|
+
readonly block: CompileBlock;
|
|
78
|
+
constructor(compiler: Compiler, block: CompileBlock);
|
|
79
|
+
get(value: ValueInput): string;
|
|
80
|
+
getOutputVariable(output: DataOutput): string;
|
|
81
|
+
getVariableName(variable: string): string;
|
|
82
|
+
variable(): number;
|
|
83
|
+
}
|
|
84
|
+
export declare class Compiler {
|
|
85
|
+
private outputVariables;
|
|
86
|
+
private variableDeclarations;
|
|
87
|
+
private variableNumber;
|
|
88
|
+
private requiresAsync;
|
|
89
|
+
resolveValue(value: ValueInput, block: CompileBlock): string;
|
|
90
|
+
private getPureOutput;
|
|
91
|
+
getOutputVariable(output: DataOutput): string;
|
|
92
|
+
/** Get the generated local that can be assigned to for a graph variable. */
|
|
93
|
+
getVariableName(variable: string): string;
|
|
94
|
+
build(start: ExecutionNode): string;
|
|
95
|
+
compile(start: ExecutionNode): CompiledExecution;
|
|
96
|
+
private compileExecutionNode;
|
|
97
|
+
private compileRoute;
|
|
98
|
+
private compileContinuation;
|
|
99
|
+
private compilePort;
|
|
100
|
+
private emitBlock;
|
|
101
|
+
private emitStatement;
|
|
102
|
+
private indent;
|
|
103
|
+
private identifier;
|
|
104
|
+
private reset;
|
|
105
|
+
variable(): number;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=compiler.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{DataOutput as e,ExecutionNode as t,PureNode as i}from"./graph.js";export class CompileBlock{constructor(e){this.statements=[],this.resolving=new Set,this.values=new Map(e?.values)}emit(e){e.length>0&&this.statements.push({kind:"code",code:e})}getValue(e){return this.values.get(e)}setValue(e,t){this.values.set(e,t)}invalidateValues(){this.values.clear()}fork(){return new CompileBlock(this)}}export class CompilationContext{constructor(e,t){this.compiler=e,this.block=t}get(e){return this.compiler.resolveValue(e,this.block)}getOutputVariable(e){return this.compiler.getOutputVariable(e)}getVariableName(e){return this.compiler.getVariableName(e)}variable(){return this.compiler.variable()}}export class Compiler{constructor(){this.outputVariables=new Map,this.variableDeclarations=new Map,this.variableNumber=0,this.requiresAsync=!1}resolveValue(n,r){if(n instanceof e){if(n.node instanceof i)return this.getPureOutput(n.node,n.name,r);if(n.node instanceof t)return this.getOutputVariable(n);throw new Error(`Unsupported output owner for ${JSON.stringify(n.name)}`)}if(n instanceof i)return this.getPureOutput(n,"value",r);const o=JSON.stringify(n);if(null==o)throw new Error("Event graph value cannot be serialized to JavaScript");return o}getPureOutput(e,t,i){let n=i.getValue(e);if(null==n){if(i.resolving.has(e))throw new Error(`Circular data dependency at ${e.constructor.name}`);i.resolving.add(e);try{n=e.compileData(new CompilationContext(this,i)),null!=n.setup&&i.emit(n.setup),i.setValue(e,n)}finally{i.resolving.delete(e)}}const r=n.outputs[t];if(null==r)throw new Error(`${e.constructor.name} did not compile an output named ${JSON.stringify(t)}`);return r}getOutputVariable(e){if(!(e.node instanceof t))throw new Error("Only execution nodes need storage for their data outputs");let i=this.outputVariables.get(e);return null==i&&(i=`out_${this.identifier(e.name)}_${this.variable()}`,this.outputVariables.set(e,i)),i}getVariableName(e){let t=this.variableDeclarations.get(e);return null==t&&(t=`v_${this.identifier(e)}_${this.variable()}`,this.variableDeclarations.set(e,t)),t}build(e){return this.compile(e).source}compile(e){this.reset();const t=new CompileBlock;this.compileExecutionNode(e,new Set,t);const i=this.emitBlock(t),n=[...this.variableDeclarations.values(),...this.outputVariables.values()];return{source:(n.length>0?`let ${n.join(", ")}\n`:"")+i,async:this.requiresAsync}}compileExecutionNode(e,t,i){if(t.has(e)){const t=e.id??e.constructor.name;throw new Error(`Unstructured execution cycle at ${JSON.stringify(t)}. Use a loop node that compiles to native JavaScript control flow.`)}t.add(e);try{const n=new CompilationContext(this,i),r=e.compileExecution(n);if(null!=r.chunk&&i.emit(r.chunk),null!=r.done&&(i.emit(`await ${r.done}`),this.requiresAsync=!0,i.invalidateValues()),!0===r.requiresAsync&&(this.requiresAsync=!0),!0===r.invalidatesValues&&i.invalidateValues(),null==r.route){const n=[...e.getExecutionOutputs().keys()].filter(e=>"then"!==e);if(n.length>0)throw new Error(`${e.constructor.name} connects named execution outputs ${n.map(e=>JSON.stringify(e)).join(", ")} but does not compile a route for them.`);this.compilePort(e,"then",t,i)}else this.compileRoute(e,r.route,t,i)}finally{t.delete(e)}}compileRoute(e,t,i,n){if("branch"===t.kind){const r=n.fork(),o=n.fork();return this.compilePort(e,t.truePort,i,r),this.compilePort(e,t.falsePort,i,o),n.statements.push({kind:"if",condition:t.condition,whenTrue:r,whenFalse:o}),void this.compileContinuation(e,t.continuationPort,i,n)}if("select"===t.kind){const r=t.cases.map(({match:t,port:r})=>{const o=n.fork();return this.compilePort(e,r,i,o),{match:t,block:o}});let o;return null!=t.defaultPort&&(o=n.fork(),this.compilePort(e,t.defaultPort,i,o)),n.statements.push({kind:"switch",expression:t.expression,cases:r,defaultCase:o}),void this.compileContinuation(e,t.continuationPort,i,n)}if("parallel"===t.kind){this.requiresAsync=!0;const r=t.ports.map(t=>{const r=n.fork();return this.compilePort(e,t,i,r),r}).filter(e=>e.statements.length>0);return r.length>0&&(n.statements.push({kind:"parallel",branches:r}),n.invalidateValues()),void this.compilePort(e,t.continuationPort,i,n)}if("sequence"===t.kind){for(const r of t.ports)n.invalidateValues(),this.compilePort(e,r,i,n);return void this.compileContinuation(e,t.continuationPort,i,n)}if("forEach"===t.kind){const r=n.fork();return r.invalidateValues(),this.compilePort(e,t.bodyPort,i,r),n.statements.push({kind:"forEach",arrayExpression:t.arrayExpression,arrayVariable:`array_${this.variable()}`,indexVariable:`index_${this.variable()}`,elementOutput:t.elementOutput,indexOutput:t.indexOutput,body:r}),n.invalidateValues(),void this.compilePort(e,t.continuationPort,i,n)}if("forLoop"===t.kind){const r=n.fork();return r.invalidateValues(),this.compilePort(e,t.bodyPort,i,r),n.statements.push({kind:"forLoop",firstIndexExpression:t.firstIndexExpression,lastIndexExpression:t.lastIndexExpression,firstIndexVariable:`firstIndex_${this.variable()}`,lastIndexVariable:`lastIndex_${this.variable()}`,indexVariable:`index_${this.variable()}`,indexOutput:t.indexOutput,body:r}),n.invalidateValues(),void this.compilePort(e,t.continuationPort,i,n)}if("completion"===t.kind){const r=n.fork();return r.invalidateValues(),this.compilePort(e,t.completedPort,i,r),r.statements.length>0&&n.statements.push({kind:"completion",actorExpression:t.actorExpression,eventNodeId:e.id??e.constructor.name,body:r}),void this.compilePort(e,t.continuationPort,i,n)}if("runtimeCallback"===t.kind){const r=n.fork();return r.invalidateValues(),this.compilePort(e,t.completedPort,i,r),n.statements.push({kind:"runtimeCallback",callee:t.callee,arguments:t.arguments,eventNodeId:e.id??e.constructor.name,body:r,callbackValueOutput:t.callbackValueOutput,returnValueOutput:t.returnValueOutput}),n.invalidateValues(),void this.compilePort(e,t.continuationPort,i,n)}const r=`succeeded_${this.variable()}`,o=n.fork(),a=n.fork();this.compilePort(e,t.successPort,i,o),this.compilePort(e,t.errorPort,i,a),n.statements.push({kind:"try",attempt:t.attempt,catchVariable:t.catchVariable,recover:t.recover,succeeded:r,success:o,error:a}),this.compileContinuation(e,t.continuationPort,i,n)}compileContinuation(e,t,i,n){null!=t&&(n.invalidateValues(),this.compilePort(e,t,i,n))}compilePort(e,t,i,n){const r=e.getExecutionOutputs().get(t);null!=r&&this.compileExecutionNode(r,i,n)}emitBlock(e){return e.statements.map(e=>this.emitStatement(e)).filter(e=>e.length>0).join("\n")}emitStatement(e){if("code"===e.kind)return e.code;if("if"===e.kind){const t=this.emitBlock(e.whenTrue),i=this.emitBlock(e.whenFalse);return 0===t.length&&0===i.length?"":0===i.length?`if (${e.condition}) {\n${this.indent(t)}\n}`:0===t.length?`if (!(${e.condition})) {\n${this.indent(i)}\n}`:[`if (${e.condition}) {`,this.indent(t),"} else {",this.indent(i),"}"].join("\n")}if("switch"===e.kind){const t=e.cases.map(({match:e,block:t})=>{const i=this.emitBlock(t),n=i.length>0?`${i}\nbreak`:"break";return[`case ${e}: {`,this.indent(n),"}"].join("\n")});if(null!=e.defaultCase){const i=this.emitBlock(e.defaultCase);t.push(["default: {",this.indent(i),"}"].join("\n"))}return[`switch (${e.expression}) {`,this.indent(t.join("\n")),"}"].join("\n")}if("parallel"===e.kind){const t=e.branches.map(e=>["(async () => {",this.indent(this.emitBlock(e)),"})()"].join("\n"));return["await Promise.all([",this.indent(t.join(",\n")),"])"].join("\n")}if("forEach"===e.kind){const t=[`${e.indexOutput} = ${e.indexVariable}`,`${e.elementOutput} = ${e.arrayVariable}[${e.indexVariable}]`,this.emitBlock(e.body)].filter(e=>e.length>0).join("\n");return[`const ${e.arrayVariable} = ${e.arrayExpression}`,`if (!Array.isArray(${e.arrayVariable})) throw new Error("For Each requires an array")`,`for (let ${e.indexVariable} = 0; ${e.indexVariable} < ${e.arrayVariable}.length; ${e.indexVariable}++) {`,this.indent(t),"}"].join("\n")}if("forLoop"===e.kind){const t=[`${e.indexOutput} = ${e.indexVariable}`,this.emitBlock(e.body)].filter(e=>e.length>0).join("\n");return[`const ${e.firstIndexVariable} = ${e.firstIndexExpression}`,`const ${e.lastIndexVariable} = ${e.lastIndexExpression}`,`if (!Number.isSafeInteger(${e.firstIndexVariable}) || !Number.isSafeInteger(${e.lastIndexVariable})) throw new Error("For Loop indices must be safe integers")`,`if (${e.lastIndexVariable} - ${e.firstIndexVariable} > 100000) throw new Error("For Loop exceeds the 100000 iteration safety limit")`,`for (let ${e.indexVariable} = ${e.firstIndexVariable}; ${e.indexVariable} <= ${e.lastIndexVariable}; ${e.indexVariable}++) {`,this.indent(t),"}"].join("\n")}if("completion"===e.kind)return[`runtime.onActorCompleted(${e.actorExpression}, async () => {`,this.indent(this.emitBlock(e.body)),`}, ${JSON.stringify(e.eventNodeId)})`].join("\n");if("runtimeCallback"===e.kind){const t=this.emitBlock(e.body),i=null!=e.callbackValueOutput?`callbackValue_${this.variable()}`:void 0,n=[...null!=i?[`${e.callbackValueOutput} = ${i}`]:[],...t.length>0?[t]:[]].join("\n"),r=0===t.length?"undefined":[`async (${i??""}) => {`,this.indent(n),"}"].join("\n"),o=[`${e.callee}(`,this.indent([...e.arguments,r,JSON.stringify(e.eventNodeId)].join(",\n")),")"].join("\n");return null!=e.returnValueOutput?`${e.returnValueOutput} = ${o}`:o}const t=this.emitBlock(e.success),i=this.emitBlock(e.error),n=null==e.recover?"":`\n${this.indent(e.recover)}`,r=[`let ${e.succeeded} = false`,"try {",this.indent(e.attempt),` ${e.succeeded} = true`,`} catch (${e.catchVariable}) {${n}`,"}"];return t.length>0&&i.length>0?r.push(`if (${e.succeeded}) {`,this.indent(t),"} else {",this.indent(i),"}"):t.length>0?r.push(`if (${e.succeeded}) {\n${this.indent(t)}\n}`):i.length>0&&r.push(`if (!${e.succeeded}) {\n${this.indent(i)}\n}`),r.join("\n")}indent(e,t=1){const i=" ".repeat(t);return e.split("\n").map(e=>`${i}${e}`).join("\n")}identifier(e){const t=e.replace(/[^a-zA-Z0-9_$]/g,"_");return t.length>0?t:"value"}reset(){this.outputVariables=new Map,this.variableDeclarations=new Map,this.variableNumber=0,this.requiresAsync=!1}variable(){return++this.variableNumber}}/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type EventGraphType, type EventGraphTypeSource } from './types.js';
|
|
2
|
+
export interface EventGraphParameterInfo {
|
|
3
|
+
name: string;
|
|
4
|
+
type: EventGraphType;
|
|
5
|
+
optional?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface EventGraphCallableInfo {
|
|
8
|
+
methodName: string;
|
|
9
|
+
label: string;
|
|
10
|
+
parameters: EventGraphParameterInfo[];
|
|
11
|
+
/** False when decorator metadata was unavailable and no explicit signature was supplied. */
|
|
12
|
+
parametersKnown: boolean;
|
|
13
|
+
returnType: EventGraphType;
|
|
14
|
+
awaitResult: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface EventGraphEventSourceInfo {
|
|
17
|
+
methodName: string;
|
|
18
|
+
label: string;
|
|
19
|
+
parameters: EventGraphParameterInfo[];
|
|
20
|
+
/** False when decorator metadata was unavailable and no explicit signature was supplied. */
|
|
21
|
+
parametersKnown: boolean;
|
|
22
|
+
valueType: EventGraphType;
|
|
23
|
+
valueLabel: string;
|
|
24
|
+
}
|
|
25
|
+
export type EventGraphParameterOptions = EventGraphTypeSource | {
|
|
26
|
+
name?: string;
|
|
27
|
+
type: EventGraphTypeSource;
|
|
28
|
+
optional?: boolean;
|
|
29
|
+
};
|
|
30
|
+
export interface EventGraphCallableOptions {
|
|
31
|
+
label?: string;
|
|
32
|
+
parameters?: EventGraphParameterOptions[];
|
|
33
|
+
returns?: EventGraphTypeSource;
|
|
34
|
+
awaitResult?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface EventGraphEventSourceOptions {
|
|
37
|
+
label?: string;
|
|
38
|
+
parameters?: EventGraphParameterOptions[];
|
|
39
|
+
/** Payload type emitted by the returned Observable. */
|
|
40
|
+
emits?: EventGraphTypeSource;
|
|
41
|
+
valueLabel?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface EventGraphPropertyInfo {
|
|
44
|
+
propertyName: string;
|
|
45
|
+
label: string;
|
|
46
|
+
type: EventGraphType;
|
|
47
|
+
writable: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface EventGraphPropertyOptions {
|
|
50
|
+
label?: string;
|
|
51
|
+
type?: EventGraphTypeSource;
|
|
52
|
+
writable?: boolean;
|
|
53
|
+
/** Required to preserve the generic value type erased from Observable<T> at runtime. */
|
|
54
|
+
observableValueType?: EventGraphTypeSource;
|
|
55
|
+
}
|
|
56
|
+
/** Marks an actor or component method as callable by event graphs. */
|
|
57
|
+
export declare function EventGraphCallable(...args: any[]): any;
|
|
58
|
+
/** Marks an actor or component property as readable and optionally writable/subscribable. */
|
|
59
|
+
export declare function EventGraphProperty(...args: any[]): any;
|
|
60
|
+
/** Marks an Observable-returning actor or component method as an event source. */
|
|
61
|
+
export declare function EventGraphEventSource(...args: any[]): any;
|
|
62
|
+
export declare function isEventGraphCallable(target: object, method: string): boolean;
|
|
63
|
+
export declare function isEventGraphEventSource(target: object, method: string): boolean;
|
|
64
|
+
export declare function isEventGraphProperty(target: object, property: string): boolean;
|
|
65
|
+
export declare function getEventGraphCallableMethods(target: object): string[];
|
|
66
|
+
export declare function getEventGraphEventSourceMethods(target: object): string[];
|
|
67
|
+
export declare function getEventGraphProperties(target: object): string[];
|
|
68
|
+
export declare function getEventGraphCallableInfo(target: object, method: string): EventGraphCallableInfo | undefined;
|
|
69
|
+
export declare function getEventGraphCallableInfos(target: object): EventGraphCallableInfo[];
|
|
70
|
+
export declare function getEventGraphEventSourceInfo(target: object, method: string): EventGraphEventSourceInfo | undefined;
|
|
71
|
+
export declare function getEventGraphEventSourceInfos(target: object): EventGraphEventSourceInfo[];
|
|
72
|
+
export declare function getEventGraphPropertyInfo(target: object, property: string): EventGraphPropertyInfo | undefined;
|
|
73
|
+
export declare function getEventGraphPropertyInfos(target: object): EventGraphPropertyInfo[];
|
|
74
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{EVENT_GRAPH_ANY_TYPE as e,EVENT_GRAPH_VOID_TYPE as t,resolveEventGraphType as n}from"./types.js";const r=new WeakMap,o=new WeakMap,a=new WeakMap;export function EventGraphCallable(...e){if(m(e))return l({},e);const t=e[0]??{};return(...e)=>l(t,e)}export function EventGraphProperty(...e){if(m(e))return p({},e);const t=e[0]??{};return(...e)=>p(t,e)}export function EventGraphEventSource(...e){if(m(e))return u({},e);const t=e[0]??{};return(...e)=>u(t,e)}export function isEventGraphCallable(e,t){return null!=getEventGraphCallableInfo(e,t)}export function isEventGraphEventSource(e,t){return null!=getEventGraphEventSourceInfo(e,t)}export function isEventGraphProperty(e,t){return null!=getEventGraphPropertyInfo(e,t)}export function getEventGraphCallableMethods(e){return getEventGraphCallableInfos(e).map(e=>e.methodName)}export function getEventGraphEventSourceMethods(e){return getEventGraphEventSourceInfos(e).map(e=>e.methodName)}export function getEventGraphProperties(e){return getEventGraphPropertyInfos(e).map(e=>e.propertyName)}export function getEventGraphCallableInfo(e,t){return h(r,e).get(t)}export function getEventGraphCallableInfos(e){return[...h(r,e).values()]}export function getEventGraphEventSourceInfo(e,t){return h(o,e).get(t)}export function getEventGraphEventSourceInfos(e){return[...h(o,e).values()]}export function getEventGraphPropertyInfo(e,t){return h(a,e).get(t)}export function getEventGraphPropertyInfos(e){return[...h(a,e).values()]}function l(e,t){if(y(t)){const[n,o,a]=t,l=String(o),u=Reflect.getMetadata("design:paramtypes",n,o),p=Reflect.getMetadata("design:returntype",n,o),i=Reflect.hasMetadata("design:returntype",n,o);return g(r,n,l,c(l,e,u,p,i)),a}if(d(t,"method")){const[n,o]=t,a=String(o.name);return o.addInitializer(function(){g(r,Object.getPrototypeOf(this),a,c(a,e))}),n}throw new Error("@EventGraphCallable can only decorate methods")}function u(e,t){if(y(t)){const[n,r,a]=t,l=String(r),u=Reflect.getMetadata("design:paramtypes",n,r);return g(o,n,l,s(l,e,u)),a}if(d(t,"method")){const[n,r]=t,a=String(r.name);return r.addInitializer(function(){g(o,Object.getPrototypeOf(this),a,s(a,e))}),n}throw new Error("@EventGraphEventSource can only decorate methods")}function p(e,t){if(y(t)){const[n,r,o]=t,l=String(r),u=Reflect.getMetadata("design:type",n,r);return g(a,n,l,f(l,e,u,o)),o}if(d(t,"field")||d(t,"accessor")){const[n,r]=t,o=String(r.name);return r.addInitializer(function(){g(a,Object.getPrototypeOf(this),o,f(o,e))}),n}throw new Error("@EventGraphProperty can only decorate fields or accessors")}function i(e){return e.map((e,t)=>"object"!=typeof e||null==e||"kind"in e?{name:`arg${t}`,type:n(e)}:{name:e.name??`arg${t}`,type:n(e.type),...!0===e.optional?{optional:!0}:{}})}function c(r,o,a,l,u=!1){const p=o.parameters??a??[];return{methodName:r,label:o.label??v(r),parameters:i(p),parametersKnown:null!=o.parameters||null!=a,returnType:null!=o.returns?n(o.returns):null!=l?n(l):u?t:e,awaitResult:!0===o.awaitResult||l===Promise}}function s(e,t,r){const o=t.parameters??r??[];return{methodName:e,label:t.label??v(e),parameters:i(o),parametersKnown:null!=t.parameters||null!=r,valueType:n(t.emits),valueLabel:t.valueLabel??"Value"}}function f(e,t,r,o){const a=null==t.observableValueType?n(t.type??r):{kind:"observable",value:n(t.observableValueType)};return{propertyName:e,label:t.label??v(e),type:a,writable:t.writable??(null!=o?.set||null==o)}}function g(e,t,n,r){let o=e.get(t);null==o&&(o=new Map,e.set(t,o)),o.set(n,r)}function h(e,t){const n=new Map;let r="function"==typeof t?t.prototype:t;for(;null!=r;){for(const[t,o]of e.get(r)??[])n.has(t)||n.set(t,o);r=Object.getPrototypeOf(r)}return n}function v(e){const t=e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[_-]+/g," ");return t.length>0?t[0].toUpperCase()+t.slice(1):e}function m(e){return y(e)||2===e.length&&"string"==typeof e[1]?.kind}function y(e){return e.length>=2&&("string"==typeof e[1]||"symbol"==typeof e[1])}function d(e,t){return 2===e.length&&e[1]?.kind===t}/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Euler, Vector2, Vector3 } from 'three';
|
|
2
|
+
import type { EventGraphDocument, EventGraphTransformAxis, EventGraphTransformSpace } from './model.js';
|
|
3
|
+
import { type EventGraphTypeAnalysis, type EventGraphTypeContext } from './type-inference.js';
|
|
4
|
+
export type EventGraphHandler = (runtime: EventGraphExecutionContext, eventValue?: unknown) => unknown;
|
|
5
|
+
export interface EventGraphExecutionContext {
|
|
6
|
+
actor(id: string): unknown;
|
|
7
|
+
component(target: unknown, property: string): unknown;
|
|
8
|
+
getProperty(target: unknown, property: string): unknown;
|
|
9
|
+
setProperty(target: unknown, property: string, value: unknown): void;
|
|
10
|
+
tweenProperty(target: unknown, property: string, to: unknown, duration: number, curve: string, completed: (() => unknown) | undefined, eventNodeId: string): void;
|
|
11
|
+
tweenMoveTo(target: unknown, position: Vector3, duration: number, curve: string, space: EventGraphTransformSpace, completed: (() => unknown) | undefined, eventNodeId: string): void;
|
|
12
|
+
tweenMoveBy(target: unknown, offset: Vector3, duration: number, curve: string, space: EventGraphTransformSpace, completed: (() => unknown) | undefined, eventNodeId: string): void;
|
|
13
|
+
tweenRotateTo(target: unknown, rotation: Euler, duration: number, curve: string, space: EventGraphTransformSpace, completed: (() => unknown) | undefined, eventNodeId: string): void;
|
|
14
|
+
tweenRotateBy(target: unknown, angleDegrees: number, duration: number, curve: string, space: EventGraphTransformSpace, axis: EventGraphTransformAxis, completed: (() => unknown) | undefined, eventNodeId: string): void;
|
|
15
|
+
tweenScaleTo(target: unknown, scale: Vector3, duration: number, curve: string, completed: (() => unknown) | undefined, eventNodeId: string): void;
|
|
16
|
+
tweenScaleBy(target: unknown, factor: Vector3, duration: number, curve: string, completed: (() => unknown) | undefined, eventNodeId: string): void;
|
|
17
|
+
callMethod(target: unknown, method: string, args: unknown[]): unknown;
|
|
18
|
+
actorClass(classId: string): unknown;
|
|
19
|
+
findActorByType(actorClass: unknown): unknown;
|
|
20
|
+
findActorsByType(actorClass: unknown): unknown[];
|
|
21
|
+
bindEventSource(nodeId: string, target: unknown, method: string, args: unknown[], callback: ((value: unknown) => unknown) | undefined, eventNodeId: string): void;
|
|
22
|
+
spawnActor(classId: string): Promise<unknown>;
|
|
23
|
+
spawnPrefab(assetId: string, position: Vector3, rotation: Euler): Promise<{
|
|
24
|
+
instance: unknown;
|
|
25
|
+
mainActor: unknown | null;
|
|
26
|
+
}>;
|
|
27
|
+
playVfx(assetId: string, position: Vector3, rotation: Euler, autoDestroy: boolean): Promise<unknown>;
|
|
28
|
+
playSequence(assetId: string, target: unknown | null, cameraControlEnabled: boolean, autoDestroy: boolean): Promise<unknown>;
|
|
29
|
+
onActorCompleted(actor: unknown, callback: () => unknown, eventNodeId: string): void;
|
|
30
|
+
destroyPrefab(instance: unknown): void;
|
|
31
|
+
destroyActor(actor: unknown): void;
|
|
32
|
+
getVariable(name: string): unknown;
|
|
33
|
+
setVariable(name: string, value: unknown): void;
|
|
34
|
+
delay(durationMs: number): Promise<void>;
|
|
35
|
+
setInterval(nodeId: string, intervalMs: number, callback: (() => unknown) | undefined, eventNodeId: string): number | undefined;
|
|
36
|
+
clearInterval(intervalId: number): void;
|
|
37
|
+
doOnce(nodeId: string, entryPort: string, startClosed: boolean): boolean;
|
|
38
|
+
gate(nodeId: string, entryPort: string, startClosed: boolean): boolean;
|
|
39
|
+
readValue(value: unknown): unknown;
|
|
40
|
+
mathAdd(a: unknown, b: unknown): unknown;
|
|
41
|
+
mathSubtract(a: unknown, b: unknown): unknown;
|
|
42
|
+
mathMultiply(a: unknown, b: unknown): unknown;
|
|
43
|
+
mathDivide(a: unknown, b: unknown): unknown;
|
|
44
|
+
mathModulo(a: unknown, b: unknown): unknown;
|
|
45
|
+
vectorLength(value: unknown): number;
|
|
46
|
+
vectorLengthSquared(value: unknown): number;
|
|
47
|
+
vectorDistance(a: unknown, b: unknown): number;
|
|
48
|
+
vectorDistanceSquared(a: unknown, b: unknown): number;
|
|
49
|
+
vectorNormalize(value: unknown): unknown;
|
|
50
|
+
vectorDot(a: unknown, b: unknown): number;
|
|
51
|
+
vectorCross(a: unknown, b: unknown): Vector3;
|
|
52
|
+
vectorLerp(a: unknown, b: unknown, alpha: number): unknown;
|
|
53
|
+
vectorApplyRotation(value: unknown, rotation: Euler): Vector3;
|
|
54
|
+
createVector2(x: number, y: number): Vector2;
|
|
55
|
+
createVector3(x: number, y: number, z: number): Vector3;
|
|
56
|
+
createEuler(x: number, y: number, z: number): Euler;
|
|
57
|
+
}
|
|
58
|
+
export interface CompiledEventGraphHandler {
|
|
59
|
+
eventNodeId: string;
|
|
60
|
+
source: string;
|
|
61
|
+
async: boolean;
|
|
62
|
+
invoke: EventGraphHandler;
|
|
63
|
+
}
|
|
64
|
+
export interface CompiledObservableEvent extends CompiledEventGraphHandler {
|
|
65
|
+
actorId: string;
|
|
66
|
+
component?: string;
|
|
67
|
+
property: string;
|
|
68
|
+
}
|
|
69
|
+
export type CompiledEventSourceArgument = {
|
|
70
|
+
kind: 'actor';
|
|
71
|
+
actorId: string;
|
|
72
|
+
} | {
|
|
73
|
+
kind: 'actorClass';
|
|
74
|
+
classId: string;
|
|
75
|
+
};
|
|
76
|
+
export interface CompiledEventSourceEvent extends CompiledEventGraphHandler {
|
|
77
|
+
actorId: string;
|
|
78
|
+
component?: string;
|
|
79
|
+
method: string;
|
|
80
|
+
args: CompiledEventSourceArgument[];
|
|
81
|
+
}
|
|
82
|
+
export interface CompiledEventGraph {
|
|
83
|
+
beginPlay: CompiledEventGraphHandler[];
|
|
84
|
+
update: CompiledEventGraphHandler[];
|
|
85
|
+
endPlay: CompiledEventGraphHandler[];
|
|
86
|
+
observables: CompiledObservableEvent[];
|
|
87
|
+
eventSources: CompiledEventSourceEvent[];
|
|
88
|
+
}
|
|
89
|
+
export interface EventGraphDiagnostic {
|
|
90
|
+
code: string;
|
|
91
|
+
severity: 'error' | 'warning';
|
|
92
|
+
nodeId?: string;
|
|
93
|
+
portId?: string;
|
|
94
|
+
path: readonly (string | number)[];
|
|
95
|
+
message: string;
|
|
96
|
+
}
|
|
97
|
+
export interface EventGraphValidationResult {
|
|
98
|
+
diagnostics: readonly EventGraphDiagnostic[];
|
|
99
|
+
typeAnalysis: EventGraphTypeAnalysis | null;
|
|
100
|
+
}
|
|
101
|
+
/** Validates a persisted document, lowers it into node IR, and compiles each event entry point. */
|
|
102
|
+
export declare class EventGraphCompiler {
|
|
103
|
+
compile(graph: EventGraphDocument, typeContext?: EventGraphTypeContext): CompiledEventGraph;
|
|
104
|
+
}
|
|
105
|
+
/** Runs the same structural and type checks used by compilation without throwing. */
|
|
106
|
+
export declare function validateEventGraphDocument(graph: EventGraphDocument, typeContext?: EventGraphTypeContext): EventGraphValidationResult;
|
|
107
|
+
//# sourceMappingURL=document-compiler.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{getActorClassById as e,getComponentClassById as t}from"../actors/type-registry.js";import{collectEventGraphAssetReferences as n,isEventGraphAssetReference as r}from"./asset-references.js";import{Compiler as o}from"./compiler.js";import{ExecutionNode as i,PureNode as s}from"./graph.js";import{normalizeEventGraphDocument as a}from"./model.js";import{EVENT_GRAPH_NODE_DEFINITIONS as u,getEventGraphInputDefault as d,getEventGraphNodePorts as c,getEventGraphPortDefinition as l}from"./registry.js";import{isEventGraphLiteralAssignableToType as p,isEventGraphType as h}from"./types.js";import{analyzeEventGraphTypes as f}from"./type-inference.js";import{BranchNode as w,ClearIntervalNode as m,DelayNode as g,DoOnceNode as y,ForLoopNode as v,GateNode as N,IntervalNode as E,ForEachNode as $,LogNode as k,ParallelNode as S,SequenceNode as b,IsValidNode as I,SelectNode as O,StartNode as J}from"./nodes/execution-nodes.js";import{ActorReferenceNode as x,AssetReferenceNode as A,BinaryOperatorNode as T,CallMethodNode as q,ComponentReferenceNode as C,DestroyActorNode as j,DestroyPrefabNode as M,EventValueNode as P,BindEventSourceNode as R,FindActorByTypeNode as B,FindActorsByTypeNode as z,GetPropertyNode as V,GraphVariableNode as D,LiteralNode as L,NotNode as F,PlaySequenceNode as G,PlayVfxNode as U,RuntimeCallbackNode as W,RuntimeLiteralNode as _,SetGraphVariableNode as H,SetPropertyNode as K,SpawnActorNode as Q,SpawnPrefabNode as X,TryCallMethodNode as Y,VectorApplyRotationNode as Z,VectorBinaryOperatorNode as ee,VectorEqualityNode as te,VectorLerpNode as ne,VectorMathOperatorNode as re,VectorUnaryOperatorNode as oe}from"./nodes/gameplay-nodes.js";import{getEventGraphEventSourceInfo as ie,getEventGraphPropertyInfo as se}from"./decorators.js";const ae=Object.getPrototypeOf(async function(){}).constructor;export class EventGraphCompiler{compile(e,t={}){const n=ue(e=a(e),t),r=n.result.diagnostics.filter(e=>"error"===e.severity);if(r.length>0||null==n.document)throw new Error(`Event graph validation failed:\n${r.map(de).join("\n")}`);const o=n.document,i=n.result.typeAnalysis,s={beginPlay:[],update:[],endPlay:[],observables:[],eventSources:[]};for(const n of e.nodes){if(!0!==u[n.kind].event)continue;const e=new le(o,n,i).compile();if("event.beginPlay"===n.kind&&s.beginPlay.push(e),"event.update"===n.kind&&s.update.push(e),"event.endPlay"===n.kind&&s.endPlay.push(e),"event.observable"===n.kind){const t=Je(n,"component");s.observables.push({...e,actorId:Oe(n,"actorId"),property:Oe(n,"property"),...null!=t?{component:t}:{}})}if("event.source"===n.kind){const r=Je(n,"component"),o=Oe(n,"source"),i=he(pe(n,t),o);s.eventSources.push({...e,actorId:Oe(n,"actorId"),method:o,args:fe(n,i),...null!=r?{component:r}:{}})}}return s}}export function validateEventGraphDocument(e,t={}){return ue(e,t).result}function ue(e,t){e=a(e);const r=[],o=new ce(e);let i=!0;try{o.validate()}catch(e){i=!1,r.push({code:"invalid-structure",severity:"error",path:[],message:e instanceof Error?e.message:String(e)})}i&&r.push(...function(e){const t=new Map(e.nodes.map(e=>[e.id,e])),n=[];for(const r of["data","execution"]){const o=new Map;for(const n of e.edges){const e=t.get(n.from.nodeId);if(null==e||l(e,n.from.port,"outputs")?.kind!==r)continue;const i=o.get(n.from.nodeId)??[];i.push(n),o.set(n.from.nodeId,i)}const i=new Set,s=new Set;let a;const u=e=>{if(i.has(e))return!0;if(s.has(e))return!1;i.add(e);for(const t of o.get(e)??[])if(u(t.to.nodeId))return a=t,!0;return i.delete(e),s.add(e),!1};for(const t of e.nodes)if(u(t.id))break;null!=a&&n.push({code:`${r}-cycle`,severity:"error",nodeId:a.to.nodeId,portId:a.to.port,path:["edges"],message:`Event graph contains a ${r} cycle`})}return n}(e)),i&&r.push(...function(e,t){return null==t.resolveAssetType?[]:n(e).flatMap(e=>{const n=t.resolveAssetType(e.reference.assetId);return void 0===n?[{code:"missing-asset",severity:"error",...null!=e.nodeId?{nodeId:e.nodeId}:{},...null!=e.portId?{portId:e.portId}:{},path:e.path,message:`Asset ${JSON.stringify(e.reference.assetId)} does not exist`}]:n!==e.reference.assetType?[{code:"wrong-asset-type",severity:"error",...null!=e.nodeId?{nodeId:e.nodeId}:{},...null!=e.portId?{portId:e.portId}:{},path:e.path,message:`Expected ${e.reference.assetType} asset, received ${n}`}]:[]})}(e,t));let s=null;if(i)try{s=f(e,t),r.push(...function(e,t){const n=new Set(e.edges.map(e=>Te(e.to))),r=[];for(const o of e.nodes)for(const e of c(o,"inputs"))"data"===e.kind&&!0!==e.optional&&(null!=o.inputs?.[e.name]||n.has(Te({nodeId:o.id,port:e.name}))||void 0===d(o,e.name)&&(ke(o)&&void 0!==Se(t.getInputType(o.id,e.name))||r.push({code:"missing-input",severity:"error",nodeId:o.id,portId:e.name,path:["nodes",o.id,"inputs",e.name],message:`Required input ${JSON.stringify(e.label??e.name)} is not connected and has no fallback value`})));return r}(e,s),...function(e,t){const n=new Map(e.nodes.map(e=>[e.id,e])),r=[],o=new Set,i=e=>{const i=n.get(e.nodeId);if(null==i||null!=l(i,e.port,"outputs",t))return;const s=Te(e);o.has(s)||(o.add(s),r.push({code:"unavailable-output-port",severity:"error",nodeId:i.id,portId:e.port,path:["nodes",i.id,"outputs",e.port],message:`Output ${JSON.stringify(e.port)} is unavailable for its inferred type`}))};for(const t of e.edges)i(t.from);for(const t of e.nodes)for(const e of Object.values(t.inputs??{}))"nodeId"in e&&i(e);return r}(e,s)),r.push(...s.diagnostics.map(e=>({code:"incompatible-type",severity:e.severity,nodeId:e.nodeId,...null!=e.port?{portId:e.port}:{},path:["nodes",e.nodeId,...null!=e.port?["inputs",e.port]:[]],message:e.message})))}catch(e){r.push({code:"type-analysis-failed",severity:"error",path:[],message:e instanceof Error?e.message:String(e)})}return{result:{diagnostics:r,typeAnalysis:s},document:i?o:null}}function de(e){const t=null==e.nodeId?"":` at ${e.nodeId}${null!=e.portId?`:${e.portId}`:""}`;return`[${e.code}]${t} ${e.message}`}class ce{constructor(e){this.graph=e,this.nodes=new Map,this.variables=new Set,this.incomingEdges=new Map,this.executionEdges=new Map}validate(){if(1!==this.graph.version)throw new Error(`Unsupported event graph version ${String(this.graph.version)}`);for(const e of this.graph.variables??[]){if(0===e.name.trim().length)throw new Error("Event graph variable names must not be empty");if(this.variables.has(e.name))throw new Error(`Duplicate event graph variable ${JSON.stringify(e.name)}`);if(null!=e.type&&!h(e.type))throw new Error(`Event graph variable ${JSON.stringify(e.name)} has an invalid type`);if(null!=e.type&&void 0!==e.defaultValue&&!p(e.defaultValue,e.type))throw new Error(`Event graph variable ${JSON.stringify(e.name)} has an incompatible default value`);this.variables.add(e.name)}for(const e of this.graph.nodes){if(this.nodes.has(e.id))throw new Error(`Duplicate event graph node id ${JSON.stringify(e.id)}`);if(null==u[e.kind])throw new Error(`Unknown event graph node kind ${JSON.stringify(e.kind)}`);if(this.nodes.set(e.id,e),e.kind.startsWith("constant.")&&Ee(e),"asset.reference"===e.kind&&!r(e.params?.reference))throw new Error(`Asset Reference node ${JSON.stringify(e.id)} requires a valid reference`);"flow.sequence"!==e.kind&&"flow.parallel"!==e.kind||ye(e),"flow.switch"===e.kind&&ve(e)}for(const e of this.graph.edges){const t=this.getNode(e.from.nodeId),n=this.getNode(e.to.nodeId),r=Ne(t,e.from.port,"outputs"),o=Ne(n,e.to.port,"inputs");if(r.kind!==o.kind)throw new Error(`Event graph edge ${qe(e)} mixes data and execution ports`);if("data"===o.kind){const t=Te(e.to);if(this.incomingEdges.has(t))throw new Error(`Event graph input ${JSON.stringify(t)} has more than one connection`);this.incomingEdges.set(t,e)}if("execution"===r.kind){const t=Te(e.from);if(this.executionEdges.has(t))throw new Error(`Execution output ${JSON.stringify(t)} has more than one connection`);if(!0===u[n.kind].event)throw new Error("Event nodes cannot be reached through execution inputs");this.executionEdges.set(t,e)}}for(const e of this.graph.nodes)for(const[t,n]of Object.entries(e.inputs??{})){if("data"!==Ne(e,t,"inputs").kind)throw new Error(`Explicit node input ${JSON.stringify(`${e.id}:${t}`)} must be a data port`);if("nodeId"in n){if("data"!==Ne(this.getNode(n.nodeId),n.port,"outputs").kind)throw new Error(`Explicit node input ${JSON.stringify(`${e.id}:${t}`)} references an execution port`)}}}getNode(e){const t=this.nodes.get(e);if(null==t)throw new Error(`Event graph references missing node ${JSON.stringify(e)}`);return t}getInput(e,t){const n=this.incomingEdges.get(Te({nodeId:e.id,port:t}))?.from??e.inputs?.[t];if(null!=n)return n;const r=d(e,t);return void 0!==r?{value:r}:void 0}getExecutionTarget(e,t){const n=this.executionEdges.get(Te({nodeId:e.id,port:t}));return null!=n?{node:this.getNode(n.to.nodeId),inputPort:n.to.port}:void 0}}class le{constructor(e,t,n){this.document=e,this.eventNode=t,this.typeAnalysis=n,this.compiler=new o,this.loweredNodes=new Map,this.loweringNodes=new Set,this.connectedExecutionNodes=new Set,this.loweredExecutionNodes=new Map,this.eventValues=new Map}compile(){const e=new J;e.id=this.eventNode.id,this.connectExecutionOutputs(this.eventNode,e);const t=this.compiler.compile(e),n=`"use strict"\n${t.source}`,r=t.async?ae:Function;return{eventNodeId:this.eventNode.id,source:n,async:t.async,invoke:new r("runtime","eventValue",n)}}connectExecutionOutputs(e,t,n="exec"){const r=`${e.id}:${n}`;if(this.connectedExecutionNodes.has(r))return;this.connectedExecutionNodes.add(r);const o=c(e,"outputs").filter(e=>"execution"===e.kind).map(e=>e.name);for(const n of o){const r=this.document.getExecutionTarget(e,n);if(null==r)continue;const o=this.lowerExecutionNode(r.node,r.inputPort);t.connect(n,o),this.connectExecutionOutputs(r.node,o,r.inputPort)}}lowerExecutionNode(e,t="exec"){const n=`${e.id}:${t}`,r=this.loweredExecutionNodes.get(n);if(null!=r)return r;const o=this.lowerNode(e,t);if(!(o instanceof i))throw new Error(`Node ${JSON.stringify(e.id)} cannot be placed on an execution line`);return this.loweredExecutionNodes.set(n,o),o}lowerNode(e,t="exec"){const n=this.loweredNodes.get(e.id),r="flow.doOnce"===e.kind||"flow.gate"===e.kind;if(null!=n&&!r)return n;if(this.loweringNodes.has(e.id))throw new Error(`Circular data dependency at ${JSON.stringify(e.id)}`);if(!0===u[e.kind].event)throw new Error(`Event node ${JSON.stringify(e.id)} cannot be lowered as a regular node`);this.loweringNodes.add(e.id);try{const n=this.createNode(e,t);return n.id=e.id,r||this.loweredNodes.set(e.id,n),n}finally{this.loweringNodes.delete(e.id)}}createNode(e,t="exec"){if(e.kind.startsWith("constant.")){const t=Ee(e),n=this.typeAnalysis.getOutputType(e.id,"value");return $e(n)?new _(t,n):new L(t)}if("compare.equal"===e.kind||"compare.notEqual"===e.kind){const t=this.typeAnalysis.getInputType(e.id,"a");if("vector2"===t.kind||"vector3"===t.kind||"euler"===t.kind)return new te(this.input(e,"a"),this.input(e,"b"),"compare.notEqual"===e.kind)}const n={"math.add":"+","math.subtract":"-","math.multiply":"*","math.divide":"/","math.modulo":"%","compare.equal":"===","compare.notEqual":"!==","compare.greaterThan":">","compare.greaterThanOrEqual":">=","compare.lessThan":"<","compare.lessThanOrEqual":"<=","boolean.and":"&&","boolean.or":"||"}[e.kind];if(null!=n){const t=function(e){return{"math.add":"add","math.subtract":"subtract","math.multiply":"multiply","math.divide":"divide","math.modulo":"modulo"}[e]}(e.kind),r=this.typeAnalysis.getOutputType(e.id,"value");return null==t||"vector2"!==r.kind&&"vector3"!==r.kind?new T(this.input(e,"a"),this.input(e,"b"),n):new re(this.input(e,"a"),this.input(e,"b"),t)}const o=function(e){return{"vector.length":"length","vector.lengthSquared":"lengthSquared","vector.normalize":"normalize"}[e]}(e.kind);if(null!=o)return new oe(this.input(e,"value"),o);const i=function(e){return{"vector.distance":"distance","vector.distanceSquared":"distanceSquared","vector.dot":"dot","vector.cross":"cross"}[e]}(e.kind);if(null!=i)return new ee(this.input(e,"a"),this.input(e,"b"),i);switch(e.kind){case"vector.lerp":return new ne(this.input(e,"a"),this.input(e,"b"),this.input(e,"alpha"));case"vector.applyRotation":return new Z(this.input(e,"value"),this.input(e,"rotation"));case"boolean.not":return new F(this.input(e,"value"));case"flow.branch":return new w(this.input(e,"condition"));case"flow.sequence":return new b(ye(e));case"flow.parallel":return new S(...ye(e));case"flow.switch":return new O(this.input(e,"value"),ve(e));case"flow.delay":return new g(this.input(e,"durationMs"));case"flow.interval":return new E(e.id,this.input(e,"intervalMs"));case"flow.clearInterval":return new m(this.input(e,"timerId"));case"flow.forLoop":return new v(this.input(e,"firstIndex"),this.input(e,"lastIndex"));case"flow.isValid":return new I(this.input(e,"value"));case"flow.forEach":return new $(this.input(e,"array"));case"flow.doOnce":return new y(e.id,t,this.input(e,"startClosed"));case"flow.gate":return new N(e.id,t,this.input(e,"startClosed"));case"debug.log":return new k(this.input(e,"value"));case"variable.get":{const t=Ie(e,this.document.variables);return new D(t)}case"variable.set":{const t=Ie(e,this.document.variables);return new H(t,this.input(e,"value"))}case"actor.reference":return new x(Oe(e,"actorId"));case"asset.reference":return new A(function(e){const t=e.params?.reference;if(!r(t)||0===t.assetId.length)throw new Error(`Node ${JSON.stringify(e.id)} requires a valid asset reference`);return t}(e).assetId);case"actor.component":return new C(this.input(e,"target"),Oe(e,"property"));case"actor.getProperty":return new V(this.input(e,"target"),Oe(e,"property"));case"actor.setProperty":return new K(this.input(e,"target"),Oe(e,"property"),this.input(e,"value"));case"actor.tweenProperty":return new W("tweenProperty",[this.input(e,"target"),Oe(e,"property"),this.input(e,"to"),this.input(e,"duration"),Je(e,"curve")??"Linear"]);case"transform.moveTo":return new W("tweenMoveTo",this.transformTweenArgs(e,"position",!0));case"transform.moveBy":return new W("tweenMoveBy",this.transformTweenArgs(e,"offset",!0));case"transform.rotateTo":return new W("tweenRotateTo",this.transformTweenArgs(e,"rotation",!0));case"transform.rotateBy":return new W("tweenRotateBy",[this.input(e,"target"),this.input(e,"angle"),this.input(e,"duration"),Je(e,"curve")??"Linear",xe(e),Ae(e)]);case"transform.scaleTo":return new W("tweenScaleTo",this.transformTweenArgs(e,"scale",!1));case"transform.scaleBy":return new W("tweenScaleBy",this.transformTweenArgs(e,"factor",!1));case"actor.callMethod":{const t=this.callArguments(e);return new q(this.input(e,"target"),Oe(e,"method"),t,!0===e.params?.awaitResult)}case"actor.tryCallMethod":return new Y(this.input(e,"target"),Oe(e,"method"),this.callArguments(e),!0===e.params?.awaitResult);case"actor.findByType":return new B(this.input(e,"actorClass"));case"actor.findAllByType":return new z(this.input(e,"actorClass"));case"event.bindSource":{const t=this.dynamicEventSourceInfo(e);return new R(e.id,this.input(e,"target"),Oe(e,"source"),this.eventSourceRuntimeArguments(e,t),Je(e,"component"))}case"actor.spawnClass":return new Q(Oe(e,"classId"));case"actor.spawnPrefab":return new X(this.input(e,"prefab"),this.input(e,"position"),this.input(e,"rotation"));case"vfx.play":return new U(this.input(e,"vfx"),this.input(e,"position"),this.input(e,"rotation"),this.input(e,"autoDestroy"));case"sequence.play":return new G(this.input(e,"sequence"),this.input(e,"target"),this.input(e,"cameraControlEnabled"),this.input(e,"autoDestroy"));case"prefab.destroy":return new M(this.input(e,"instance"));case"actor.destroy":return new j(this.input(e,"actor"));default:throw new Error(`Node kind ${JSON.stringify(e.kind)} has no lowering implementation`)}}input(e,t){const n=this.document.getInput(e,t);if(null==n){const n=this.typeAnalysis.getInputType(e.id,t),r=ke(e)?Se(n):void 0;if(void 0!==r)return $e(n)?new _(r,n):r;throw new Error(`Node ${JSON.stringify(e.id)} is missing input ${JSON.stringify(t)}`)}if("value"in n){const r=this.typeAnalysis.getInputType(e.id,t);return $e(r)?new _(n.value,r):n.value}return this.output(n)}transformTweenArgs(e,t,n){return[this.input(e,"target"),this.input(e,t),this.input(e,"duration"),Je(e,"curve")??"Linear",...n?[xe(e)]:[]]}callArguments(e){const t=function(e,t){const n=e.params?.[t];if(null==n)return;if("number"!=typeof n)throw new Error(`Node ${JSON.stringify(e.id)} parameter ${JSON.stringify(t)} must be a number`);return n}(e,"argumentCount")??0;if(!Number.isInteger(t)||t<0)throw new Error(`Call Method node ${JSON.stringify(e.id)} has an invalid argumentCount`);return Array.from({length:t},(t,n)=>this.input(e,`arg${n}`))}dynamicEventSourceInfo(e){let t=this.connectedInputType(e,"target");return t=we(t,Je(e,"component"),Je(e,"componentTypeId")),he(t,Oe(e,"source"))}connectedInputType(e,t){const n=this.document.getInput(e,t);return null!=n&&"nodeId"in n?this.typeAnalysis.getOutputType(n.nodeId,n.port):this.typeAnalysis.getInputType(e.id,t)}eventSourceRuntimeArguments(e,t){let n=0;return t.parameters.map((t,r)=>"actorClass"===t.type.kind?{kind:"actorClass",classId:Oe(e,`arg${r}ActorClassId`)}:this.input(e,"arg"+n++))}output(e){const t=this.document.getNode(e.nodeId);if("data"!==Ne(t,e.port,"outputs").kind)throw new Error(`Socket ${JSON.stringify(Te(e))} is not a data output`);if(!0===u[t.kind].event){if(t.id!==this.eventNode.id)throw new Error(`Handler ${JSON.stringify(this.eventNode.id)} cannot read data from event ${JSON.stringify(t.id)}`);if(!function(e,t){return"event.update"===e.kind&&"deltaTime"===t||"event.observable"===e.kind&&"value"===t||"event.source"===e.kind&&"value"===t}(t,e.port))throw new Error(`Event node ${JSON.stringify(t.id)} has no data output ${JSON.stringify(e.port)}`);let n=this.eventValues.get(e.port);return null==n&&(n=new P,n.id=`${t.id}:${e.port}`,this.eventValues.set(e.port,n)),n}const n=this.lowerNode(t);return n instanceof s&&"value"===e.port?n:n.output(e.port)}}function pe(e,t){const n=Oe(e,"actorId"),r=t.resolveActorClass?.(n);return we(null!=r?{kind:"actor",classId:ge(r)}:{kind:"actor"},Je(e,"component"),Je(e,"componentTypeId"))}function he(e,t){const n=me(e),r=null!=n?ie(n,t):void 0;if(null==r)throw new Error(`Event source ${JSON.stringify(t)} is not exposed to event graphs`);return r}function fe(e,t){return t.parameters.map((n,r)=>{if("actorClass"===n.type.kind)return{kind:"actorClass",classId:Oe(e,`arg${r}ActorClassId`)};if("actor"===n.type.kind)return{kind:"actor",actorId:Oe(e,`arg${r}ActorId`)};throw new Error(`Static event source ${JSON.stringify(t.label)} parameter ${JSON.stringify(n.name)} must be an actor or actor class selector`)})}function we(e,t,n){if(null!=t){const n=function(e,t){const n=me(e);return null!=n?se(n,t):void 0}(e,t)?.type;if(null!=n)return n}return null!=n?{kind:"component",classId:n}:null!=t?{kind:"component"}:e}function me(n){return"actor"===n.kind&&null!=n.classId?e(n.classId):"component"===n.kind&&null!=n.classId?t(n.classId):void 0}function ge(e){return e.__actorId??e.name}function ye(e){const t=e.params?.ports;if(!Array.isArray(t)||0===t.length||t.some(e=>"string"!=typeof e||0===e.length))throw new Error(`${u[e.kind].label} node ${JSON.stringify(e.id)} requires non-empty string ports`);const n=t;if(n.includes("then"))throw new Error(`${u[e.kind].label} node reserves the "then" port for its continuation`);if(new Set(n).size!==n.length)throw new Error(`${u[e.kind].label} node branch names must be unique`);return n}function ve(e){const t=e.params?.cases;if(!Array.isArray(t)||0===t.length)throw new Error(`Switch node ${JSON.stringify(e.id)} requires at least one case`);const n=t.map(t=>{if(null==t||Array.isArray(t)||"object"!=typeof t)throw new Error(`Switch node ${JSON.stringify(e.id)} has an invalid case`);const n=t.port;if("string"!=typeof n||0===n.length||"then"===n||"default"===n)throw new Error(`Switch node ${JSON.stringify(e.id)} has an invalid case port`);if(!Object.prototype.hasOwnProperty.call(t,"value"))throw new Error(`Switch node ${JSON.stringify(e.id)} case ${JSON.stringify(n)} is missing a value`);return{match:be(t.value),port:n}});if(new Set(n.map(e=>e.port)).size!==n.length)throw new Error(`Switch node ${JSON.stringify(e.id)} case ports must be unique`);if(new Set(n.map(e=>e.match)).size!==n.length)throw new Error(`Switch node ${JSON.stringify(e.id)} case values must be unique`);return n}function Ne(e,t,n){const r=l(e,t,n);if(null!=r)return r;throw new Error(`Node ${JSON.stringify(e.id)} has no ${n.slice(0,-1)} port ${JSON.stringify(t)}`)}function Ee(e){const t=e.params?.value;if("constant.vector2"===e.kind||"constant.vector3"===e.kind){const n="constant.vector2"===e.kind?{kind:"vector2"}:{kind:"vector3"};if(!p(t,n))throw new Error(`Node ${JSON.stringify(e.id)} requires a finite ${n.kind} tuple`);return t}const n="constant.boolean"===e.kind?"boolean":"constant.number"===e.kind?"number":"string";if(typeof t!==n)throw new Error(`Node ${JSON.stringify(e.id)} requires a ${n} value`);if("number"==typeof t&&!Number.isFinite(t))throw new Error("Event graph numbers must be finite");return t}function $e(e){return"vector2"===e.kind||"vector3"===e.kind||"euler"===e.kind||"asset"===e.kind||"actorClass"===e.kind||"optional"===e.kind&&$e(e.value)||"array"===e.kind&&$e(e.element)}function ke(e){return"compare.equal"===e.kind||"compare.notEqual"===e.kind}function Se(e){return"boolean"!==e.kind&&("number"===e.kind?0:"string"===e.kind?"":"vector2"===e.kind?[0,0]:"vector3"===e.kind||"euler"===e.kind?[0,0,0]:void 0)}function be(e){if("number"==typeof e&&!Number.isFinite(e))throw new Error("Event graph numbers must be finite");const t=JSON.stringify(e);if(null==t)throw new Error("Event graph value cannot be serialized to JavaScript");return t}function Ie(e,t){const n=Oe(e,"variable");if(!t.has(n))throw new Error(`Node ${JSON.stringify(e.id)} references undeclared variable ${JSON.stringify(n)}`);return n}function Oe(e,t){const n=e.params?.[t];if("string"!=typeof n||0===n.length)throw new Error(`Node ${JSON.stringify(e.id)} requires a non-empty string parameter ${JSON.stringify(t)}`);return n}function Je(e,t){const n=e.params?.[t];if(null!=n&&""!==n){if("string"!=typeof n)throw new Error(`Node ${JSON.stringify(e.id)} parameter ${JSON.stringify(t)} must be a string`);return n}}function xe(e){const t=Je(e,"space")??"local";if("local"!==t&&"world"!==t)throw new Error(`Node ${JSON.stringify(e.id)} has invalid transform space ${JSON.stringify(t)}`);return t}function Ae(e){const t=Je(e,"axis")??"y";if("x"!==t&&"y"!==t&&"z"!==t)throw new Error(`Node ${JSON.stringify(e.id)} has invalid rotation axis ${JSON.stringify(t)}`);return t}function Te(e){return`${e.nodeId}:${e.port}`}function qe(e){return`${Te(e.from)} -> ${Te(e.to)}`}/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{AssignNode as e,BranchNode as n,CallScopeNode as o,ConstantNumberNode as t,DelayNode as c,LogNode as s,ParallelNode as w,ParseNumberNode as l,SplitStringNode as r,StartNode as a,ThisNode as h,VariableNode as i}from"./nodes/index.js";import{Compiler as d}from"./compiler.js";const m=Object.getPrototypeOf(async function(){}).constructor,p=new d;{const d=new a,u=new t(1).add(2),f=new s(u),g=new s(new h),b=new e("assignTest",u.asString().add(" hi")),y=new s(new i("assignTest")),j=new c(1e3),O=new o,T=new w("slow","fast"),P=new c(30),v=new c(5),x=new s("both parallel branches completed"),C=new n(!0),D=new s("branch completed"),F=new l("not a number"),S=new r("hello:world",":"),k=new s(S.before),q=new s(S.after);d.then(f),f.then(g),g.then(b),b.then(y),y.then(j),j.then(O),O.then(T),T.connect("slow",P),P.then(new s("slow branch completed")),T.connect("fast",v),v.then(new s("fast branch completed")).then(q),T.then(x),x.then(C),C.connect("true",F),C.connect("false",new s("condition was false")),C.then(D),D.then(k),k.then(q),F.connect("success",new s(F.value));const z=new s(F.error);F.connect("error",z);const A=p.compile(d);console.log("----- Code -----"),console.log(A.source),console.log("----- Output -----");const B=new(A.async?m:Function)("runtime",A.source);await B.apply({foo:()=>console.log("passed function")},[{delay:e=>new Promise(n=>setTimeout(n,e))}]),console.log("----- Done ------")}/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { CompilationContext } from './compiler.js';
|
|
2
|
+
export type ValueLiteral = string | number | boolean | null | ValueLiteral[] | {
|
|
3
|
+
[key: string]: ValueLiteral;
|
|
4
|
+
};
|
|
5
|
+
export type DataCompileResult = {
|
|
6
|
+
/** Setup emitted once before this node's outputs are first used in a block. */
|
|
7
|
+
setup?: string;
|
|
8
|
+
outputs: Readonly<Record<string, string>>;
|
|
9
|
+
};
|
|
10
|
+
export type ExecutionRoute = {
|
|
11
|
+
kind: 'branch';
|
|
12
|
+
condition: string;
|
|
13
|
+
truePort: string;
|
|
14
|
+
falsePort: string;
|
|
15
|
+
continuationPort?: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: 'select';
|
|
18
|
+
expression: string;
|
|
19
|
+
cases: ReadonlyArray<{
|
|
20
|
+
match: string;
|
|
21
|
+
port: string;
|
|
22
|
+
}>;
|
|
23
|
+
defaultPort?: string;
|
|
24
|
+
continuationPort?: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'parallel';
|
|
27
|
+
ports: ReadonlyArray<string>;
|
|
28
|
+
continuationPort: string;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'sequence';
|
|
31
|
+
ports: ReadonlyArray<string>;
|
|
32
|
+
continuationPort: string;
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'forLoop';
|
|
35
|
+
firstIndexExpression: string;
|
|
36
|
+
lastIndexExpression: string;
|
|
37
|
+
indexOutput: string;
|
|
38
|
+
bodyPort: string;
|
|
39
|
+
continuationPort: string;
|
|
40
|
+
} | {
|
|
41
|
+
kind: 'forEach';
|
|
42
|
+
arrayExpression: string;
|
|
43
|
+
elementOutput: string;
|
|
44
|
+
indexOutput: string;
|
|
45
|
+
bodyPort: string;
|
|
46
|
+
continuationPort: string;
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'try';
|
|
49
|
+
attempt: string;
|
|
50
|
+
catchVariable: string;
|
|
51
|
+
recover?: string;
|
|
52
|
+
successPort: string;
|
|
53
|
+
errorPort: string;
|
|
54
|
+
continuationPort?: string;
|
|
55
|
+
} | {
|
|
56
|
+
kind: 'completion';
|
|
57
|
+
actorExpression: string;
|
|
58
|
+
completedPort: string;
|
|
59
|
+
continuationPort: string;
|
|
60
|
+
} | {
|
|
61
|
+
kind: 'runtimeCallback';
|
|
62
|
+
callee: string;
|
|
63
|
+
arguments: readonly string[];
|
|
64
|
+
completedPort: string;
|
|
65
|
+
continuationPort: string;
|
|
66
|
+
callbackValueOutput?: string;
|
|
67
|
+
returnValueOutput?: string;
|
|
68
|
+
};
|
|
69
|
+
export type ExecutionCompileResult = {
|
|
70
|
+
/** Code executed when control reaches the node. */
|
|
71
|
+
chunk?: string;
|
|
72
|
+
/** A promise that must settle before routing to the next node. */
|
|
73
|
+
done?: string;
|
|
74
|
+
/** Structured control flow that chooses a named execution output. */
|
|
75
|
+
route?: ExecutionRoute;
|
|
76
|
+
/** The node changes values that cached pure computations may depend on. */
|
|
77
|
+
invalidatesValues?: boolean;
|
|
78
|
+
/** The emitted chunk contains await and requires an async handler. */
|
|
79
|
+
requiresAsync?: boolean;
|
|
80
|
+
};
|
|
81
|
+
export declare class DataOutput<T = unknown> {
|
|
82
|
+
readonly node: Node;
|
|
83
|
+
readonly name: string;
|
|
84
|
+
readonly type: T;
|
|
85
|
+
constructor(node: Node, name: string);
|
|
86
|
+
}
|
|
87
|
+
export type ValueInput<T = unknown> = ValueLiteral | PureNode | DataOutput<T>;
|
|
88
|
+
export declare abstract class Node {
|
|
89
|
+
/** Used by editor integrations, breakpoints, and profiling. */
|
|
90
|
+
id?: string;
|
|
91
|
+
private readonly dataOutputs;
|
|
92
|
+
output<T = unknown>(name?: string): DataOutput<T>;
|
|
93
|
+
}
|
|
94
|
+
/** A side-effect-free node whose outputs may inline or share block-local setup. */
|
|
95
|
+
export declare abstract class PureNode extends Node {
|
|
96
|
+
abstract compileData(c: CompilationContext): DataCompileResult;
|
|
97
|
+
}
|
|
98
|
+
/** A node reached through execution pins and emitted as a basic block. */
|
|
99
|
+
export declare abstract class ExecutionNode extends Node {
|
|
100
|
+
private readonly executionOutputs;
|
|
101
|
+
connect(output: string, downstream: ExecutionNode): ExecutionNode;
|
|
102
|
+
then(downstream: ExecutionNode): ExecutionNode;
|
|
103
|
+
getExecutionOutputs(): ReadonlyMap<string, ExecutionNode>;
|
|
104
|
+
abstract compileExecution(c: CompilationContext): ExecutionCompileResult;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=graph.d.ts.map
|