@combos-fun/plugin-renderer-3d 0.0.54 → 0.2.0

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.
@@ -1 +1 @@
1
- "use strict";var e=require("tslib"),t=require("@combos-fun/engine"),o=require("three"),r=require("@combos-fun/inspector-decorator");const s="combosGameObjectId",n="combosTransform3D";function i(e){return!!e?.userData?.[n]}function a(e,t){e.traverse(e=>{e.userData[s]=t})}function c(e){let t=e;for(;t;){const e=t.userData?.[s];if("number"==typeof e)return e;t=t.parent}}function p(e){if(!e)return!0;const t=e.parent;return!t||t===e.scene}function d(e){return{positionX:e.positionX??0,positionY:e.positionY??0,positionZ:e.positionZ??0,rotationX:e.rotationX??0,rotationY:e.rotationY??0,rotationZ:e.rotationZ??0,scaleX:e.scaleX??1,scaleY:e.scaleY??1,scaleZ:e.scaleZ??1}}function h(e){const t=d(e);return[t.positionX,t.positionY,t.positionZ,t.rotationX,t.rotationY,t.rotationZ,t.scaleX,t.scaleY,t.scaleZ].join(",")}function l(e,t){const o=d(e);t.positionX=o.positionX,t.positionY=o.positionY,t.positionZ=o.positionZ,t.rotationX=o.rotationX,t.rotationY=o.rotationY,t.rotationZ=o.rotationZ,t.scaleX=o.scaleX,t.scaleY=o.scaleY,t.scaleZ=o.scaleZ}function m(e){const t=d(e);return 0===t.positionX&&0===t.positionY&&0===t.positionZ&&0===t.rotationX&&0===t.rotationY&&0===t.rotationZ&&1===t.scaleX&&1===t.scaleY&&1===t.scaleZ}function u(e,t){m(t)&&!m(e)&&l(e,t)}const g={none:o.NoToneMapping,aces:o.ACESFilmicToneMapping,linear:o.LinearToneMapping,reinhard:o.ReinhardToneMapping,cineon:o.CineonToneMapping},y=new o.Vector3,f=new o.Euler;class b{constructor(e){this.mixers=new Map,this.models=new Map,this.nodes=new Map,this.defaultLights=[];const{canvas:t,container:r,width:s,height:n,antialias:i=!0,backgroundColor:a=0,backgroundAlpha:c=1}=e;this.scene=new o.Scene,this.shadows=!!e.shadows,this.camera=new o.PerspectiveCamera(75,s/n,.1,1e3),this.camera.position.z=5,this.fallbackCamera=this.camera;const p={antialias:i};t&&(p.canvas=t),c<1&&(p.alpha=!0),this.renderer=new o.WebGLRenderer(p),this.renderer.setSize(s,n),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setClearColor(a,c),this.renderer.toneMapping=g[e.toneMapping??"aces"]??o.ACESFilmicToneMapping,this.renderer.toneMappingExposure=e.toneMappingExposure??1,this.shadows&&(this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=o.PCFSoftShadowMap),!t&&r&&r.appendChild(this.renderer.domElement);const d=new o.AmbientLight(16777215,e.ambientIntensity??.6);this.scene.add(d),this.defaultLights.push(d);const h=new o.DirectionalLight(16777215,e.directionalIntensity??.8);if(h.position.set(5,10,7.5),this.shadows&&(h.castShadow=!0,h.shadow.mapSize.set(1024,1024)),this.scene.add(h),this.defaultLights.push(h),!1!==e.hemisphereLight){const t="object"==typeof e.hemisphereLight?e.hemisphereLight:{},r=new o.HemisphereLight(t.skyColor??16777215,t.groundColor??4473924,t.intensity??.35);this.scene.add(r),this.defaultLights.push(r)}if(e.fog){const t="object"==typeof e.fog?e.fog:{};this.scene.fog=new o.Fog(t.color??a,t.near??8,t.far??40)}this.clock=new o.Clock}update(){const e=this.clock.getDelta();for(const t of this.mixers.values())t.update(e);this.renderer.render(this.scene,this.camera)}hasTransform3DRoot(e){return i(this.nodes.get(e))}applyModelShadows(e){this.shadows&&e.traverse(e=>{const t=e;t.isMesh&&(t.castShadow=!0,t.receiveShadow=!0)})}attachParsedModel(e,t,r,s){if(a(t,e),this.applyModelShadows(t),this.models.set(e,t),this.attachVisual(e,t,s),r&&r.length>0){const s=new o.AnimationMixer(t);this.mixers.set(e,s),t.userData.animations=r}return t}object3DFor(e){return this.nodes.get(e)}attachObject3D(e,t,o){const r=this.nodes.get(e);r&&r!==t&&(this.rehomeRegisteredChildren(r),r.parent?.remove(r)),this.nodes.set(e,t);const s=this.findParentNode(o);t.parent!==s&&s.add(t),o&&this.adoptChildGameObjects(o,t)}attachVisual(e,t,o){a(t,e);const r=this.nodes.get(e);i(r)&&r!==t?t.parent!==r&&r.add(t):this.attachObject3D(e,t,o)}detachVisual(e,t){const o=this.nodes.get(e);return i(o)&&o!==t?(t.parent?.remove(t),t):o===t?this.detachObject3D(e):(t.parent?.remove(t),t)}detachObject3D(e){const t=this.nodes.get(e);if(t)return this.rehomeRegisteredChildren(t),t.parent?.remove(t),this.nodes.delete(e),t}reparentGameObject(e){const t=this.nodes.get(e.id);if(!t)return;const o=this.findParentNode(e);t.parent!==o&&o.add(t)}findParentNode(e){if(!e||p(e))return this.scene;let t=e.parent;for(;t&&t!==e.scene;){const e=this.nodes.get(t.id);if(e)return e;t=t.parent}return this.scene}adoptChildGameObjects(e,t){const o=e.transform?.children;if(o)for(const e of o){const o=e.gameObject;if(!o)continue;const r=this.nodes.get(o.id);r&&r.parent!==t&&t.add(r)}}ensureTransformRoot(e,t){const r=this.nodes.get(e.id);if(i(r))return this.applyTransformPose(r,t),r;const s=new o.Group;if(s.name=e.name,s.userData[n]=!0,a(s,e.id),r&&r!==s){(function(e){const t=d(e);return 0===t.positionX&&0===t.positionY&&0===t.positionZ&&0===t.rotationX&&0===t.rotationY&&0===t.rotationZ&&1===t.scaleX&&1===t.scaleY&&1===t.scaleZ})(t)&&(t.positionX=r.position.x,t.positionY=r.position.y,t.positionZ=r.position.z,t.rotationX=r.rotation.x,t.rotationY=r.rotation.y,t.rotationZ=r.rotation.z,t.scaleX=r.scale.x,t.scaleY=r.scale.y,t.scaleZ=r.scale.z);(r.parent||this.scene).add(s),s.add(r),r.position.set(0,0,0),r.rotation.set(0,0,0),r.scale.set(1,1,1),this.nodes.set(e.id,s),this.adoptChildGameObjects(e,s)}else this.attachObject3D(e.id,s,e);return this.applyTransformPose(s,t),s}applyTransform3D(e,t){const o=this.ensureTransformRoot(e,t);return this.applyTransformPose(o,t),o.updateWorldMatrix(!0,!1),o.getWorldPosition(y),t.worldPositionX=y.x,t.worldPositionY=y.y,t.worldPositionZ=y.z,f.setFromRotationMatrix(o.matrixWorld),t.worldRotationX=f.x,t.worldRotationY=f.y,t.worldRotationZ=f.z,o}applyTransformPose(e,t){const o=d(t);e.position.set(o.positionX,o.positionY,o.positionZ),e.rotation.set(o.rotationX,o.rotationY,o.rotationZ),e.scale.set(o.scaleX,o.scaleY,o.scaleZ)}removeDefaultLights(){if(this.defaultLights.length){for(const e of this.defaultLights)e.parent?.remove(e),e.dispose?.();this.defaultLights=[]}}setActiveCamera(e){const t=this.camera;this.camera=e,t&&(e.aspect=t.aspect),e.updateProjectionMatrix()}restoreFallbackCamera(){this.camera!==this.fallbackCamera&&this.setActiveCamera(this.fallbackCamera)}rehomeRegisteredChildren(e){for(const t of[...e.children]){const e=t.userData?.[s];"number"==typeof e&&this.nodes.get(e)===t&&this.scene.add(t)}}playAnimation(e,t,o){const r=this.mixers.get(e),s=this.models.get(e);if(!r||!s)return;r.stopAllAction();const n=s.userData.animations;if(n&&n[t]){const e=r.clipAction(n[t]);e.timeScale=o,e.play()}}stopAnimation(e){const t=this.mixers.get(e);t&&t.stopAllAction()}removeModel(e){const t=this.models.get(e);t&&(this.detachVisual(e,t),t.traverse(e=>{const t=e;if(t.geometry&&t.geometry.dispose(),t.material){(Array.isArray(t.material)?t.material:[t.material]).forEach(e=>e.dispose())}}),this.models.delete(e));const o=this.mixers.get(e);o&&(o.stopAllAction(),this.mixers.delete(e))}resize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.fallbackCamera!==this.camera&&(this.fallbackCamera.aspect=e/t,this.fallbackCamera.updateProjectionMatrix()),this.renderer.setSize(e,t)}destroy(){for(const e of this.models.keys())this.removeModel(e);this.removeDefaultLights(),this.renderer.dispose(),this.renderer.domElement.remove(),this.nodes.clear(),this.scene=null,this.camera=null,this.fallbackCamera=null,this.renderer=null,this.clock=null}}class C{constructor({game:e,rendererSystem:t}){this.renderers=[],this.game=e,this.rendererSystem=t}register(...e){for(const t of e)t.game=this.game,t.rendererManager=this,t.threeContext=this.rendererSystem.threeContext,this.renderers.push(t)}componentChanged(e){for(const o of e)for(const e of this.renderers){const r=e.observerInfo[o.componentName];if(!r)continue;if(o.type===t.OBSERVER_TYPE.ADD||o.type===t.OBSERVER_TYPE.REMOVE){try{e.componentChanged(o)}catch(e){console.error(`gameObject: ${o.gameObject.name}, ${o.componentName} error.`,o,e)}continue}if(r.findIndex(e=>"string"==typeof e&&"string"==typeof o.prop?e===o.prop:JSON.stringify(e)===JSON.stringify(o.prop))>-1)try{e.componentChanged(o)}catch(e){console.error(`gameObject: ${o.gameObject?.name}, ${o.componentName} componentChanged error.`,o,e)}}}update(e){for(const t of e.components)for(const o of this.renderers){if(o.observerInfo[t.name])try{o.rendererUpdate(e)}catch(o){console.info(`gameObject: ${e.name}, ${t.name} update error`,o)}}}}class D extends t.Component{constructor(){super(...arguments),this.positionX=0,this.positionY=0,this.positionZ=0,this.rotationX=0,this.rotationY=0,this.rotationZ=0,this.scaleX=1,this.scaleY=1,this.scaleZ=1,this.worldPositionX=0,this.worldPositionY=0,this.worldPositionZ=0,this.worldRotationX=0,this.worldRotationY=0,this.worldRotationZ=0}static{this.componentName="Transform3D"}init(e){e&&Object.assign(this,e)}}e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"positionX",description:"Local X position.",editor:"number-stepper"})],D.prototype,"positionX",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"positionY",description:"Local Y position.",editor:"number-stepper"})],D.prototype,"positionY",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"positionZ",description:"Local Z position.",editor:"number-stepper"})],D.prototype,"positionZ",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Transform3D",label:"rotationX",description:"Rotation around X in radians.",editor:"number-stepper"})],D.prototype,"rotationX",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Transform3D",label:"rotationY",description:"Rotation around Y in radians.",editor:"number-stepper"})],D.prototype,"rotationY",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Transform3D",label:"rotationZ",description:"Rotation around Z in radians.",editor:"number-stepper"})],D.prototype,"rotationZ",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"scaleX",description:"Scale on X.",editor:"number-stepper"})],D.prototype,"scaleX",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"scaleY",description:"Scale on Y.",editor:"number-stepper"})],D.prototype,"scaleY",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"scaleZ",description:"Scale on Z.",editor:"number-stepper"})],D.prototype,"scaleZ",void 0);let v=class extends t.System{constructor(){super(...arguments),this.name="Renderer3DSystem"}static{this.systemName="Renderer3DSystem"}init(e){const t=e||{},o=t.width||750,r=t.height||1334;this.threeContext=new b({canvas:t.canvas,container:t.container,width:o,height:r,antialias:t.antialias,backgroundColor:t.backgroundColor,backgroundAlpha:t.backgroundAlpha,fog:t.fog,hemisphereLight:t.hemisphereLight,shadows:t.shadows,toneMapping:t.toneMapping,toneMappingExposure:t.toneMappingExposure,ambientIntensity:t.ambientIntensity,directionalIntensity:t.directionalIntensity}),this.game.canvas=this.threeContext.renderer.domElement,this.rendererManager=new C({game:this.game,rendererSystem:this})}update(e){const t=this.componentObserver.clear();for(const e of t)this.handleHierarchyChange(e);for(const e of this.game.gameObjects){const t=e.getComponent(D);t&&this.threeContext.applyTransform3D(e,t),this.rendererManager.update(e)}}handleHierarchyChange(e){"Transform"===e.componentName&&(e.type!==t.OBSERVER_TYPE.CHANGE&&e.type!==t.OBSERVER_TYPE.ADD||(this.ensureTransform3D(e.gameObject),e.gameObject.parent&&this.ensureTransform3D(e.gameObject.parent),this.threeContext?.reparentGameObject(e.gameObject)))}ensureTransform3D(e){if(!e||e===e.scene)return;let t=e.getComponent(D);t||(t=new D,e.addComponent(t)),this.threeContext?.ensureTransformRoot(e,t)}lateUpdate(){this.threeContext?.update()}resize(e,t){this.threeContext?.resize(e,t)}onDestroy(){this.threeContext?.destroy(),this.threeContext=null}};v=e.__decorate([t.decorators.componentObserver({Transform:["_parent"]})],v);var x=v;Object.assign(x,{packageName:"@combos-fun/plugin-renderer-3d",packageVersion:"0.0.54"});class O extends t.System{constructor(e){super(e),this.asyncIdMap={};const t=this.constructor;this.observerInfo=t.observerInfo}componentChanged(e){}rendererUpdate(e){}update(e){const t=this.componentObserver.clear();for(const e of t)this.componentChanged(e)}increaseAsyncId(e){return this.asyncIdMap[e]=(this.asyncIdMap[e]||0)+1,this.asyncIdMap[e]}validateAsyncId(e,t){return this.asyncIdMap[e]===t}}const w=new Set(["positionX","positionY","positionZ","rotationX","rotationY","rotationZ","scaleX","scaleY","scaleZ"]);let _=class extends O{constructor(){super(...arguments),this.name="Transform3DSystem"}static{this.systemName="Transform3DSystem"}init(){this.game.getSystem("Renderer3DSystem").rendererManager.register(this)}componentChanged(e){if("Transform"===e.componentName)return this.ensureOn(e.gameObject),e.gameObject.parent&&this.ensureOn(e.gameObject.parent),void this.threeContext.reparentGameObject(e.gameObject);"Transform3D"===e.componentName&&(e.type===t.OBSERVER_TYPE.ADD?this.threeContext.ensureTransformRoot(e.gameObject,e.component):e.type===t.OBSERVER_TYPE.REMOVE?this.threeContext.detachObject3D(e.gameObject.id):w.has(e.prop?.prop?.[0])&&this.threeContext.applyTransform3D(e.gameObject,e.component))}rendererUpdate(e){const t=e.getComponent(D);t&&this.threeContext.applyTransform3D(e,t)}ensureOn(e){if(!e||e===e.scene)return;let t=e.getComponent(D);t||(t=new D,e.addComponent(t)),this.threeContext.ensureTransformRoot(e,t)}};_=e.__decorate([t.decorators.componentObserver({Transform3D:["positionX","positionY","positionZ","rotationX","rotationY","rotationZ","scaleX","scaleY","scaleZ"],Transform:["_parent"]})],_);var R=_;class S extends t.Component{constructor(){super(...arguments),this.visible=!0,this.opacity=1,this.renderOrder=0,this.sortableChildren=!1}static{this.componentName="Render3D"}init(e){e&&Object.assign(this,e)}}e.__decorate([r.Field({type:"boolean",group:"Render3D",label:"visible",description:"Whether this object is drawn.",editor:"toggle"})],S.prototype,"visible",void 0),e.__decorate([r.Field({type:"number",step:.01,min:0,max:1,group:"Render3D",label:"opacity",description:"Opacity from 0 to 1.",editor:"number-slider"})],S.prototype,"opacity",void 0),e.__decorate([r.Field({type:"number",step:1,group:"Render3D",label:"renderOrder",description:"Draw order; higher values render on top.",editor:"number-stepper"})],S.prototype,"renderOrder",void 0),e.__decorate([r.Field({type:"boolean",group:"Render3D",label:"sortableChildren",description:"When on, children are sorted by their render order before drawing.",editor:"toggle"})],S.prototype,"sortableChildren",void 0);let T=class extends O{constructor(){super(...arguments),this.name="Render3DSystem"}static{this.systemName="Render3DSystem"}init(){this.game.getSystem("Renderer3DSystem").rendererManager.register(this)}componentChanged(e){if("Render3D"===e.componentName){if(e.type===t.OBSERVER_TYPE.REMOVE){const t=this.threeContext.object3DFor(e.gameObject.id);return void(t&&this.apply(t,{visible:!0,opacity:1,renderOrder:0,sortableChildren:!1}))}this.applyTo(e.gameObject,e.component)}}rendererUpdate(e){const t=e.getComponent(S);t&&this.applyTo(e,t)}applyTo(e,t){const o=this.threeContext.object3DFor(e.id);o&&(this.apply(o,t),t.sortableChildren&&this.sortChildren(e,o))}apply(e,t){e.visible=t.visible,e.traverse(e=>{e.renderOrder=t.renderOrder;const o=e;if(!o.isMesh||!o.material)return;const r=Array.isArray(o.material)?o.material:[o.material];for(const e of r){const o=e;"number"==typeof o.opacity&&(o.opacity=t.opacity,o.transparent=t.opacity<1)}})}sortChildren(e,t){const o=e.transform?.children?.map(e=>{const o=e.gameObject;if(!o)return null;const r=this.threeContext.object3DFor(o.id);if(!r||r.parent!==t)return null;const s=o.getComponent(S);return{node:r,order:s?.renderOrder??0}}).filter(e=>!!e).sort((e,t)=>e.order-t.order);if(o?.length)for(const e of o)t.add(e.node)}};T=e.__decorate([t.decorators.componentObserver({Render3D:["visible","opacity","renderOrder","sortableChildren"]})],T);var Y=T;class j extends t.Component{constructor(){super(...arguments),this.fov=75,this.near=.1,this.far=1e3,this.active=!0,this.lookAt=!1,this.lookAtX=0,this.lookAtY=0,this.lookAtZ=0}static{this.componentName="Camera3D"}init(e){e&&Object.assign(this,e)}}e.__decorate([r.Field({type:"number",step:1,group:"Camera3D",label:"fov",description:"Vertical field of view in degrees.",editor:"number-stepper"})],j.prototype,"fov",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Camera3D",label:"near",description:"Near clipping plane.",editor:"number-stepper"})],j.prototype,"near",void 0),e.__decorate([r.Field({type:"number",step:1,group:"Camera3D",label:"far",description:"Far clipping plane.",editor:"number-stepper"})],j.prototype,"far",void 0),e.__decorate([r.Field({type:"boolean",group:"Camera3D",label:"active",description:"Use this camera for rendering.",editor:"toggle"})],j.prototype,"active",void 0),e.__decorate([r.Field({type:"boolean",group:"Camera3D",label:"lookAt",description:"Point the camera at lookAtX/Y/Z each frame.",editor:"toggle"})],j.prototype,"lookAt",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Camera3D",label:"lookAtX",description:"World-space look-at target on X.",editor:"number-stepper"})],j.prototype,"lookAtX",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Camera3D",label:"lookAtY",description:"World-space look-at target on Y.",editor:"number-stepper"})],j.prototype,"lookAtY",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Camera3D",label:"lookAtZ",description:"World-space look-at target on Z.",editor:"number-stepper"})],j.prototype,"lookAtZ",void 0);let E=class extends O{constructor(){super(...arguments),this.name="Camera3DSystem",this.cameras=new Map}static{this.systemName="Camera3DSystem"}init(){this.game.getSystem("Renderer3DSystem").rendererManager.register(this)}componentChanged(e){if("Camera3D"!==e.componentName)return;const o=e.component;e.type===t.OBSERVER_TYPE.ADD?this.mount(e.gameObject,o):e.type===t.OBSERVER_TYPE.REMOVE?this.unmount(e.gameObject.id):this.sync(e.gameObject,o)}rendererUpdate(e){const t=e.getComponent(j),o=this.cameras.get(e.id);t&&o&&t.lookAt&&o.lookAt(t.lookAtX,t.lookAtY,t.lookAtZ)}mount(e,t){this.ensureTransform(e);const r=new o.PerspectiveCamera(t.fov,this.threeContext.camera.aspect,t.near,t.far);this.threeContext.attachVisual(e.id,r,e),this.cameras.set(e.id,r),this.sync(e,t)}sync(e,t){const o=this.cameras.get(e.id);o&&(o.fov=t.fov,o.near=t.near,o.far=t.far,o.updateProjectionMatrix(),t.active?this.threeContext.setActiveCamera(o):this.threeContext.camera===o&&this.activateAnother(e.id))}unmount(e){const t=this.cameras.get(e);t&&(this.threeContext.detachVisual(e,t),this.cameras.delete(e),this.threeContext.camera===t&&this.activateAnother(e))}activateAnother(e){for(const[t,o]of this.cameras){if(t===e)continue;const r=this.game.gameObjects.find(e=>e.id===t),s=r?.getComponent(j);if(s?.active)return void this.threeContext.setActiveCamera(o)}this.threeContext.restoreFallbackCamera()}ensureTransform(e){let t=e.getComponent(D);if(!t)return t=new D,t.positionZ=5,void e.addComponent(t);m(t)&&(t.positionZ=5)}onDestroy(){for(const[e]of this.cameras)this.unmount(e);this.cameras.clear()}};E=e.__decorate([t.decorators.componentObserver({Camera3D:["fov","near","far","active","lookAt","lookAtX","lookAtY","lookAtZ"]})],E);var A=E;class M extends t.Component{constructor(){super(...arguments),this.type="directional",this.color=16777215,this.intensity=1,this.castShadow=!1,this.skyColor=16777215,this.groundColor=4473924,this.distance=0,this.decay=2,this.angle=Math.PI/3,this.penumbra=0}static{this.componentName="Light3D"}init(e){e&&Object.assign(this,e)}}e.__decorate([r.Field({type:"string",group:"Light3D",label:"type",description:"Light kind.",editor:"enum",enumOptions:["ambient","directional","hemisphere","point","spot"]})],M.prototype,"type",void 0),e.__decorate([r.Field({type:"number",group:"Light3D",label:"color",description:"Light color (hex).",editor:"number-stepper"})],M.prototype,"color",void 0),e.__decorate([r.Field({type:"number",step:.05,group:"Light3D",label:"intensity",description:"Light intensity.",editor:"number-stepper"})],M.prototype,"intensity",void 0),e.__decorate([r.Field({type:"boolean",group:"Light3D",label:"castShadow",description:"Whether this light casts shadows.",editor:"toggle"})],M.prototype,"castShadow",void 0),e.__decorate([r.Field({type:"number",group:"Light3D",label:"skyColor",description:"Hemisphere sky color (hex).",editor:"number-stepper"})],M.prototype,"skyColor",void 0),e.__decorate([r.Field({type:"number",group:"Light3D",label:"groundColor",description:"Hemisphere ground color (hex).",editor:"number-stepper"})],M.prototype,"groundColor",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Light3D",label:"distance",description:"Range for point and spot lights. 0 means no limit.",editor:"number-stepper"})],M.prototype,"distance",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Light3D",label:"decay",description:"Intensity falloff for point and spot lights.",editor:"number-stepper"})],M.prototype,"decay",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Light3D",label:"angle",description:"Spot light cone angle in radians.",editor:"number-stepper"})],M.prototype,"angle",void 0),e.__decorate([r.Field({type:"number",step:.01,min:0,max:1,group:"Light3D",label:"penumbra",description:"Spot light soft edge (0–1).",editor:"number-slider"})],M.prototype,"penumbra",void 0);let Z=class extends O{constructor(){super(...arguments),this.name="Light3DSystem",this.lights=new Map}static{this.systemName="Light3DSystem"}init(){this.game.getSystem("Renderer3DSystem").rendererManager.register(this)}componentChanged(e){if("Light3D"!==e.componentName)return;const o=e.component;e.type===t.OBSERVER_TYPE.ADD?this.mount(e.gameObject,o):e.type===t.OBSERVER_TYPE.REMOVE?this.unmount(e.gameObject.id):"type"===e.prop?.prop?.[0]?(this.unmount(e.gameObject.id),this.mount(e.gameObject,o)):this.sync(e.gameObject.id,o)}rendererUpdate(e){}mount(e,t){this.ensureTransform(e),0===this.lights.size&&this.threeContext.removeDefaultLights();const o=this.createLight(t);this.threeContext.attachVisual(e.id,o,e),this.lights.set(e.id,o),this.sync(e.id,t)}createLight(e){switch(e.type){case"ambient":return new o.AmbientLight(e.color,e.intensity);case"hemisphere":return new o.HemisphereLight(e.skyColor,e.groundColor,e.intensity);case"point":return new o.PointLight(e.color,e.intensity,e.distance,e.decay);case"spot":return new o.SpotLight(e.color,e.intensity,e.distance,e.angle,e.penumbra,e.decay);default:return new o.DirectionalLight(e.color,e.intensity)}}sync(e,t){const r=this.lights.get(e);r&&("color"in r&&r.color&&r.color.set(t.color),r.intensity=t.intensity,r instanceof o.HemisphereLight&&(r.color.set(t.skyColor),r.groundColor.set(t.groundColor)),(r instanceof o.PointLight||r instanceof o.SpotLight)&&(r.distance=t.distance,r.decay=t.decay),r instanceof o.SpotLight&&(r.angle=t.angle,r.penumbra=t.penumbra),"castShadow"in r&&(r.castShadow=!(!t.castShadow||!this.threeContext.shadows)))}unmount(e){const t=this.lights.get(e);t&&(this.threeContext.detachVisual(e,t),t.dispose?.(),this.lights.delete(e))}ensureTransform(e){e.getComponent(D)||e.addComponent(new D)}onDestroy(){for(const[e]of this.lights)this.unmount(e);this.lights.clear()}};Z=e.__decorate([t.decorators.componentObserver({Light3D:["type","color","intensity","castShadow","skyColor","groundColor","distance","decay","angle","penumbra"]})],Z);var k=Z;async function X(e){const o=String(e??"").trim();if(!o)throw new Error("resource name is required; register it with resource.addResource");const r=await t.resource.getResource(o);if(!r||!r.name)throw new Error(`Unknown resource "${o}"; register it with resource.addResource first`);return r}function L(e){const t=e.data?.image;if(!t)throw new Error(`Resource "${e.name}" has no image data; use RESOURCE_TYPE.IMAGE with src.image.url`);const r=new o.Texture(t);return r.colorSpace=o.SRGBColorSpace,r.needsUpdate=!0,r}exports.COMBOS_GAME_OBJECT_ID=s,exports.COMBOS_TRANSFORM3D=n,exports.Camera3D=j,exports.Camera3DSystem=A,exports.Light3D=M,exports.Light3DSystem=k,exports.Render3D=S,exports.Render3DSystem=Y,exports.Renderer3D=O,exports.Renderer3DManager=C,exports.Renderer3DSystem=x,exports.ThreeContext=b,exports.Transform3D=D,exports.Transform3DSystem=R,exports.VisualPoseBridge=class{constructor(){this.lastVisual="",this.lastRoot=""}sync(e,t){if(!t)return!0;if(""===this.lastVisual&&""===this.lastRoot)return u(e,t),this.lastVisual=h(e),this.lastRoot=h(t),!1;const o=h(e),r=h(t);return o!==this.lastVisual&&r===this.lastRoot&&l(e,t),this.lastVisual=h(e),this.lastRoot=h(t),!1}},exports.copyPose=l,exports.gameObjectIdFromIntersection=function(e){return c(e?.object)},exports.gameObjectIdFromObject3D=c,exports.has3DChildGameObjects=function(e){return(e?.transform?.children?.length??0)>0},exports.is3DSceneParent=p,exports.isIdentityPose=m,exports.isTransform3DRoot=i,exports.poseKeyOf=h,exports.readPose=d,exports.requireNamedResource=X,exports.seedTransform3D=u,exports.tagObject3D=a,exports.textureFromNamedImage=async function(e){return L(await X(e))},exports.textureFromResourceImage=L;
1
+ "use strict";var e=require("tslib"),t=require("@combos-fun/engine"),o=require("three"),r=require("@combos-fun/inspector-decorator");const s="combosGameObjectId",n="combosTransform3D";function i(e){return!!e?.userData?.[n]}function a(e,t){e.traverse(e=>{e.userData[s]=t})}function c(e){let t=e;for(;t;){const e=t.userData?.[s];if("number"==typeof e)return e;t=t.parent}}function p(e){if(!e)return!0;const t=e.parent;return!t||t===e.scene}function d(e){return{positionX:e.positionX??0,positionY:e.positionY??0,positionZ:e.positionZ??0,rotationX:e.rotationX??0,rotationY:e.rotationY??0,rotationZ:e.rotationZ??0,scaleX:e.scaleX??1,scaleY:e.scaleY??1,scaleZ:e.scaleZ??1}}function h(e){const t=d(e);return[t.positionX,t.positionY,t.positionZ,t.rotationX,t.rotationY,t.rotationZ,t.scaleX,t.scaleY,t.scaleZ].join(",")}function l(e,t){const o=d(e);t.positionX=o.positionX,t.positionY=o.positionY,t.positionZ=o.positionZ,t.rotationX=o.rotationX,t.rotationY=o.rotationY,t.rotationZ=o.rotationZ,t.scaleX=o.scaleX,t.scaleY=o.scaleY,t.scaleZ=o.scaleZ}function m(e){const t=d(e);return 0===t.positionX&&0===t.positionY&&0===t.positionZ&&0===t.rotationX&&0===t.rotationY&&0===t.rotationZ&&1===t.scaleX&&1===t.scaleY&&1===t.scaleZ}function u(e,t){m(t)&&!m(e)&&l(e,t)}const g={none:o.NoToneMapping,aces:o.ACESFilmicToneMapping,linear:o.LinearToneMapping,reinhard:o.ReinhardToneMapping,cineon:o.CineonToneMapping},y=new o.Vector3,b=new o.Euler;class f{constructor(e){this.mixers=new Map,this.models=new Map,this.nodes=new Map,this.defaultLights=[];const{canvas:t,container:r,width:s,height:n,antialias:i=!0,backgroundColor:a=0,backgroundAlpha:c=1}=e;this.scene=new o.Scene,this.shadows=!!e.shadows,this.camera=new o.PerspectiveCamera(75,s/n,.1,1e3),this.camera.position.z=5,this.fallbackCamera=this.camera;const p={antialias:i};t&&(p.canvas=t),c<1&&(p.alpha=!0),this.renderer=new o.WebGLRenderer(p),this.renderer.setSize(s,n),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setClearColor(a,c),this.renderer.toneMapping=g[e.toneMapping??"aces"]??o.ACESFilmicToneMapping,this.renderer.toneMappingExposure=e.toneMappingExposure??1,this.shadows&&(this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=o.PCFSoftShadowMap),!t&&r&&r.appendChild(this.renderer.domElement);const d=new o.AmbientLight(16777215,e.ambientIntensity??.6);this.scene.add(d),this.defaultLights.push(d);const h=new o.DirectionalLight(16777215,e.directionalIntensity??.8);if(h.position.set(5,10,7.5),this.shadows&&(h.castShadow=!0,h.shadow.mapSize.set(1024,1024)),this.scene.add(h),this.defaultLights.push(h),!1!==e.hemisphereLight){const t="object"==typeof e.hemisphereLight?e.hemisphereLight:{},r=new o.HemisphereLight(t.skyColor??16777215,t.groundColor??4473924,t.intensity??.35);this.scene.add(r),this.defaultLights.push(r)}if(e.fog){const t="object"==typeof e.fog?e.fog:{};this.scene.fog=new o.Fog(t.color??a,t.near??8,t.far??40)}this.clock=new o.Clock}update(){const e=this.clock.getDelta();for(const t of this.mixers.values())t.update(e);this.renderer.render(this.scene,this.camera)}hasTransform3DRoot(e){return i(this.nodes.get(e))}applyModelShadows(e){this.shadows&&e.traverse(e=>{const t=e;t.isMesh&&(t.castShadow=!0,t.receiveShadow=!0)})}attachParsedModel(e,t,r,s){if(a(t,e),this.applyModelShadows(t),this.models.set(e,t),this.attachVisual(e,t,s),r&&r.length>0){const s=new o.AnimationMixer(t);this.mixers.set(e,s),t.userData.animations=r}return t}object3DFor(e){return this.nodes.get(e)}attachObject3D(e,t,o){const r=this.nodes.get(e);r&&r!==t&&(this.rehomeRegisteredChildren(r),r.parent?.remove(r)),this.nodes.set(e,t);const s=this.findParentNode(o);t.parent!==s&&s.add(t),o&&this.adoptChildGameObjects(o,t)}attachVisual(e,t,o){a(t,e);const r=this.nodes.get(e);i(r)&&r!==t?t.parent!==r&&r.add(t):this.attachObject3D(e,t,o)}detachVisual(e,t){const o=this.nodes.get(e);return i(o)&&o!==t?(t.parent?.remove(t),t):o===t?this.detachObject3D(e):(t.parent?.remove(t),t)}detachObject3D(e){const t=this.nodes.get(e);if(t)return this.rehomeRegisteredChildren(t),t.parent?.remove(t),this.nodes.delete(e),t}reparentGameObject(e){const t=this.nodes.get(e.id);if(!t)return;const o=this.findParentNode(e);t.parent!==o&&o.add(t)}findParentNode(e){if(!e||p(e))return this.scene;let t=e.parent;for(;t&&t!==e.scene;){const e=this.nodes.get(t.id);if(e)return e;t=t.parent}return this.scene}adoptChildGameObjects(e,t){const o=e.children;if(o)for(const e of o){if(!e)continue;const o=this.nodes.get(e.id);o&&o.parent!==t&&t.add(o)}}ensureTransformRoot(e,t){const r=this.nodes.get(e.id);if(i(r))return this.applyTransformPose(r,t),r;const s=new o.Group;if(s.name=e.name,s.userData[n]=!0,a(s,e.id),r&&r!==s){(function(e){const t=d(e);return 0===t.positionX&&0===t.positionY&&0===t.positionZ&&0===t.rotationX&&0===t.rotationY&&0===t.rotationZ&&1===t.scaleX&&1===t.scaleY&&1===t.scaleZ})(t)&&(t.positionX=r.position.x,t.positionY=r.position.y,t.positionZ=r.position.z,t.rotationX=r.rotation.x,t.rotationY=r.rotation.y,t.rotationZ=r.rotation.z,t.scaleX=r.scale.x,t.scaleY=r.scale.y,t.scaleZ=r.scale.z);(r.parent||this.scene).add(s),s.add(r),r.position.set(0,0,0),r.rotation.set(0,0,0),r.scale.set(1,1,1),this.nodes.set(e.id,s),this.adoptChildGameObjects(e,s)}else this.attachObject3D(e.id,s,e);return this.applyTransformPose(s,t),s}applyTransform3D(e,t){const o=this.ensureTransformRoot(e,t);return this.applyTransformPose(o,t),o.updateWorldMatrix(!0,!1),o.getWorldPosition(y),t.worldPositionX=y.x,t.worldPositionY=y.y,t.worldPositionZ=y.z,b.setFromRotationMatrix(o.matrixWorld),t.worldRotationX=b.x,t.worldRotationY=b.y,t.worldRotationZ=b.z,o}applyTransformPose(e,t){const o=d(t);e.position.set(o.positionX,o.positionY,o.positionZ),e.rotation.set(o.rotationX,o.rotationY,o.rotationZ),e.scale.set(o.scaleX,o.scaleY,o.scaleZ)}removeDefaultLights(){if(this.defaultLights.length){for(const e of this.defaultLights)e.parent?.remove(e),e.dispose?.();this.defaultLights=[]}}setActiveCamera(e){const t=this.camera;this.camera=e,t&&(e.aspect=t.aspect),e.updateProjectionMatrix()}restoreFallbackCamera(){this.camera!==this.fallbackCamera&&this.setActiveCamera(this.fallbackCamera)}rehomeRegisteredChildren(e){for(const t of[...e.children]){const e=t.userData?.[s];"number"==typeof e&&this.nodes.get(e)===t&&this.scene.add(t)}}playAnimation(e,t,o){const r=this.mixers.get(e),s=this.models.get(e);if(!r||!s)return;r.stopAllAction();const n=s.userData.animations;if(n&&n[t]){const e=r.clipAction(n[t]);e.timeScale=o,e.play()}}stopAnimation(e){const t=this.mixers.get(e);t&&t.stopAllAction()}removeModel(e){const t=this.models.get(e);t&&(this.detachVisual(e,t),t.traverse(e=>{const t=e;if(t.geometry&&t.geometry.dispose(),t.material){(Array.isArray(t.material)?t.material:[t.material]).forEach(e=>e.dispose())}}),this.models.delete(e));const o=this.mixers.get(e);o&&(o.stopAllAction(),this.mixers.delete(e))}resize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.fallbackCamera!==this.camera&&(this.fallbackCamera.aspect=e/t,this.fallbackCamera.updateProjectionMatrix()),this.renderer.setSize(e,t)}destroy(){for(const e of this.models.keys())this.removeModel(e);this.removeDefaultLights(),this.renderer.dispose(),this.renderer.domElement.remove(),this.nodes.clear(),this.scene=null,this.camera=null,this.fallbackCamera=null,this.renderer=null,this.clock=null}}class C{constructor({game:e,rendererSystem:t}){this.renderers=[],this.game=e,this.rendererSystem=t}register(...e){for(const t of e)t.game=this.game,t.rendererManager=this,t.threeContext=this.rendererSystem.threeContext,this.renderers.push(t)}componentChanged(e){for(const o of e)for(const e of this.renderers){const r=e.observerInfo[o.componentName];if(!r)continue;if(o.type===t.OBSERVER_TYPE.ADD||o.type===t.OBSERVER_TYPE.REMOVE){try{e.componentChanged(o)}catch(e){console.error(`gameObject: ${o.gameObject.name}, ${o.componentName} error.`,o,e)}continue}if(r.findIndex(e=>"string"==typeof e&&"string"==typeof o.prop?e===o.prop:JSON.stringify(e)===JSON.stringify(o.prop))>-1)try{e.componentChanged(o)}catch(e){console.error(`gameObject: ${o.gameObject?.name}, ${o.componentName} componentChanged error.`,o,e)}}}update(e){for(const t of e.components)for(const o of this.renderers){if(o.observerInfo[t.name])try{o.rendererUpdate(e)}catch(o){console.info(`gameObject: ${e.name}, ${t.name} update error`,o)}}}}class D extends t.Component{constructor(){super(...arguments),this.positionX=0,this.positionY=0,this.positionZ=0,this.rotationX=0,this.rotationY=0,this.rotationZ=0,this.scaleX=1,this.scaleY=1,this.scaleZ=1,this.worldPositionX=0,this.worldPositionY=0,this.worldPositionZ=0,this.worldRotationX=0,this.worldRotationY=0,this.worldRotationZ=0}static{this.componentName="Transform3D"}init(e){e&&Object.assign(this,e)}}e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"positionX",description:"Local X position.",editor:"number-stepper"})],D.prototype,"positionX",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"positionY",description:"Local Y position.",editor:"number-stepper"})],D.prototype,"positionY",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"positionZ",description:"Local Z position.",editor:"number-stepper"})],D.prototype,"positionZ",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Transform3D",label:"rotationX",description:"Rotation around X in radians.",editor:"number-stepper"})],D.prototype,"rotationX",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Transform3D",label:"rotationY",description:"Rotation around Y in radians.",editor:"number-stepper"})],D.prototype,"rotationY",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Transform3D",label:"rotationZ",description:"Rotation around Z in radians.",editor:"number-stepper"})],D.prototype,"rotationZ",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"scaleX",description:"Scale on X.",editor:"number-stepper"})],D.prototype,"scaleX",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"scaleY",description:"Scale on Y.",editor:"number-stepper"})],D.prototype,"scaleY",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Transform3D",label:"scaleZ",description:"Scale on Z.",editor:"number-stepper"})],D.prototype,"scaleZ",void 0);let v=class extends t.System{constructor(){super(...arguments),this.name="Renderer3DSystem"}static{this.systemName="Renderer3DSystem"}init(e){const t=e||{},o=t.width||750,r=t.height||1334;this.threeContext=new f({canvas:t.canvas,container:t.container,width:o,height:r,antialias:t.antialias,backgroundColor:t.backgroundColor,backgroundAlpha:t.backgroundAlpha,fog:t.fog,hemisphereLight:t.hemisphereLight,shadows:t.shadows,toneMapping:t.toneMapping,toneMappingExposure:t.toneMappingExposure,ambientIntensity:t.ambientIntensity,directionalIntensity:t.directionalIntensity}),this.game.canvas=this.threeContext.renderer.domElement,this.rendererManager=new C({game:this.game,rendererSystem:this})}update(e){const t=this.componentObserver.clear();for(const e of t)this.handleHierarchyChange(e);for(const e of this.game.gameObjects){const t=e.getComponent(D);t&&this.threeContext.applyTransform3D(e,t),this.rendererManager.update(e)}}handleHierarchyChange(e){"GameObject"===e.componentName&&(e.type!==t.OBSERVER_TYPE.CHANGE&&e.type!==t.OBSERVER_TYPE.ADD||(this.ensureTransform3D(e.gameObject),e.gameObject.parent&&this.ensureTransform3D(e.gameObject.parent),this.threeContext?.reparentGameObject(e.gameObject)))}ensureTransform3D(e){if(!e||e===e.scene)return;let t=e.getComponent(D);t||(t=new D,e.addComponent(t)),this.threeContext?.ensureTransformRoot(e,t)}lateUpdate(){this.threeContext?.update()}resize(e,t){this.threeContext?.resize(e,t)}onDestroy(){this.threeContext?.destroy(),this.threeContext=null}};v=e.__decorate([t.decorators.componentObserver({GameObject:["parent"]})],v);var x=v;Object.assign(x,{packageName:"@combos-fun/plugin-renderer-3d",packageVersion:"0.2.0"});class O extends t.System{constructor(e){super(e),this.asyncIdMap={};const t=this.constructor;this.observerInfo=t.observerInfo}componentChanged(e){}rendererUpdate(e){}update(e){const t=this.componentObserver.clear();for(const e of t)this.componentChanged(e)}increaseAsyncId(e){return this.asyncIdMap[e]=(this.asyncIdMap[e]||0)+1,this.asyncIdMap[e]}validateAsyncId(e,t){return this.asyncIdMap[e]===t}}const w=new Set(["positionX","positionY","positionZ","rotationX","rotationY","rotationZ","scaleX","scaleY","scaleZ"]);let R=class extends O{constructor(){super(...arguments),this.name="Transform3DSystem"}static{this.systemName="Transform3DSystem"}init(){this.game.getSystem("Renderer3DSystem").rendererManager.register(this)}componentChanged(e){if("GameObject"===e.componentName)return this.ensureOn(e.gameObject),e.gameObject.parent&&this.ensureOn(e.gameObject.parent),void this.threeContext.reparentGameObject(e.gameObject);"Transform3D"===e.componentName&&(e.type===t.OBSERVER_TYPE.ADD?this.threeContext.ensureTransformRoot(e.gameObject,e.component):e.type===t.OBSERVER_TYPE.REMOVE?this.threeContext.detachObject3D(e.gameObject.id):w.has(e.prop?.prop?.[0])&&this.threeContext.applyTransform3D(e.gameObject,e.component))}rendererUpdate(e){const t=e.getComponent(D);t&&this.threeContext.applyTransform3D(e,t)}ensureOn(e){if(!e||e===e.scene)return;let t=e.getComponent(D);t||(t=new D,e.addComponent(t)),this.threeContext.ensureTransformRoot(e,t)}};R=e.__decorate([t.decorators.componentObserver({Transform3D:["positionX","positionY","positionZ","rotationX","rotationY","rotationZ","scaleX","scaleY","scaleZ"],GameObject:["parent"]})],R);var _=R;class S extends t.Component{constructor(){super(...arguments),this.visible=!0,this.opacity=1,this.renderOrder=0,this.sortableChildren=!1}static{this.componentName="Render3D"}init(e){e&&Object.assign(this,e)}}e.__decorate([r.Field({type:"boolean",group:"Render3D",label:"visible",description:"Whether this object is drawn.",editor:"toggle"})],S.prototype,"visible",void 0),e.__decorate([r.Field({type:"number",step:.01,min:0,max:1,group:"Render3D",label:"opacity",description:"Opacity from 0 to 1.",editor:"number-slider"})],S.prototype,"opacity",void 0),e.__decorate([r.Field({type:"number",step:1,group:"Render3D",label:"renderOrder",description:"Draw order; higher values render on top.",editor:"number-stepper"})],S.prototype,"renderOrder",void 0),e.__decorate([r.Field({type:"boolean",group:"Render3D",label:"sortableChildren",description:"When on, children are sorted by their render order before drawing.",editor:"toggle"})],S.prototype,"sortableChildren",void 0);let j=class extends O{constructor(){super(...arguments),this.name="Render3DSystem"}static{this.systemName="Render3DSystem"}init(){this.game.getSystem("Renderer3DSystem").rendererManager.register(this)}componentChanged(e){if("Render3D"===e.componentName){if(e.type===t.OBSERVER_TYPE.REMOVE){const t=this.threeContext.object3DFor(e.gameObject.id);return void(t&&this.apply(t,{visible:!0,opacity:1,renderOrder:0,sortableChildren:!1}))}this.applyTo(e.gameObject,e.component)}}rendererUpdate(e){const t=e.getComponent(S);t&&this.applyTo(e,t)}applyTo(e,t){const o=this.threeContext.object3DFor(e.id);o&&(this.apply(o,t),t.sortableChildren&&this.sortChildren(e,o))}apply(e,t){e.visible=t.visible,e.traverse(e=>{e.renderOrder=t.renderOrder;const o=e;if(!o.isMesh||!o.material)return;const r=Array.isArray(o.material)?o.material:[o.material];for(const e of r){const o=e;"number"==typeof o.opacity&&(o.opacity=t.opacity,o.transparent=t.opacity<1)}})}sortChildren(e,t){const o=e.children?.map(e=>{if(!e)return null;const o=this.threeContext.object3DFor(e.id);if(!o||o.parent!==t)return null;const r=e.getComponent(S);return{node:o,order:r?.renderOrder??0}}).filter(e=>!!e).sort((e,t)=>e.order-t.order);if(o?.length)for(const e of o)t.add(e.node)}};j=e.__decorate([t.decorators.componentObserver({Render3D:["visible","opacity","renderOrder","sortableChildren"]})],j);var Y=j;class T extends t.Component{constructor(){super(...arguments),this.fov=75,this.near=.1,this.far=1e3,this.active=!0,this.lookAt=!1,this.lookAtX=0,this.lookAtY=0,this.lookAtZ=0}static{this.componentName="Camera3D"}init(e){e&&Object.assign(this,e)}}e.__decorate([r.Field({type:"number",step:1,group:"Camera3D",label:"fov",description:"Vertical field of view in degrees.",editor:"number-stepper"})],T.prototype,"fov",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Camera3D",label:"near",description:"Near clipping plane.",editor:"number-stepper"})],T.prototype,"near",void 0),e.__decorate([r.Field({type:"number",step:1,group:"Camera3D",label:"far",description:"Far clipping plane.",editor:"number-stepper"})],T.prototype,"far",void 0),e.__decorate([r.Field({type:"boolean",group:"Camera3D",label:"active",description:"Use this camera for rendering.",editor:"toggle"})],T.prototype,"active",void 0),e.__decorate([r.Field({type:"boolean",group:"Camera3D",label:"lookAt",description:"Point the camera at lookAtX/Y/Z each frame.",editor:"toggle"})],T.prototype,"lookAt",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Camera3D",label:"lookAtX",description:"World-space look-at target on X.",editor:"number-stepper"})],T.prototype,"lookAtX",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Camera3D",label:"lookAtY",description:"World-space look-at target on Y.",editor:"number-stepper"})],T.prototype,"lookAtY",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Camera3D",label:"lookAtZ",description:"World-space look-at target on Z.",editor:"number-stepper"})],T.prototype,"lookAtZ",void 0);let E=class extends O{constructor(){super(...arguments),this.name="Camera3DSystem",this.cameras=new Map}static{this.systemName="Camera3DSystem"}init(){this.game.getSystem("Renderer3DSystem").rendererManager.register(this)}componentChanged(e){if("Camera3D"!==e.componentName)return;const o=e.component;e.type===t.OBSERVER_TYPE.ADD?this.mount(e.gameObject,o):e.type===t.OBSERVER_TYPE.REMOVE?this.unmount(e.gameObject.id):this.sync(e.gameObject,o)}rendererUpdate(e){const t=e.getComponent(T),o=this.cameras.get(e.id);t&&o&&t.lookAt&&o.lookAt(t.lookAtX,t.lookAtY,t.lookAtZ)}mount(e,t){this.ensureTransform(e);const r=new o.PerspectiveCamera(t.fov,this.threeContext.camera.aspect,t.near,t.far);this.threeContext.attachVisual(e.id,r,e),this.cameras.set(e.id,r),this.sync(e,t)}sync(e,t){const o=this.cameras.get(e.id);o&&(o.fov=t.fov,o.near=t.near,o.far=t.far,o.updateProjectionMatrix(),t.active?this.threeContext.setActiveCamera(o):this.threeContext.camera===o&&this.activateAnother(e.id))}unmount(e){const t=this.cameras.get(e);t&&(this.threeContext.detachVisual(e,t),this.cameras.delete(e),this.threeContext.camera===t&&this.activateAnother(e))}activateAnother(e){for(const[t,o]of this.cameras){if(t===e)continue;const r=this.game.gameObjects.find(e=>e.id===t),s=r?.getComponent(T);if(s?.active)return void this.threeContext.setActiveCamera(o)}this.threeContext.restoreFallbackCamera()}ensureTransform(e){let t=e.getComponent(D);if(!t)return t=new D,t.positionZ=5,void e.addComponent(t);m(t)&&(t.positionZ=5)}onDestroy(){for(const[e]of this.cameras)this.unmount(e);this.cameras.clear()}};E=e.__decorate([t.decorators.componentObserver({Camera3D:["fov","near","far","active","lookAt","lookAtX","lookAtY","lookAtZ"]})],E);var A=E;class M extends t.Component{constructor(){super(...arguments),this.type="directional",this.color=16777215,this.intensity=1,this.castShadow=!1,this.skyColor=16777215,this.groundColor=4473924,this.distance=0,this.decay=2,this.angle=Math.PI/3,this.penumbra=0}static{this.componentName="Light3D"}init(e){e&&Object.assign(this,e)}}e.__decorate([r.Field({type:"string",group:"Light3D",label:"type",description:"Light kind.",editor:"enum",enumOptions:["ambient","directional","hemisphere","point","spot"]})],M.prototype,"type",void 0),e.__decorate([r.Field({type:"number",group:"Light3D",label:"color",description:"Light color (hex).",editor:"number-stepper"})],M.prototype,"color",void 0),e.__decorate([r.Field({type:"number",step:.05,group:"Light3D",label:"intensity",description:"Light intensity.",editor:"number-stepper"})],M.prototype,"intensity",void 0),e.__decorate([r.Field({type:"boolean",group:"Light3D",label:"castShadow",description:"Whether this light casts shadows.",editor:"toggle"})],M.prototype,"castShadow",void 0),e.__decorate([r.Field({type:"number",group:"Light3D",label:"skyColor",description:"Hemisphere sky color (hex).",editor:"number-stepper"})],M.prototype,"skyColor",void 0),e.__decorate([r.Field({type:"number",group:"Light3D",label:"groundColor",description:"Hemisphere ground color (hex).",editor:"number-stepper"})],M.prototype,"groundColor",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Light3D",label:"distance",description:"Range for point and spot lights. 0 means no limit.",editor:"number-stepper"})],M.prototype,"distance",void 0),e.__decorate([r.Field({type:"number",step:.1,group:"Light3D",label:"decay",description:"Intensity falloff for point and spot lights.",editor:"number-stepper"})],M.prototype,"decay",void 0),e.__decorate([r.Field({type:"number",step:.01,group:"Light3D",label:"angle",description:"Spot light cone angle in radians.",editor:"number-stepper"})],M.prototype,"angle",void 0),e.__decorate([r.Field({type:"number",step:.01,min:0,max:1,group:"Light3D",label:"penumbra",description:"Spot light soft edge (0–1).",editor:"number-slider"})],M.prototype,"penumbra",void 0);let Z=class extends O{constructor(){super(...arguments),this.name="Light3DSystem",this.lights=new Map}static{this.systemName="Light3DSystem"}init(){this.game.getSystem("Renderer3DSystem").rendererManager.register(this)}componentChanged(e){if("Light3D"!==e.componentName)return;const o=e.component;e.type===t.OBSERVER_TYPE.ADD?this.mount(e.gameObject,o):e.type===t.OBSERVER_TYPE.REMOVE?this.unmount(e.gameObject.id):"type"===e.prop?.prop?.[0]?(this.unmount(e.gameObject.id),this.mount(e.gameObject,o)):this.sync(e.gameObject.id,o)}rendererUpdate(e){}mount(e,t){this.ensureTransform(e),0===this.lights.size&&this.threeContext.removeDefaultLights();const o=this.createLight(t);this.threeContext.attachVisual(e.id,o,e),this.lights.set(e.id,o),this.sync(e.id,t)}createLight(e){switch(e.type){case"ambient":return new o.AmbientLight(e.color,e.intensity);case"hemisphere":return new o.HemisphereLight(e.skyColor,e.groundColor,e.intensity);case"point":return new o.PointLight(e.color,e.intensity,e.distance,e.decay);case"spot":return new o.SpotLight(e.color,e.intensity,e.distance,e.angle,e.penumbra,e.decay);default:return new o.DirectionalLight(e.color,e.intensity)}}sync(e,t){const r=this.lights.get(e);r&&("color"in r&&r.color&&r.color.set(t.color),r.intensity=t.intensity,r instanceof o.HemisphereLight&&(r.color.set(t.skyColor),r.groundColor.set(t.groundColor)),(r instanceof o.PointLight||r instanceof o.SpotLight)&&(r.distance=t.distance,r.decay=t.decay),r instanceof o.SpotLight&&(r.angle=t.angle,r.penumbra=t.penumbra),"castShadow"in r&&(r.castShadow=!(!t.castShadow||!this.threeContext.shadows)))}unmount(e){const t=this.lights.get(e);t&&(this.threeContext.detachVisual(e,t),t.dispose?.(),this.lights.delete(e))}ensureTransform(e){e.getComponent(D)||e.addComponent(new D)}onDestroy(){for(const[e]of this.lights)this.unmount(e);this.lights.clear()}};Z=e.__decorate([t.decorators.componentObserver({Light3D:["type","color","intensity","castShadow","skyColor","groundColor","distance","decay","angle","penumbra"]})],Z);var k=Z;async function X(e){const o=String(e??"").trim();if(!o)throw new Error("resource name is required; register it with resource.addResource");const r=await t.resource.getResource(o);if(!r||!r.name)throw new Error(`Unknown resource "${o}"; register it with resource.addResource first`);return r}function L(e){const t=e.data?.image;if(!t)throw new Error(`Resource "${e.name}" has no image data; use RESOURCE_TYPE.IMAGE with src.image.url`);const r=new o.Texture(t);return r.colorSpace=o.SRGBColorSpace,r.needsUpdate=!0,r}exports.COMBOS_GAME_OBJECT_ID=s,exports.COMBOS_TRANSFORM3D=n,exports.Camera3D=T,exports.Camera3DSystem=A,exports.Light3D=M,exports.Light3DSystem=k,exports.Render3D=S,exports.Render3DSystem=Y,exports.Renderer3D=O,exports.Renderer3DManager=C,exports.Renderer3DSystem=x,exports.ThreeContext=f,exports.Transform3D=D,exports.Transform3DSystem=_,exports.VisualPoseBridge=class{constructor(){this.lastVisual="",this.lastRoot=""}sync(e,t){if(!t)return!0;if(""===this.lastVisual&&""===this.lastRoot)return u(e,t),this.lastVisual=h(e),this.lastRoot=h(t),!1;const o=h(e),r=h(t);return o!==this.lastVisual&&r===this.lastRoot&&l(e,t),this.lastVisual=h(e),this.lastRoot=h(t),!1}},exports.copyPose=l,exports.gameObjectIdFromIntersection=function(e){return c(e?.object)},exports.gameObjectIdFromObject3D=c,exports.has3DChildGameObjects=function(e){return(e?.children?.length??0)>0},exports.is3DSceneParent=p,exports.isIdentityPose=m,exports.isTransform3DRoot=i,exports.poseKeyOf=h,exports.readPose=d,exports.requireNamedResource=X,exports.seedTransform3D=u,exports.tagObject3D=a,exports.textureFromNamedImage=async function(e){return L(await X(e))},exports.textureFromResourceImage=L;
@@ -38,7 +38,7 @@ function is3DSceneParent(gameObject) {
38
38
  return !parent || parent === gameObject.scene;
39
39
  }
40
40
  function has3DChildGameObjects(gameObject) {
41
- return (gameObject?.transform?.children?.length ?? 0) > 0;
41
+ return (gameObject?.children?.length ?? 0) > 0;
42
42
  }
43
43
 
44
44
  function readPose(pose) {
@@ -292,11 +292,10 @@ class ThreeContext {
292
292
  return this.scene;
293
293
  }
294
294
  adoptChildGameObjects(gameObject, object) {
295
- const children = gameObject.transform?.children;
295
+ const children = gameObject.children;
296
296
  if (!children)
297
297
  return;
298
- for (const childTransform of children) {
299
- const childGo = childTransform.gameObject;
298
+ for (const childGo of children) {
300
299
  if (!childGo)
301
300
  continue;
302
301
  const childNode = this.nodes.get(childGo.id);
@@ -692,7 +691,7 @@ let Renderer3DSystem = class Renderer3DSystem extends System {
692
691
  }
693
692
  }
694
693
  handleHierarchyChange(changed) {
695
- if (changed.componentName !== 'Transform')
694
+ if (changed.componentName !== 'GameObject')
696
695
  return;
697
696
  if (changed.type !== OBSERVER_TYPE.CHANGE && changed.type !== OBSERVER_TYPE.ADD)
698
697
  return;
@@ -724,7 +723,7 @@ let Renderer3DSystem = class Renderer3DSystem extends System {
724
723
  };
725
724
  Renderer3DSystem = __decorate([
726
725
  decorators.componentObserver({
727
- Transform: ['_parent'],
726
+ GameObject: ['parent'],
728
727
  })
729
728
  ], Renderer3DSystem);
730
729
  var Renderer3DSystem$1 = Renderer3DSystem;
@@ -732,7 +731,7 @@ var Renderer3DSystem$1 = Renderer3DSystem;
732
731
  /** Auto-generated by scripts/build-package.mjs — do not edit. */
733
732
  Object.assign(Renderer3DSystem$1, {
734
733
  packageName: "@combos-fun/plugin-renderer-3d",
735
- packageVersion: "0.0.54",
734
+ packageVersion: "0.2.0",
736
735
  });
737
736
 
738
737
  class Renderer3D extends System {
@@ -775,7 +774,7 @@ let Transform3DSystem = class Transform3DSystem extends Renderer3D {
775
774
  renderer3DSystem.rendererManager.register(this);
776
775
  }
777
776
  componentChanged(changed) {
778
- if (changed.componentName === 'Transform') {
777
+ if (changed.componentName === 'GameObject') {
779
778
  this.ensureOn(changed.gameObject);
780
779
  if (changed.gameObject.parent)
781
780
  this.ensureOn(changed.gameObject.parent);
@@ -818,7 +817,7 @@ Transform3DSystem = __decorate([
818
817
  'rotationX', 'rotationY', 'rotationZ',
819
818
  'scaleX', 'scaleY', 'scaleZ',
820
819
  ],
821
- Transform: ['_parent'],
820
+ GameObject: ['parent'],
822
821
  })
823
822
  ], Transform3DSystem);
824
823
  var Transform3DSystem_default = Transform3DSystem;
@@ -932,9 +931,8 @@ let Render3DSystem = class Render3DSystem extends Renderer3D {
932
931
  });
933
932
  }
934
933
  sortChildren(gameObject, root) {
935
- const ranked = gameObject.transform?.children
936
- ?.map((childTransform) => {
937
- const childGo = childTransform.gameObject;
934
+ const ranked = gameObject.children
935
+ ?.map((childGo) => {
938
936
  if (!childGo)
939
937
  return null;
940
938
  const node = this.threeContext.object3DFor(childGo.id);