@combos-fun/plugin-development-tool 0.0.19 → 0.0.20

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"),n=require("@combos-fun/plugin-renderer"),o=require("@combos-fun/plugin-renderer-graphics"),s=require("@combos-fun/plugin-renderer-event");const i="combos-development-tool:set",r="combos-development-tool:refresh",a="combos-development-tool:gameobject-selected",c="combos-development-tool:apply-property";class h extends t.Component{constructor(){super(...arguments),this.payload={}}static{this.componentName="CombosDevelopmentToolTarget"}init(e){this.payload=e?.payload?{...e.payload}:{}}}const l=new Set(["gameObject","name","started","__componentDefaultParams","destroyed","inScene","worldTransform","children","_parent"]),d={Graphics:new Set(["graphics"]),Physics:new Set(["body","Body","PhysicsEngine","World","Constraint","mouseConstraint","bodyParams"]),Event:new Set(["hitArea"])};function p(e,t=0){if(null==e)return e;if("number"==typeof e||"string"==typeof e||"boolean"==typeof e)return e;if(!(t>6)){if(Array.isArray(e))return e.map(e=>p(e,t+1));if("object"==typeof e){const n={};for(const[o,s]of Object.entries(e)){if("function"==typeof s)continue;const e=p(s,t+1);void 0!==e&&(n[o]=e)}return n}}}function u(e){const t={},n=d[e.name];for(const o of Object.keys(e)){if(l.has(o)||o.startsWith("_"))continue;if(n?.has(o))continue;const s=e[o];if("function"==typeof s)continue;const i=p(s);void 0!==i&&(t[o]=i)}return t}function f(e){const t=e.getComponent(h),n=t?.payload?.source;var o;if((o=n)&&"object"==typeof o&&"string"==typeof o.file)return{file:n.file,anchor:n.anchor??e.name}}function m(e){const t=e.components.filter(e=>"CombosDevelopmentToolTarget"!==e.name).map(e=>({componentName:e.name,fields:u(e)}));return{id:e.id,name:e.name,components:t,source:f(e)}}function g(e,t,n,o){const s=e.getComponent(t);if(!s||!n.length)return!1;let i=s;for(let e=0;e<n.length-1;e++){const t=n[e];void 0!==i[t]&&null!==i[t]||(i[t]={}),i=i[t]}return i[n[n.length-1]]=o,!0}const y=new Set(["position","size","origin","anchor","scale","skew"]);function b(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"==typeof e&&""!==e.trim()){const t=Number(e);return Number.isFinite(t)?t:void 0}}const w={Transform:function(e,t,n,o){const s=e.transform??t,i=s;if(1===n.length&&"rotation"===n[0]){const e=b(o);return void 0!==e&&(s.rotation=e,!0)}if(2===n.length&&y.has(n[0])){const t=n[0],s=n[1],r=b(o);if(void 0===r)return!1;const a=i[t];return!(!a||"object"!=typeof a)&&(a[s]=r,"position"===t&&(function(e){const t=e.getComponent("Physics");if(!t?.body)return;const{x:n,y:o}=e.transform.position;t.Body?.setPosition?t.Body.setPosition(t.body,{x:n,y:o}):(t.body.position.x=n,t.body.position.y=o)}(e),function(e){const t=e.getComponent("PlatformerMover");t&&(t.originX=e.transform.position.x,t.originY=e.transform.position.y)}(e)),!0)}return!1},Text:function(e,t,n,o){const s=t;if(1===n.length&&"text"===n[0])return s.text=String(o??""),!0;if(2===n.length&&"style"===n[0]){const e=n[1],t={...s.style??{},[e]:o};return s.style=t,!0}return!1},Sound:function(e,t,n,o){const s=t;if(1===n.length&&"volume"===n[0]||2===n.length&&"config"===n[0]&&"volume"===n[1]){const e=b(o);return void 0!==e&&(s.volume=e,!0)}return!1}};function v(e,t,n,o){const s=e.getComponent(t);if(!s||!n.length)return!1;const i=w[t];return!!i?.(e,s,n,o)||g(e,t,n,o)}const O="__combosDevelopmentToolOutline";let T=class extends t.System{constructor(){super(...arguments),this.postMessageOrigin="*",this.scope="scene",this.enabled=!1,this.outlineGo=null,this.selected=null,this.tapHandlers=new Map,this.tapOwners=new Map,this.savedTapListeners=new Map,this.injectedEvents=new Set,this.needsSceneRescan=!1,this.needsTaggedRescan=!1,this.onWindowSet=e=>{const t=e.detail;t&&"boolean"==typeof t.enabled&&this.setEnabled(t.enabled)},this.onWindowMessage=e=>{const t=e.data;t&&"object"==typeof t&&(t.type===i&&"boolean"==typeof t.enabled?this.setEnabled(t.enabled):t.type===r?this.requestSceneRescan():t.type===c&&this.handleApplyProperty(t))},this.onGameSet=e=>{e&&"boolean"==typeof e.enabled&&this.setEnabled(e.enabled)},this.onGameRefresh=()=>{this.requestSceneRescan()},this.onWindowRefresh=()=>{this.requestSceneRescan()}}static{this.systemName="CombosDevelopmentToolSystem"}init(e){this.postMessageOrigin=e?.postMessageOrigin??"*",this.scope=e?.scope??"scene","undefined"!=typeof window&&(window.addEventListener(i,this.onWindowSet),window.addEventListener(r,this.onWindowRefresh),window.addEventListener("message",this.onWindowMessage)),this.game.on(i,this.onGameSet),this.game.on(r,this.onGameRefresh),this.enabled&&"scene"===this.scope?this.needsSceneRescan=!0:this.enabled&&"tagged"===this.scope&&(this.needsTaggedRescan=!0)}onDestroy(){"undefined"!=typeof window&&(window.removeEventListener(i,this.onWindowSet),window.removeEventListener(r,this.onWindowRefresh),window.removeEventListener("message",this.onWindowMessage)),this.game.off(i,this.onGameSet),this.game.off(r,this.onGameRefresh),this.detachAllTaps(),this.clearSelection()}setEnabled(e){this.enabled!==e&&(this.enabled=e,e?"scene"===this.scope?this.needsSceneRescan=!0:this.needsTaggedRescan=!0:(this.clearSelection(),this.detachAllTaps()))}get isEnabled(){return this.enabled}update(e){this.enabled&&this.needsSceneRescan&&"scene"===this.scope&&(this.needsSceneRescan=!1,this.attachSceneTree()),this.enabled&&this.needsTaggedRescan&&"tagged"===this.scope&&(this.needsTaggedRescan=!1,this.attachTaggedObjects());for(const e of[...this.tapOwners.values()])e.destroyed&&this.releaseTap(e);if(!this.enabled||!this.selected||!this.outlineGo)return;const t=this.outlineGo.getComponent(o.Graphics);if(!t?.graphics)return;const n=this.resolvePickBounds(this.selected),s=t.graphics;s.clear();const i="undefined"!=typeof performance?performance.now():e.time,r=.35+.65*(.5+.5*Math.sin(.012*i));s.rect(n.x,n.y,n.width,n.height),s.stroke({width:4,color:5636010,alpha:r})}componentChanged(e){if("scene"===this.scope)return;const{type:n,gameObject:o,componentName:s}=e;o&&"CombosDevelopmentToolTarget"===s&&(n===t.OBSERVER_TYPE.ADD?this.ensureTap(o):n===t.OBSERVER_TYPE.REMOVE&&(this.releaseTap(o),this.selected===o&&this.clearSelection()))}requestSceneRescan(){this.enabled&&("scene"===this.scope?this.needsSceneRescan=!0:this.needsTaggedRescan=!0)}attachTaggedObjects(){const e=[];for(const t of this.game.scene.transform.children)this.collectGameObjects(t.gameObject,e);for(const t of e)t.name!==O&&t!==this.outlineGo&&t.getComponent(h)&&this.ensureTap(t)}attachSceneTree(){this.detachAllTaps(!1);const e=[];for(const t of this.game.scene.transform.children)this.collectGameObjects(t.gameObject,e);for(const t of e)t.name!==O&&t!==this.outlineGo&&this.ensureTap(t)}collectGameObjects(e,t){t.push(e);for(const n of e.transform.children)this.collectGameObjects(n.gameObject,t)}detachAllTaps(e=!0){for(const t of[...this.tapOwners.values()])this.releaseTap(t,e)}ensureTap(e){let t=e.getComponent(s.Event);if(t||(t=e.addComponent(this.createInjectedEvent(e)),this.injectedEvents.add(e.id)),this.tapHandlers.has(e.id))return;if(!this.savedTapListeners.has(e.id)){const n=t.listeners("tap");this.savedTapListeners.set(e.id,[...n])}t.removeAllListeners("tap");const n=t=>this.onSelect(e,t);this.tapHandlers.set(e.id,n),this.tapOwners.set(e.id,e),t.on("tap",n)}createInjectedEvent(e){const t=this.resolvePickBounds(e);return t.width>0&&t.height>0?new s.Event({hitArea:{type:s.HIT_AREA_TYPE.Rect,style:{x:t.x,y:t.y,width:t.width,height:t.height}}}):new s.Event}resolvePickBounds(e){if(this.shouldPreferRenderedBounds(e)){const t=this.resolveContainerLocalBounds(e);if(t)return t}const{width:t,height:n}=e.transform.size;if(t>0&&n>0)return{x:0,y:0,width:t,height:n};const o=this.resolveContainerLocalBounds(e);return o||{x:0,y:0,width:1,height:1}}shouldPreferRenderedBounds(e){return null!=e.getComponent(o.Graphics)}resolveContainerLocalBounds(e){const t=this.getRendererContainer(e);if(!t)return null;try{const e=t.getLocalBounds();if(e.width>0&&e.height>0)return{x:e.x,y:e.y,width:e.width,height:e.height}}catch{}return null}getRendererContainer(e){const t=this.game.getSystem(n.RendererSystem);if(!t?.containerManager)return null;try{return t.containerManager.getContainer(e.id)}catch{return null}}releaseTap(e,t=!0){const n=this.tapHandlers.get(e.id);if(!n)return;const o=e.getComponent(s.Event);if(o?.off("tap",n),this.tapHandlers.delete(e.id),this.tapOwners.delete(e.id),t){const t=this.savedTapListeners.get(e.id);if(t&&t.length>0&&o)for(const e of t)o.on("tap",e);if(this.savedTapListeners.delete(e.id),this.injectedEvents.has(e.id)){try{e.removeComponent(s.Event)}catch{}this.injectedEvents.delete(e.id)}}}ensureOutline(){if(this.outlineGo)return;const e=new t.GameObject(O,{size:{width:1,height:1},position:{x:0,y:0},origin:{x:0,y:0}});e.addComponent(new o.Graphics),this.outlineGo=e}onSelect(e,t){if(!this.enabled)return;if(t?.stopPropagation?.(),this.ensureOutline(),!this.outlineGo)return;this.selected=e,this.outlineGo.parent&&this.outlineGo.remove(),e.addChild(this.outlineGo);const n=m(e),o={type:a,snapshot:n,pointer:t?.data?.position??null};"undefined"!=typeof window&&window.parent&&window.parent!==window&&window.parent.postMessage(o,this.postMessageOrigin)}findGameObjectById(e){const t=[];for(const e of this.game.scene.transform.children)this.collectGameObjects(e.gameObject,t);return t.find(t=>t.id===e)??null}findGameObjectBySource(e){const t=[];for(const e of this.game.scene.transform.children)this.collectGameObjects(e.gameObject,t);const n=e.file.trim(),o=(e.anchor??"").trim();if(!o)return null;for(const e of t){const t=f(e);if(!t||t.file!==n)continue;if((t.anchor??e.name)===o)return e}return null}resolveApplyTarget(e){if("number"==typeof e.gameObjectId){const t=this.findGameObjectById(e.gameObjectId);if(t)return t}const t=e.source?.file?.trim(),n=e.source?.anchor?.trim();return t&&n?this.findGameObjectBySource({file:t,anchor:n}):null}handleApplyProperty(e){const t=e.componentName,n=e.path,o="number"==typeof e.gameObjectId,s=Boolean(e.source?.file?.trim())&&Boolean(e.source?.anchor?.trim());if(!o&&!s||"string"!=typeof t||!Array.isArray(n)||0===n.length)return;const i=this.resolveApplyTarget(e);if(!i)return;v(i,t,n,e.value)&&this.selected?.id===i.id&&this.postSnapshotUpdate(i)}postSnapshotUpdate(e){const t=m(e);"undefined"!=typeof window&&window.parent&&window.parent!==window&&window.parent.postMessage({type:a,snapshot:t,pointer:null,source:"property-applied"},this.postMessageOrigin)}clearSelection(){this.selected=null,this.outlineGo?.parent&&this.outlineGo.remove();const e=this.outlineGo?.getComponent(o.Graphics);e?.graphics&&e.graphics.clear()}};T=e.__decorate([t.decorators.componentObserver({CombosDevelopmentToolTarget:[]})],T);var E=T;Object.assign(E,{packageName:"@combos-fun/plugin-development-tool",packageVersion:"0.0.19"}),exports.COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY=c,exports.COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED=a,exports.COMBOS_DEVELOPMENT_TOOL_READY="combos-development-tool:ready",exports.COMBOS_DEVELOPMENT_TOOL_REFRESH=r,exports.COMBOS_DEVELOPMENT_TOOL_SET=i,exports.CombosDevelopmentToolSystem=E,exports.CombosDevelopmentToolTarget=h,exports.applyPropertyValue=g,exports.applyPropertyWithHooks=v,exports.buildGameObjectSnapshot=m,exports.readPropertyValue=function(e,t,n){const o=e.getComponent(t);if(!o||!n.length)return;let s=o;for(const e of n){if(null==s||"object"!=typeof s)return;s=s[e]}return s},exports.readSourceAnchor=f;
1
+ "use strict";var e=require("tslib"),t=require("@combos-fun/engine"),n=require("@combos-fun/plugin-renderer"),o=require("@combos-fun/plugin-renderer-graphics"),s=require("@combos-fun/plugin-renderer-event");const i="combos-development-tool:set",r="combos-development-tool:set-success",a="combos-development-tool:refresh",c="combos-development-tool:gameobject-selected",h="combos-development-tool:apply-property";class d extends t.Component{constructor(){super(...arguments),this.payload={}}static{this.componentName="CombosDevelopmentToolTarget"}init(e){this.payload=e?.payload?{...e.payload}:{}}}const l=new Set(["gameObject","name","started","__componentDefaultParams","destroyed","inScene","worldTransform","children","_parent"]),p={Graphics:new Set(["graphics"]),Physics:new Set(["body","Body","PhysicsEngine","World","Constraint","mouseConstraint","bodyParams"]),Event:new Set(["hitArea"])};function u(e,t=0){if(null==e)return e;if("number"==typeof e||"string"==typeof e||"boolean"==typeof e)return e;if(!(t>6)){if(Array.isArray(e))return e.map(e=>u(e,t+1));if("object"==typeof e){const n={};for(const[o,s]of Object.entries(e)){if("function"==typeof s)continue;const e=u(s,t+1);void 0!==e&&(n[o]=e)}return n}}}function m(e){const t={},n=p[e.name];for(const o of Object.keys(e)){if(l.has(o)||o.startsWith("_"))continue;if(n?.has(o))continue;const s=e[o];if("function"==typeof s)continue;const i=u(s);void 0!==i&&(t[o]=i)}return t}function f(e){const t=e.getComponent(d),n=t?.payload?.source;var o;if((o=n)&&"object"==typeof o&&"string"==typeof o.file)return{file:n.file,anchor:n.anchor??e.name}}function g(e){const t=e.components.filter(e=>"CombosDevelopmentToolTarget"!==e.name).map(e=>({componentName:e.name,fields:m(e)}));return{id:e.id,name:e.name,components:t,source:f(e)}}function y(e,t,n,o){const s=e.getComponent(t);if(!s||!n.length)return!1;let i=s;for(let e=0;e<n.length-1;e++){const t=n[e];void 0!==i[t]&&null!==i[t]||(i[t]={}),i=i[t]}return i[n[n.length-1]]=o,!0}const b=new Set(["position","size","origin","anchor","scale","skew"]);function w(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"==typeof e&&""!==e.trim()){const t=Number(e);return Number.isFinite(t)?t:void 0}}const v={Transform:function(e,t,n,o){const s=e.transform??t,i=s;if(1===n.length&&"rotation"===n[0]){const e=w(o);return void 0!==e&&(s.rotation=e,!0)}if(2===n.length&&b.has(n[0])){const t=n[0],s=n[1],r=w(o);if(void 0===r)return!1;const a=i[t];return!(!a||"object"!=typeof a)&&(a[s]=r,"position"===t&&(function(e){const t=e.getComponent("Physics");if(!t?.body)return;const{x:n,y:o}=e.transform.position;t.Body?.setPosition?t.Body.setPosition(t.body,{x:n,y:o}):(t.body.position.x=n,t.body.position.y=o)}(e),function(e){const t=e.getComponent("PlatformerMover");t&&(t.originX=e.transform.position.x,t.originY=e.transform.position.y)}(e)),!0)}return!1},Text:function(e,t,n,o){const s=t;if(1===n.length&&"text"===n[0])return s.text=String(o??""),!0;if(2===n.length&&"style"===n[0]){const e=n[1],t={...s.style??{},[e]:o};return s.style=t,!0}return!1},Sound:function(e,t,n,o){const s=t;if(1===n.length&&"volume"===n[0]||2===n.length&&"config"===n[0]&&"volume"===n[1]){const e=w(o);return void 0!==e&&(s.volume=e,!0)}return!1}};function E(e,t,n,o){const s=e.getComponent(t);if(!s||!n.length)return!1;const i=v[t];return!!i?.(e,s,n,o)||y(e,t,n,o)}const O="__combosDevelopmentToolOutline";let S=class extends t.System{constructor(){super(...arguments),this.postMessageOrigin="*",this.enabled=!1,this.outlineGo=null,this.selected=null,this.tapHandlers=new Map,this.tapOwners=new Map,this.cachedGameEvents=new Map,this.pickEvents=new Set,this.needsRescan=!1,this.onWindowSet=e=>{const t=e.detail;t&&"boolean"==typeof t.enabled&&this.setEnabled(t.enabled)},this.onWindowMessage=e=>{const t=e.data;t&&"object"==typeof t&&(t.type===i&&"boolean"==typeof t.enabled?this.setEnabled(t.enabled):t.type===a?this.requestSceneRescan():t.type===h&&this.handleApplyProperty(t))},this.onGameSet=e=>{e&&"boolean"==typeof e.enabled&&this.setEnabled(e.enabled)},this.onGameRefresh=()=>{this.requestSceneRescan()},this.onWindowRefresh=()=>{this.requestSceneRescan()}}static{this.systemName="CombosDevelopmentToolSystem"}init(e){this.postMessageOrigin=e?.postMessageOrigin??"*","undefined"!=typeof window&&(window.addEventListener(i,this.onWindowSet),window.addEventListener(a,this.onWindowRefresh),window.addEventListener("message",this.onWindowMessage)),this.game.on(i,this.onGameSet),this.game.on(a,this.onGameRefresh),this.enabled&&(this.needsRescan=!0)}onDestroy(){"undefined"!=typeof window&&(window.removeEventListener(i,this.onWindowSet),window.removeEventListener(a,this.onWindowRefresh),window.removeEventListener("message",this.onWindowMessage)),this.game.off(i,this.onGameSet),this.game.off(a,this.onGameRefresh),this.detachAllPicks(),this.restoreCachedGameEvents(),this.clearSelection()}setEnabled(e){this.enabled!==e&&(this.enabled=e,e?this.needsRescan=!0:(this.clearSelection(),this.detachAllPicks(),this.restoreCachedGameEvents(),this.postSetSuccess(!1)))}get isEnabled(){return this.enabled}update(e){this.enabled&&this.needsRescan&&(this.needsRescan=!1,this.attachEditMode(),this.postSetSuccess(!0));for(const e of[...this.tapOwners.values()])e.destroyed&&this.releasePick(e);if(!this.enabled||!this.selected||!this.outlineGo)return;const t=this.outlineGo.getComponent(o.Graphics);if(!t?.graphics)return;const n=this.resolvePickBounds(this.selected),s=t.graphics;s.clear();const i="undefined"!=typeof performance?performance.now():e.time,r=.35+.65*(.5+.5*Math.sin(.012*i));s.rect(n.x,n.y,n.width,n.height),s.stroke({width:4,color:5636010,alpha:r})}componentChanged(e){if(!this.enabled)return;const{type:n,gameObject:o,componentName:s}=e;o&&"CombosDevelopmentToolTarget"===s&&(n===t.OBSERVER_TYPE.ADD?(this.stripGameEvent(o),this.ensurePick(o)):n===t.OBSERVER_TYPE.REMOVE&&(this.releasePick(o),this.selected===o&&this.clearSelection()))}requestSceneRescan(){this.enabled&&(this.needsRescan=!0)}attachEditMode(){this.detachAllPicks();const e=[];for(const t of this.game.scene.transform.children)this.collectGameObjects(t.gameObject,e);for(const t of e)this.isIgnoredPickGo(t)||this.stripGameEvent(t);for(const t of e)this.isIgnoredPickGo(t)||t.getComponent(d)&&this.ensurePick(t)}collectGameObjects(e,t){t.push(e);for(const n of e.transform.children)this.collectGameObjects(n.gameObject,t)}isIgnoredPickGo(e){return e.name===O||e===this.outlineGo}stripGameEvent(e){if(this.cachedGameEvents.has(e.id))return;if(e.getComponent(s.Event))try{const t=e.removeComponent(s.Event);this.cachedGameEvents.set(e.id,t)}catch{}}restoreCachedGameEvents(){for(const[e,t]of[...this.cachedGameEvents.entries()]){const n=this.findGameObjectById(e);if(!n||n.destroyed||n.getComponent(s.Event))this.cachedGameEvents.delete(e);else{try{n.addComponent(t)}catch{}this.cachedGameEvents.delete(e)}}}detachAllPicks(){for(const e of[...this.tapOwners.values()])this.releasePick(e)}ensurePick(e){if(this.tapHandlers.has(e.id))return;let t=e.getComponent(s.Event);t||(t=e.addComponent(this.createPickEvent(e)),this.pickEvents.add(e.id));const n=t=>this.onSelect(e,t);this.tapHandlers.set(e.id,n),this.tapOwners.set(e.id,e),t.on("tap",n)}createPickEvent(e){const t=this.resolvePickBounds(e);return t.width>0&&t.height>0?new s.Event({hitArea:{type:s.HIT_AREA_TYPE.Rect,style:{x:t.x,y:t.y,width:t.width,height:t.height}}}):new s.Event}resolvePickBounds(e){if(this.shouldPreferRenderedBounds(e)){const t=this.resolveContainerLocalBounds(e);if(t)return t}const{width:t,height:n}=e.transform.size;if(t>0&&n>0)return{x:0,y:0,width:t,height:n};const o=this.resolveContainerLocalBounds(e);return o||{x:0,y:0,width:1,height:1}}shouldPreferRenderedBounds(e){return null!=e.getComponent(o.Graphics)}resolveContainerLocalBounds(e){const t=this.getRendererContainer(e);if(!t)return null;try{const e=t.getLocalBounds();if(e.width>0&&e.height>0)return{x:e.x,y:e.y,width:e.width,height:e.height}}catch{}return null}getRendererContainer(e){const t=this.game.getSystem(n.RendererSystem);if(!t?.containerManager)return null;try{return t.containerManager.getContainer(e.id)}catch{return null}}releasePick(e){const t=this.tapHandlers.get(e.id);if(!t)return;const n=e.getComponent(s.Event);if(n?.off("tap",t),this.tapHandlers.delete(e.id),this.tapOwners.delete(e.id),this.pickEvents.has(e.id)){try{e.removeComponent(s.Event)}catch{}this.pickEvents.delete(e.id)}}postSetSuccess(e){const t={type:r,enabled:e};"undefined"!=typeof window&&window.parent&&window.parent!==window&&window.parent.postMessage(t,this.postMessageOrigin),this.game.emit(r,{enabled:e})}ensureOutline(){if(this.outlineGo)return;const e=new t.GameObject(O,{size:{width:1,height:1},position:{x:0,y:0},origin:{x:0,y:0}});e.addComponent(new o.Graphics),this.outlineGo=e}onSelect(e,t){if(!this.enabled)return;if(t?.stopPropagation?.(),this.ensureOutline(),!this.outlineGo)return;this.selected=e,this.outlineGo.parent&&this.outlineGo.remove(),e.addChild(this.outlineGo);const n=g(e),o={type:c,snapshot:n,pointer:t?.data?.position??null};"undefined"!=typeof window&&window.parent&&window.parent!==window&&window.parent.postMessage(o,this.postMessageOrigin)}findGameObjectById(e){const t=[];for(const e of this.game.scene.transform.children)this.collectGameObjects(e.gameObject,t);return t.find(t=>t.id===e)??null}findGameObjectBySource(e){const t=[];for(const e of this.game.scene.transform.children)this.collectGameObjects(e.gameObject,t);const n=e.file.trim(),o=(e.anchor??"").trim();if(!o)return null;for(const e of t){const t=f(e);if(!t||t.file!==n)continue;if((t.anchor??e.name)===o)return e}return null}resolveApplyTarget(e){if("number"==typeof e.gameObjectId){const t=this.findGameObjectById(e.gameObjectId);if(t)return t}const t=e.source?.file?.trim(),n=e.source?.anchor?.trim();return t&&n?this.findGameObjectBySource({file:t,anchor:n}):null}handleApplyProperty(e){const t=e.componentName,n=e.path,o="number"==typeof e.gameObjectId,s=Boolean(e.source?.file?.trim())&&Boolean(e.source?.anchor?.trim());if(!o&&!s||"string"!=typeof t||!Array.isArray(n)||0===n.length)return;const i=this.resolveApplyTarget(e);if(!i)return;E(i,t,n,e.value)&&this.selected?.id===i.id&&this.postSnapshotUpdate(i)}postSnapshotUpdate(e){const t=g(e);"undefined"!=typeof window&&window.parent&&window.parent!==window&&window.parent.postMessage({type:c,snapshot:t,pointer:null,source:"property-applied"},this.postMessageOrigin)}clearSelection(){this.selected=null,this.outlineGo?.parent&&this.outlineGo.remove();const e=this.outlineGo?.getComponent(o.Graphics);e?.graphics&&e.graphics.clear()}};S=e.__decorate([t.decorators.componentObserver({CombosDevelopmentToolTarget:[]})],S);var G=S;Object.assign(G,{packageName:"@combos-fun/plugin-development-tool",packageVersion:"0.0.20"}),exports.COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY=h,exports.COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED=c,exports.COMBOS_DEVELOPMENT_TOOL_READY="combos-development-tool:ready",exports.COMBOS_DEVELOPMENT_TOOL_REFRESH=a,exports.COMBOS_DEVELOPMENT_TOOL_SET=i,exports.COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS=r,exports.CombosDevelopmentToolSystem=G,exports.CombosDevelopmentToolTarget=d,exports.applyPropertyValue=y,exports.applyPropertyWithHooks=E,exports.buildGameObjectSnapshot=g,exports.readPropertyValue=function(e,t,n){const o=e.getComponent(t);if(!o||!n.length)return;let s=o;for(const e of n){if(null==s||"object"!=typeof s)return;s=s[e]}return s},exports.readSourceAnchor=f;
@@ -2,7 +2,9 @@ import { Component, ComponentParams, System, UpdateParams, ComponentChanged, Gam
2
2
 
3
3
  /** Toggle development-tool selection / parent postMessage. Payload: `{ enabled: boolean }`. */
4
4
  declare const COMBOS_DEVELOPMENT_TOOL_SET: "combos-development-tool:set";
5
- /** Re-scan the scene tree (only when `CombosDevelopmentToolSystem` uses `scope: 'scene'`). */
5
+ /** iframe parent: `setEnabled` finished (pick attach after enable, or restore after disable). Payload: `{ enabled: boolean }`. */
6
+ declare const COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS: "combos-development-tool:set-success";
7
+ /** Re-scan the scene tree while the development tool is enabled. */
6
8
  declare const COMBOS_DEVELOPMENT_TOOL_REFRESH: "combos-development-tool:refresh";
7
9
  /** Emitted to `window.parent` when an object is selected while the tool is on. */
8
10
  declare const COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED: "combos-development-tool:gameobject-selected";
@@ -16,8 +18,9 @@ interface CombosDevelopmentToolTargetParams extends ComponentParams {
16
18
  payload?: Record<string, unknown>;
17
19
  }
18
20
  /**
19
- * Optional marker when using `CombosDevelopmentToolSystem` with `scope: 'tagged'`, or to attach
20
- * extra `payload` on specific objects while using `scope: 'scene'` (serialization reads it if present).
21
+ * Marks a `GameObject` as selectable in editor pick mode. While the development tool is enabled,
22
+ * only nodes carrying this component receive a pick `Event`; all other game `Event` components
23
+ * are removed and cached until disable.
21
24
  */
22
25
  declare class CombosDevelopmentToolTarget extends Component<CombosDevelopmentToolTargetParams> {
23
26
  static componentName: string;
@@ -25,41 +28,36 @@ declare class CombosDevelopmentToolTarget extends Component<CombosDevelopmentToo
25
28
  init(params?: CombosDevelopmentToolTargetParams): void;
26
29
  }
27
30
 
28
- type CombosDevelopmentToolSelectScope = 'tagged' | 'scene';
29
31
  interface CombosDevelopmentToolSystemParams {
30
32
  /** postMessage `targetOrigin` when notifying parent (default `'*'`). */
31
33
  postMessageOrigin?: string;
32
- /**
33
- * - `tagged`: only `GameObject`s with {@link CombosDevelopmentToolTarget} participate (optional `payload`).
34
- * - `scene`: all objects under `game.scene` (except the outline helper) get tap → outline + postMessage; no marker component required (default).
35
- */
36
- scope?: CombosDevelopmentToolSelectScope;
37
34
  }
38
35
  /**
39
- * **Defaults:** `scope: 'scene'`, **off** at start (no tap hijack until enabled).
40
- * While enabled, game `Event` `tap` listeners are removed and restored on disable.
36
+ * **Off** at start. While enabled:
37
+ * - strips `Event` from every scene `GameObject` (cached for restore on disable);
38
+ * - attaches pick `Event` + outline only on nodes with {@link CombosDevelopmentToolTarget}.
39
+ *
41
40
  * Turn on/off via:
42
41
  * - `window.dispatchEvent(new CustomEvent(COMBOS_DEVELOPMENT_TOOL_SET, { detail: { enabled: true } }))`
43
42
  * - `window.postMessage({ type: COMBOS_DEVELOPMENT_TOOL_SET, enabled: true }, targetOrigin)` (e.g. from parent iframe)
44
43
  * - `game.emit(COMBOS_DEVELOPMENT_TOOL_SET, { enabled: true })` or `getSystem(CombosDevelopmentToolSystem).setEnabled(true)`
45
44
  *
46
- * With `scope: 'scene'`, while enabled: `game.emit(COMBOS_DEVELOPMENT_TOOL_REFRESH)`, `window` event `combos-development-tool:refresh`, or `postMessage({ type: 'combos-development-tool:refresh' })` to re-bind after adding/removing objects.
45
+ * While enabled: `game.emit(COMBOS_DEVELOPMENT_TOOL_REFRESH)`, `window` event `combos-development-tool:refresh`,
46
+ * or `postMessage({ type: 'combos-development-tool:refresh' })` to re-bind after adding/removing objects.
47
47
  */
48
48
  declare class CombosDevelopmentToolSystem extends System<CombosDevelopmentToolSystemParams> {
49
49
  static systemName: string;
50
50
  private postMessageOrigin;
51
- private scope;
52
51
  private enabled;
53
52
  private outlineGo;
54
53
  private selected;
55
54
  private readonly tapHandlers;
56
55
  private readonly tapOwners;
57
- /** Game `tap` listeners removed while enabled; restored on disable. */
58
- private readonly savedTapListeners;
59
- /** We added `Event` for hit-testing; remove on teardown when disabling / releaseTap. */
60
- private readonly injectedEvents;
61
- private needsSceneRescan;
62
- private needsTaggedRescan;
56
+ /** Game `Event` components removed while enabled; restored on disable. */
57
+ private readonly cachedGameEvents;
58
+ /** Pick `Event` injected for {@link CombosDevelopmentToolTarget} nodes. */
59
+ private readonly pickEvents;
60
+ private needsRescan;
63
61
  private readonly onWindowSet;
64
62
  private readonly onWindowMessage;
65
63
  private readonly onGameSet;
@@ -72,19 +70,22 @@ declare class CombosDevelopmentToolSystem extends System<CombosDevelopmentToolSy
72
70
  get isEnabled(): boolean;
73
71
  update(e: UpdateParams): void;
74
72
  componentChanged(changed: ComponentChanged): void;
75
- /** Re-bind scene taps when `scope === 'scene'` (e.g. after dynamic spawn). */
73
+ /** Re-bind pick targets after dynamic scene changes while enabled. */
76
74
  requestSceneRescan(): void;
77
- private attachTaggedObjects;
78
- private attachSceneTree;
75
+ private attachEditMode;
79
76
  private collectGameObjects;
80
- private detachAllTaps;
81
- private ensureTap;
82
- private createInjectedEvent;
77
+ private isIgnoredPickGo;
78
+ private stripGameEvent;
79
+ private restoreCachedGameEvents;
80
+ private detachAllPicks;
81
+ private ensurePick;
82
+ private createPickEvent;
83
83
  private resolvePickBounds;
84
84
  private shouldPreferRenderedBounds;
85
85
  private resolveContainerLocalBounds;
86
86
  private getRendererContainer;
87
- private releaseTap;
87
+ private releasePick;
88
+ private postSetSuccess;
88
89
  private ensureOutline;
89
90
  private onSelect;
90
91
  private findGameObjectById;
@@ -126,5 +127,5 @@ declare function readPropertyValue(go: GameObject, componentName: string, path:
126
127
 
127
128
  declare function applyPropertyWithHooks(go: GameObject, componentName: string, path: string[], value: unknown): boolean;
128
129
 
129
- export { COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY, COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED, COMBOS_DEVELOPMENT_TOOL_READY, COMBOS_DEVELOPMENT_TOOL_REFRESH, COMBOS_DEVELOPMENT_TOOL_SET, CombosDevelopmentToolSystem, CombosDevelopmentToolTarget, applyPropertyValue, applyPropertyWithHooks, buildGameObjectSnapshot, readPropertyValue, readSourceAnchor };
130
- export type { CombosDevelopmentToolSelectScope, CombosDevelopmentToolSystemParams, CombosDevelopmentToolTargetParams, SceneEditComponentSnapshot, SceneEditGameObjectSnapshot, SceneEditPropertyRef, SceneSourceAnchor };
130
+ export { COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY, COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED, COMBOS_DEVELOPMENT_TOOL_READY, COMBOS_DEVELOPMENT_TOOL_REFRESH, COMBOS_DEVELOPMENT_TOOL_SET, COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS, CombosDevelopmentToolSystem, CombosDevelopmentToolTarget, applyPropertyValue, applyPropertyWithHooks, buildGameObjectSnapshot, readPropertyValue, readSourceAnchor };
131
+ export type { CombosDevelopmentToolSystemParams, CombosDevelopmentToolTargetParams, SceneEditComponentSnapshot, SceneEditGameObjectSnapshot, SceneEditPropertyRef, SceneSourceAnchor };
@@ -6,7 +6,9 @@ import { Event, HIT_AREA_TYPE } from '@combos-fun/plugin-renderer-event';
6
6
 
7
7
  /** Toggle development-tool selection / parent postMessage. Payload: `{ enabled: boolean }`. */
8
8
  const COMBOS_DEVELOPMENT_TOOL_SET = 'combos-development-tool:set';
9
- /** Re-scan the scene tree (only when `CombosDevelopmentToolSystem` uses `scope: 'scene'`). */
9
+ /** iframe parent: `setEnabled` finished (pick attach after enable, or restore after disable). Payload: `{ enabled: boolean }`. */
10
+ const COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS = 'combos-development-tool:set-success';
11
+ /** Re-scan the scene tree while the development tool is enabled. */
10
12
  const COMBOS_DEVELOPMENT_TOOL_REFRESH = 'combos-development-tool:refresh';
11
13
  /** Emitted to `window.parent` when an object is selected while the tool is on. */
12
14
  const COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED = 'combos-development-tool:gameobject-selected';
@@ -16,8 +18,9 @@ const COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY = 'combos-development-tool:apply-pr
16
18
  const COMBOS_DEVELOPMENT_TOOL_READY = 'combos-development-tool:ready';
17
19
 
18
20
  /**
19
- * Optional marker when using `CombosDevelopmentToolSystem` with `scope: 'tagged'`, or to attach
20
- * extra `payload` on specific objects while using `scope: 'scene'` (serialization reads it if present).
21
+ * Marks a `GameObject` as selectable in editor pick mode. While the development tool is enabled,
22
+ * only nodes carrying this component receive a pick `Event`; all other game `Event` components
23
+ * are removed and cached until disable.
21
24
  */
22
25
  class CombosDevelopmentToolTarget extends Component {
23
26
  constructor() {
@@ -270,31 +273,32 @@ function applyPropertyWithHooks(go, componentName, path, value) {
270
273
 
271
274
  const OUTLINE_GO_NAME = '__combosDevelopmentToolOutline';
272
275
  /**
273
- * **Defaults:** `scope: 'scene'`, **off** at start (no tap hijack until enabled).
274
- * While enabled, game `Event` `tap` listeners are removed and restored on disable.
276
+ * **Off** at start. While enabled:
277
+ * - strips `Event` from every scene `GameObject` (cached for restore on disable);
278
+ * - attaches pick `Event` + outline only on nodes with {@link CombosDevelopmentToolTarget}.
279
+ *
275
280
  * Turn on/off via:
276
281
  * - `window.dispatchEvent(new CustomEvent(COMBOS_DEVELOPMENT_TOOL_SET, { detail: { enabled: true } }))`
277
282
  * - `window.postMessage({ type: COMBOS_DEVELOPMENT_TOOL_SET, enabled: true }, targetOrigin)` (e.g. from parent iframe)
278
283
  * - `game.emit(COMBOS_DEVELOPMENT_TOOL_SET, { enabled: true })` or `getSystem(CombosDevelopmentToolSystem).setEnabled(true)`
279
284
  *
280
- * With `scope: 'scene'`, while enabled: `game.emit(COMBOS_DEVELOPMENT_TOOL_REFRESH)`, `window` event `combos-development-tool:refresh`, or `postMessage({ type: 'combos-development-tool:refresh' })` to re-bind after adding/removing objects.
285
+ * While enabled: `game.emit(COMBOS_DEVELOPMENT_TOOL_REFRESH)`, `window` event `combos-development-tool:refresh`,
286
+ * or `postMessage({ type: 'combos-development-tool:refresh' })` to re-bind after adding/removing objects.
281
287
  */
282
288
  let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends System {
283
289
  constructor() {
284
290
  super(...arguments);
285
291
  this.postMessageOrigin = '*';
286
- this.scope = 'scene';
287
292
  this.enabled = false;
288
293
  this.outlineGo = null;
289
294
  this.selected = null;
290
295
  this.tapHandlers = new Map();
291
296
  this.tapOwners = new Map();
292
- /** Game `tap` listeners removed while enabled; restored on disable. */
293
- this.savedTapListeners = new Map();
294
- /** We added `Event` for hit-testing; remove on teardown when disabling / releaseTap. */
295
- this.injectedEvents = new Set();
296
- this.needsSceneRescan = false;
297
- this.needsTaggedRescan = false;
297
+ /** Game `Event` components removed while enabled; restored on disable. */
298
+ this.cachedGameEvents = new Map();
299
+ /** Pick `Event` injected for {@link CombosDevelopmentToolTarget} nodes. */
300
+ this.pickEvents = new Set();
301
+ this.needsRescan = false;
298
302
  this.onWindowSet = (e) => {
299
303
  const d = e.detail;
300
304
  if (d && typeof d.enabled === 'boolean') {
@@ -330,7 +334,6 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
330
334
  static { this.systemName = 'CombosDevelopmentToolSystem'; }
331
335
  init(params) {
332
336
  this.postMessageOrigin = params?.postMessageOrigin ?? '*';
333
- this.scope = params?.scope ?? 'scene';
334
337
  if (typeof window !== 'undefined') {
335
338
  window.addEventListener(COMBOS_DEVELOPMENT_TOOL_SET, this.onWindowSet);
336
339
  window.addEventListener(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onWindowRefresh);
@@ -338,11 +341,8 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
338
341
  }
339
342
  this.game.on(COMBOS_DEVELOPMENT_TOOL_SET, this.onGameSet);
340
343
  this.game.on(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onGameRefresh);
341
- if (this.enabled && this.scope === 'scene') {
342
- this.needsSceneRescan = true;
343
- }
344
- else if (this.enabled && this.scope === 'tagged') {
345
- this.needsTaggedRescan = true;
344
+ if (this.enabled) {
345
+ this.needsRescan = true;
346
346
  }
347
347
  }
348
348
  onDestroy() {
@@ -353,7 +353,8 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
353
353
  }
354
354
  this.game.off(COMBOS_DEVELOPMENT_TOOL_SET, this.onGameSet);
355
355
  this.game.off(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onGameRefresh);
356
- this.detachAllTaps();
356
+ this.detachAllPicks();
357
+ this.restoreCachedGameEvents();
357
358
  this.clearSelection();
358
359
  }
359
360
  /** Programmatic toggle (same effect as events). */
@@ -363,30 +364,26 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
363
364
  this.enabled = on;
364
365
  if (!on) {
365
366
  this.clearSelection();
366
- this.detachAllTaps();
367
- }
368
- else if (this.scope === 'scene') {
369
- this.needsSceneRescan = true;
367
+ this.detachAllPicks();
368
+ this.restoreCachedGameEvents();
369
+ this.postSetSuccess(false);
370
370
  }
371
371
  else {
372
- this.needsTaggedRescan = true;
372
+ this.needsRescan = true;
373
373
  }
374
374
  }
375
375
  get isEnabled() {
376
376
  return this.enabled;
377
377
  }
378
378
  update(e) {
379
- if (this.enabled && this.needsSceneRescan && this.scope === 'scene') {
380
- this.needsSceneRescan = false;
381
- this.attachSceneTree();
382
- }
383
- if (this.enabled && this.needsTaggedRescan && this.scope === 'tagged') {
384
- this.needsTaggedRescan = false;
385
- this.attachTaggedObjects();
379
+ if (this.enabled && this.needsRescan) {
380
+ this.needsRescan = false;
381
+ this.attachEditMode();
382
+ this.postSetSuccess(true);
386
383
  }
387
384
  for (const go of [...this.tapOwners.values()]) {
388
385
  if (go.destroyed) {
389
- this.releaseTap(go);
386
+ this.releasePick(go);
390
387
  }
391
388
  }
392
389
  if (!this.enabled || !this.selected || !this.outlineGo)
@@ -403,59 +400,45 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
403
400
  g.stroke({ width: 4, color: 0x55ffaa, alpha: pulse });
404
401
  }
405
402
  componentChanged(changed) {
406
- if (this.scope === 'scene')
403
+ if (!this.enabled)
407
404
  return;
408
405
  const { type, gameObject, componentName } = changed;
409
406
  if (!gameObject || componentName !== 'CombosDevelopmentToolTarget')
410
407
  return;
411
408
  if (type === OBSERVER_TYPE.ADD) {
412
- this.ensureTap(gameObject);
409
+ this.stripGameEvent(gameObject);
410
+ this.ensurePick(gameObject);
413
411
  }
414
412
  else if (type === OBSERVER_TYPE.REMOVE) {
415
- this.releaseTap(gameObject);
413
+ this.releasePick(gameObject);
416
414
  if (this.selected === gameObject) {
417
415
  this.clearSelection();
418
416
  }
419
417
  }
420
418
  }
421
- /** Re-bind scene taps when `scope === 'scene'` (e.g. after dynamic spawn). */
419
+ /** Re-bind pick targets after dynamic scene changes while enabled. */
422
420
  requestSceneRescan() {
423
421
  if (!this.enabled)
424
422
  return;
425
- if (this.scope === 'scene') {
426
- this.needsSceneRescan = true;
427
- }
428
- else {
429
- this.needsTaggedRescan = true;
430
- }
423
+ this.needsRescan = true;
431
424
  }
432
- attachTaggedObjects() {
425
+ attachEditMode() {
426
+ this.detachAllPicks();
433
427
  const list = [];
434
428
  for (const tr of this.game.scene.transform.children) {
435
429
  this.collectGameObjects(tr.gameObject, list);
436
430
  }
437
431
  for (const go of list) {
438
- if (go.name === OUTLINE_GO_NAME)
439
- continue;
440
- if (go === this.outlineGo)
441
- continue;
442
- if (!go.getComponent(CombosDevelopmentToolTarget))
432
+ if (this.isIgnoredPickGo(go))
443
433
  continue;
444
- this.ensureTap(go);
445
- }
446
- }
447
- attachSceneTree() {
448
- this.detachAllTaps(false);
449
- const list = [];
450
- for (const tr of this.game.scene.transform.children) {
451
- this.collectGameObjects(tr.gameObject, list);
434
+ this.stripGameEvent(go);
452
435
  }
453
436
  for (const go of list) {
454
- if (go.name === OUTLINE_GO_NAME)
437
+ if (this.isIgnoredPickGo(go))
455
438
  continue;
456
- if (go === this.outlineGo)
439
+ if (!go.getComponent(CombosDevelopmentToolTarget))
457
440
  continue;
458
- this.ensureTap(go);
441
+ this.ensurePick(go);
459
442
  }
460
443
  }
461
444
  collectGameObjects(go, out) {
@@ -464,30 +447,58 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
464
447
  this.collectGameObjects(tr.gameObject, out);
465
448
  }
466
449
  }
467
- detachAllTaps(restore = true) {
468
- for (const go of [...this.tapOwners.values()]) {
469
- this.releaseTap(go, restore);
450
+ isIgnoredPickGo(go) {
451
+ return go.name === OUTLINE_GO_NAME || go === this.outlineGo;
452
+ }
453
+ stripGameEvent(go) {
454
+ if (this.cachedGameEvents.has(go.id))
455
+ return;
456
+ const ev = go.getComponent(Event);
457
+ if (!ev)
458
+ return;
459
+ try {
460
+ const removed = go.removeComponent(Event);
461
+ this.cachedGameEvents.set(go.id, removed);
462
+ }
463
+ catch {
464
+ /* ignore */
470
465
  }
471
466
  }
472
- ensureTap(go) {
473
- let ev = go.getComponent(Event);
474
- if (!ev) {
475
- ev = go.addComponent(this.createInjectedEvent(go));
476
- this.injectedEvents.add(go.id);
467
+ restoreCachedGameEvents() {
468
+ for (const [id, event] of [...this.cachedGameEvents.entries()]) {
469
+ const go = this.findGameObjectById(id);
470
+ if (!go || go.destroyed || go.getComponent(Event)) {
471
+ this.cachedGameEvents.delete(id);
472
+ continue;
473
+ }
474
+ try {
475
+ go.addComponent(event);
476
+ }
477
+ catch {
478
+ /* ignore */
479
+ }
480
+ this.cachedGameEvents.delete(id);
481
+ }
482
+ }
483
+ detachAllPicks() {
484
+ for (const go of [...this.tapOwners.values()]) {
485
+ this.releasePick(go);
477
486
  }
487
+ }
488
+ ensurePick(go) {
478
489
  if (this.tapHandlers.has(go.id))
479
490
  return;
480
- if (!this.savedTapListeners.has(go.id)) {
481
- const existing = ev.listeners('tap');
482
- this.savedTapListeners.set(go.id, [...existing]);
491
+ let ev = go.getComponent(Event);
492
+ if (!ev) {
493
+ ev = go.addComponent(this.createPickEvent(go));
494
+ this.pickEvents.add(go.id);
483
495
  }
484
- ev.removeAllListeners('tap');
485
496
  const handler = payload => this.onSelect(go, payload);
486
497
  this.tapHandlers.set(go.id, handler);
487
498
  this.tapOwners.set(go.id, go);
488
499
  ev.on('tap', handler);
489
500
  }
490
- createInjectedEvent(go) {
501
+ createPickEvent(go) {
491
502
  const bounds = this.resolvePickBounds(go);
492
503
  if (bounds.width > 0 && bounds.height > 0) {
493
504
  return new Event({
@@ -502,12 +513,9 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
502
513
  },
503
514
  });
504
515
  }
505
- // Let Pixi use natural rendered bounds instead of forcing a 1×1 hit area.
506
516
  return new Event();
507
517
  }
508
518
  resolvePickBounds(go) {
509
- // Graphics draws in arbitrary local coordinates (often centered at 0,0).
510
- // transform.size is a layout box from (0,0) and must not override Pixi bounds.
511
519
  if (this.shouldPreferRenderedBounds(go)) {
512
520
  const fromGraphics = this.resolveContainerLocalBounds(go);
513
521
  if (fromGraphics) {
@@ -558,7 +566,7 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
558
566
  return null;
559
567
  }
560
568
  }
561
- releaseTap(go, restore = true) {
569
+ releasePick(go) {
562
570
  const handler = this.tapHandlers.get(go.id);
563
571
  if (!handler)
564
572
  return;
@@ -566,24 +574,25 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
566
574
  ev?.off('tap', handler);
567
575
  this.tapHandlers.delete(go.id);
568
576
  this.tapOwners.delete(go.id);
569
- if (restore) {
570
- const saved = this.savedTapListeners.get(go.id);
571
- if (saved && saved.length > 0 && ev) {
572
- for (const fn of saved) {
573
- ev.on('tap', fn);
574
- }
577
+ if (this.pickEvents.has(go.id)) {
578
+ try {
579
+ go.removeComponent(Event);
575
580
  }
576
- this.savedTapListeners.delete(go.id);
577
- if (this.injectedEvents.has(go.id)) {
578
- try {
579
- go.removeComponent(Event);
580
- }
581
- catch {
582
- /* ignore */
583
- }
584
- this.injectedEvents.delete(go.id);
581
+ catch {
582
+ /* ignore */
585
583
  }
584
+ this.pickEvents.delete(go.id);
585
+ }
586
+ }
587
+ postSetSuccess(enabled) {
588
+ const payload = {
589
+ type: COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS,
590
+ enabled,
591
+ };
592
+ if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
593
+ window.parent.postMessage(payload, this.postMessageOrigin);
586
594
  }
595
+ this.game.emit(COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS, { enabled });
587
596
  }
588
597
  ensureOutline() {
589
598
  if (this.outlineGo)
@@ -714,8 +723,8 @@ var CombosDevelopmentToolSystem$1 = CombosDevelopmentToolSystem;
714
723
  /** Auto-generated by scripts/build-package.mjs — do not edit. */
715
724
  Object.assign(CombosDevelopmentToolSystem$1, {
716
725
  packageName: "@combos-fun/plugin-development-tool",
717
- packageVersion: "0.0.19",
726
+ packageVersion: "0.0.20",
718
727
  });
719
728
 
720
- export { COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY, COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED, COMBOS_DEVELOPMENT_TOOL_READY, COMBOS_DEVELOPMENT_TOOL_REFRESH, COMBOS_DEVELOPMENT_TOOL_SET, CombosDevelopmentToolSystem$1 as CombosDevelopmentToolSystem, CombosDevelopmentToolTarget, applyPropertyValue, applyPropertyWithHooks, buildGameObjectSnapshot, readPropertyValue, readSourceAnchor };
729
+ export { COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY, COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED, COMBOS_DEVELOPMENT_TOOL_READY, COMBOS_DEVELOPMENT_TOOL_REFRESH, COMBOS_DEVELOPMENT_TOOL_SET, COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS, CombosDevelopmentToolSystem$1 as CombosDevelopmentToolSystem, CombosDevelopmentToolTarget, applyPropertyValue, applyPropertyWithHooks, buildGameObjectSnapshot, readPropertyValue, readSourceAnchor };
721
730
  //# sourceMappingURL=plugin-development-tool.esm.js.map