@combos-fun/plugin-development-tool 0.0.21 → 0.0.23

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:set-success",a="combos-development-tool:refresh",c="combos-development-tool:gameobject-selected",l="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 d=new Set(["gameObject","name","started","__componentDefaultParams","destroyed","inScene","worldTransform","children","_parent"]),u={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 m(e){const t={},n=u[e.name];for(const o of Object.keys(e)){if(d.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 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 O={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 v(e,t,n,o){const s=e.getComponent(t);if(!s||!n.length)return!1;const i=O[t];return!!i?.(e,s,n,o)||y(e,t,n,o)}const E="__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.lastOutlineBounds=null,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===l&&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);this.enabled&&this.selected&&this.outlineGo&&this.updateSelectionOutline()}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(h)&&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===E||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.resolveOwnGraphicsLocalBounds(e);if(t)return t;const n=this.resolveContainerLocalBounds(e);if(n)return n}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)}resolveOwnGraphicsLocalBounds(e){const t=e.getComponent(o.Graphics);if(!t?.graphics)return null;try{const e=t.graphics.getLocalBounds();if(e.width>0&&e.height>0)return{x:e.x,y:e.y,width:e.width,height:e.height}}catch{}return null}resolveContainerLocalBounds(e){const t=this.getRendererContainer(e);if(!t)return null;const n=this.getOutlineContainerIfChildOf(e);let o=!1;n?.parent===t&&(t.removeChild(n),o=!0);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{}finally{o&&n&&t.addChild(n)}return null}getOutlineContainerIfChildOf(e){return this.outlineGo&&this.outlineGo.parent===e?this.getRendererContainer(this.outlineGo):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(E,{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),this.invalidateOutlineBounds(),this.updateSelectionOutline();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;v(i,t,n,e.value)&&this.selected?.id===i.id&&(this.invalidateOutlineBounds(),this.updateSelectionOutline(),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.invalidateOutlineBounds(),this.outlineGo?.parent&&this.outlineGo.remove();const e=this.outlineGo?.getComponent(o.Graphics);e?.graphics&&e.graphics.clear()}updateSelectionOutline(){if(!this.enabled||!this.selected||!this.outlineGo)return;const e=this.outlineGo.getComponent(o.Graphics);if(!e?.graphics)return;const t=this.resolvePickBounds(this.selected);if(this.lastOutlineBounds&&this.pickBoundsEqual(this.lastOutlineBounds,t))return;this.lastOutlineBounds=t;const n=e.graphics;n.clear(),n.rect(t.x,t.y,t.width,t.height),n.stroke({width:4,color:5636010,alpha:1})}invalidateOutlineBounds(){this.lastOutlineBounds=null}pickBoundsEqual(e,t){const n=.01;return Math.abs(e.x-t.x)<n&&Math.abs(e.y-t.y)<n&&Math.abs(e.width-t.width)<n&&Math.abs(e.height-t.height)<n}};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=l,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=h,exports.applyPropertyValue=y,exports.applyPropertyWithHooks=v,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;
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",d="combos-development-tool:gameobject-selected",h="combos-development-tool:apply-property",c="combos-development-tool:set-paused",l="combos-development-tool:set-muted",u="combos-development-tool:state-changed";class p extends t.Component{constructor(){super(...arguments),this.payload={}}static{this.componentName="CombosDevelopmentToolTarget"}init(e){this.payload=e?.payload?{...e.payload}:{}}}const m=new Set(["gameObject","name","started","__componentDefaultParams","destroyed","inScene","worldTransform","children","_parent"]),f={Graphics:new Set(["graphics"]),Physics:new Set(["body","Body","PhysicsEngine","World","Constraint","mouseConstraint","bodyParams"]),Event:new Set(["hitArea"])};function g(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=>g(e,t+1));if("object"==typeof e){const n={};for(const[o,s]of Object.entries(e)){if("function"==typeof s)continue;const e=g(s,t+1);void 0!==e&&(n[o]=e)}return n}}}function y(e){const t={},n=f[e.name];for(const o of Object.keys(e)){if(m.has(o)||o.startsWith("_"))continue;if(n?.has(o))continue;const s=e[o];if("function"==typeof s)continue;const i=g(s);void 0!==i&&(t[o]=i)}return t}function w(e){const t=e.getComponent(p),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 b(e){const t=e.components.filter(e=>"CombosDevelopmentToolTarget"!==e.name).map(e=>({componentName:e.name,fields:y(e)}));return{id:e.id,name:e.name,components:t,source:w(e)}}function O(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 E=new Set(["position","size","origin","anchor","scale","skew"]);function S(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=S(o);return void 0!==e&&(s.rotation=e,!0)}if(2===n.length&&E.has(n[0])){const t=n[0],s=n[1],r=S(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=S(o);return void 0!==e&&(s.volume=e,!0)}return!1}};function G(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)||O(e,t,n,o)}const P="__combosDevelopmentToolOutline";let C=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.disabledGameEventGoIds=new Set,this.pickEvents=new Set,this.needsRescan=!1,this.lastOutlineBounds=null,this.mutedWithoutSoundSystem=!1,this.onWindowSet=e=>{const t=e.detail;t&&"boolean"==typeof t.enabled&&this.setEnabled(t.enabled)},this.onWindowSetPaused=e=>{const t=e.detail;t&&"boolean"==typeof t.paused&&this.setPaused(t.paused)},this.onWindowSetMuted=e=>{const t=e.detail;t&&"boolean"==typeof t.muted&&this.setMuted(t.muted)},this.onWindowMessage=e=>{const t=e.data;t&&"object"==typeof t&&(t.type===i&&"boolean"==typeof t.enabled?this.setEnabled(t.enabled):t.type===c&&"boolean"==typeof t.paused?this.setPaused(t.paused):t.type===l&&"boolean"==typeof t.muted?this.setMuted(t.muted):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.onGameSetPaused=e=>{e&&"boolean"==typeof e.paused&&this.setPaused(e.paused)},this.onGameSetMuted=e=>{e&&"boolean"==typeof e.muted&&this.setMuted(e.muted)},this.onWindowRefresh=()=>{this.requestSceneRescan()}}static{this.systemName="CombosDevelopmentToolSystem"}init(e){this.postMessageOrigin=e?.postMessageOrigin??"*","undefined"!=typeof window&&(window.addEventListener(i,this.onWindowSet),window.addEventListener(c,this.onWindowSetPaused),window.addEventListener(l,this.onWindowSetMuted),window.addEventListener(a,this.onWindowRefresh),window.addEventListener("message",this.onWindowMessage)),this.game.on(i,this.onGameSet),this.game.on(c,this.onGameSetPaused),this.game.on(l,this.onGameSetMuted),this.game.on(a,this.onGameRefresh),this.enabled&&(this.needsRescan=!0)}onDestroy(){"undefined"!=typeof window&&(window.removeEventListener(i,this.onWindowSet),window.removeEventListener(c,this.onWindowSetPaused),window.removeEventListener(l,this.onWindowSetMuted),window.removeEventListener(a,this.onWindowRefresh),window.removeEventListener("message",this.onWindowMessage)),this.game.off(i,this.onGameSet),this.game.off(c,this.onGameSetPaused),this.game.off(l,this.onGameSetMuted),this.game.off(a,this.onGameRefresh),this.detachAllPicks(),this.restoreDisabledGameEvents(),this.clearSelection()}setEnabled(e){this.enabled!==e&&(this.enabled=e,e?this.needsRescan=!0:(this.clearSelection(),this.detachAllPicks(),this.restoreDisabledGameEvents(),this.postSetSuccess(!1)))}get isEnabled(){return this.enabled}get isPaused(){return!this.game.playing}get isMuted(){const e=this.getSoundSystem();return e?e.muted:this.mutedWithoutSoundSystem}setPaused(e){e?this.game.playing&&this.game.pause():this.game.playing||this.game.resume(),this.postStateChanged()}setMuted(e){const t=this.getSoundSystem();t?t.muted=e:this.mutedWithoutSoundSystem=e,this.postStateChanged()}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);this.enabled&&this.selected&&this.outlineGo&&this.updateSelectionOutline()}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(p)&&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===P||e===this.outlineGo}stripGameEvent(e){if(this.disabledGameEventGoIds.has(e.id))return;if(!e.getComponent(s.Event))return;const t=this.getRendererContainer(e);if(t)try{t.interactive=!1,this.disabledGameEventGoIds.add(e.id)}catch{}}restoreDisabledGameEvents(){for(const e of[...this.disabledGameEventGoIds]){const t=this.findGameObjectById(e);if(!t||t.destroyed){this.disabledGameEventGoIds.delete(e);continue}const n=this.getRendererContainer(t);if(n)try{n.interactive=!0}catch{}this.disabledGameEventGoIds.delete(e)}}detachAllPicks(){for(const e of[...this.tapOwners.values()])this.releasePick(e)}ensurePick(e){if(this.tapHandlers.has(e.id))return;const t=this.getRendererContainer(e);if(t)try{t.interactive=!0}catch{}let n=e.getComponent(s.Event);n||(n=e.addComponent(this.createPickEvent(e)),this.pickEvents.add(e.id));const o=t=>this.onSelect(e,t);this.tapHandlers.set(e.id,o),this.tapOwners.set(e.id,e),n.on("tap",o)}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.resolveOwnGraphicsLocalBounds(e);if(t)return t;const n=this.resolveContainerLocalBounds(e);if(n)return n}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)}resolveOwnGraphicsLocalBounds(e){const t=e.getComponent(o.Graphics);if(!t?.graphics)return null;try{const e=t.graphics.getLocalBounds();if(e.width>0&&e.height>0)return{x:e.x,y:e.y,width:e.width,height:e.height}}catch{}return null}resolveContainerLocalBounds(e){const t=this.getRendererContainer(e);if(!t)return null;const n=this.getOutlineContainerIfChildOf(e);let o=!1;n?.parent===t&&(t.removeChild(n),o=!0);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{}finally{o&&n&&t.addChild(n)}return null}getOutlineContainerIfChildOf(e){return this.outlineGo&&this.outlineGo.parent===e?this.getRendererContainer(this.outlineGo):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})}postStateChanged(){const e={paused:this.isPaused,muted:this.isMuted},t={type:u,...e};"undefined"!=typeof window&&window.parent&&window.parent!==window&&window.parent.postMessage(t,this.postMessageOrigin),this.game.emit(u,e)}getSoundSystem(){const e=this.game.getSystem("SoundSystem");return e&&"object"==typeof e&&"muted"in e&&"boolean"==typeof e.muted?e:null}ensureOutline(){if(this.outlineGo)return;const e=new t.GameObject(P,{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),this.invalidateOutlineBounds(),this.updateSelectionOutline();const n=b(e),o={type:d,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=w(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;G(i,t,n,e.value)&&this.selected?.id===i.id&&(this.invalidateOutlineBounds(),this.updateSelectionOutline(),this.postSnapshotUpdate(i))}postSnapshotUpdate(e){const t=b(e);"undefined"!=typeof window&&window.parent&&window.parent!==window&&window.parent.postMessage({type:d,snapshot:t,pointer:null,source:"property-applied"},this.postMessageOrigin)}clearSelection(){this.selected=null,this.invalidateOutlineBounds(),this.outlineGo?.parent&&this.outlineGo.remove();const e=this.outlineGo?.getComponent(o.Graphics);e?.graphics&&e.graphics.clear()}updateSelectionOutline(){if(!this.enabled||!this.selected||!this.outlineGo)return;const e=this.outlineGo.getComponent(o.Graphics);if(!e?.graphics)return;const t=this.resolvePickBounds(this.selected);if(this.lastOutlineBounds&&this.pickBoundsEqual(this.lastOutlineBounds,t))return;this.lastOutlineBounds=t;const n=e.graphics;n.clear(),n.rect(t.x,t.y,t.width,t.height),n.stroke({width:4,color:5636010,alpha:1})}invalidateOutlineBounds(){this.lastOutlineBounds=null}pickBoundsEqual(e,t){const n=.01;return Math.abs(e.x-t.x)<n&&Math.abs(e.y-t.y)<n&&Math.abs(e.width-t.width)<n&&Math.abs(e.height-t.height)<n}};C=e.__decorate([t.decorators.componentObserver({CombosDevelopmentToolTarget:[]})],C);var M=C;Object.assign(M,{packageName:"@combos-fun/plugin-development-tool",packageVersion:"0.0.22"}),exports.COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY=h,exports.COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED=d,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_MUTED=l,exports.COMBOS_DEVELOPMENT_TOOL_SET_PAUSED=c,exports.COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS=r,exports.COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED=u,exports.CombosDevelopmentToolSystem=M,exports.CombosDevelopmentToolTarget=p,exports.applyPropertyValue=O,exports.applyPropertyWithHooks=G,exports.buildGameObjectSnapshot=b,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=w;
@@ -12,6 +12,12 @@ declare const COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED: "combos-development-t
12
12
  declare const COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY: "combos-development-tool:apply-property";
13
13
  /** iframe → parent: game scene bootstrap finished; parent may enable pick mode. */
14
14
  declare const COMBOS_DEVELOPMENT_TOOL_READY: "combos-development-tool:ready";
15
+ /** Parent → iframe: pause or resume the game loop. Payload: `{ paused: boolean }`. */
16
+ declare const COMBOS_DEVELOPMENT_TOOL_SET_PAUSED: "combos-development-tool:set-paused";
17
+ /** Parent → iframe: mute or unmute audio when `SoundSystem` is registered. Payload: `{ muted: boolean }`. */
18
+ declare const COMBOS_DEVELOPMENT_TOOL_SET_MUTED: "combos-development-tool:set-muted";
19
+ /** iframe → parent (and `game.emit`): current pause/mute snapshot after a successful change. */
20
+ declare const COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED: "combos-development-tool:state-changed";
15
21
 
16
22
  interface CombosDevelopmentToolTargetParams extends ComponentParams {
17
23
  /** Extra JSON-serializable fields included in postMessage to parent. */
@@ -34,7 +40,7 @@ interface CombosDevelopmentToolSystemParams {
34
40
  }
35
41
  /**
36
42
  * **Off** at start. While enabled:
37
- * - strips `Event` from every scene `GameObject` (cached for restore on disable);
43
+ * - soft-disables game `Event` hit targets (`container.interactive = false`, restored on disable);
38
44
  * - attaches pick `Event` + outline only on nodes with {@link CombosDevelopmentToolTarget}.
39
45
  *
40
46
  * Turn on/off via:
@@ -42,6 +48,13 @@ interface CombosDevelopmentToolSystemParams {
42
48
  * - `window.postMessage({ type: COMBOS_DEVELOPMENT_TOOL_SET, enabled: true }, targetOrigin)` (e.g. from parent iframe)
43
49
  * - `game.emit(COMBOS_DEVELOPMENT_TOOL_SET, { enabled: true })` or `getSystem(CombosDevelopmentToolSystem).setEnabled(true)`
44
50
  *
51
+ * Pause / mute (independent of pick mode; parent toolbar or in-game debug UI):
52
+ * - `postMessage({ type: COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, paused: true })`
53
+ * - `postMessage({ type: COMBOS_DEVELOPMENT_TOOL_SET_MUTED, muted: true })`
54
+ * - `game.emit(COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, { paused: true })` or `.setPaused(true)`
55
+ * Mute applies when `SoundSystem` is registered; otherwise the desired value is remembered until it appears.
56
+ * Both emit / post `COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED` with `{ paused, muted }`.
57
+ *
45
58
  * While enabled: `game.emit(COMBOS_DEVELOPMENT_TOOL_REFRESH)`, `window` event `combos-development-tool:refresh`,
46
59
  * or `postMessage({ type: 'combos-development-tool:refresh' })` to re-bind after adding/removing objects.
47
60
  */
@@ -53,22 +66,39 @@ declare class CombosDevelopmentToolSystem extends System<CombosDevelopmentToolSy
53
66
  private selected;
54
67
  private readonly tapHandlers;
55
68
  private readonly tapOwners;
56
- /** Game `Event` components removed while enabled; restored on disable. */
57
- private readonly cachedGameEvents;
69
+ /** Game `Event` hit targets soft-disabled while enabled (`container.interactive = false`). */
70
+ private readonly disabledGameEventGoIds;
58
71
  /** Pick `Event` injected for {@link CombosDevelopmentToolTarget} nodes. */
59
72
  private readonly pickEvents;
60
73
  private needsRescan;
61
74
  private lastOutlineBounds;
75
+ /** Remembered mute when `SoundSystem` is not registered yet. */
76
+ private mutedWithoutSoundSystem;
62
77
  private readonly onWindowSet;
78
+ private readonly onWindowSetPaused;
79
+ private readonly onWindowSetMuted;
63
80
  private readonly onWindowMessage;
64
81
  private readonly onGameSet;
65
82
  private readonly onGameRefresh;
83
+ private readonly onGameSetPaused;
84
+ private readonly onGameSetMuted;
66
85
  private readonly onWindowRefresh;
67
86
  init(params?: CombosDevelopmentToolSystemParams): void;
68
87
  onDestroy(): void;
69
88
  /** Programmatic toggle (same effect as events). */
70
89
  setEnabled(on: boolean): void;
71
90
  get isEnabled(): boolean;
91
+ /** Whether the game loop is paused (`!game.playing`). */
92
+ get isPaused(): boolean;
93
+ /** Master mute when `SoundSystem` exists; otherwise the last requested value. */
94
+ get isMuted(): boolean;
95
+ /** Pause or resume the game loop (same as `game.pause()` / `game.resume()`). */
96
+ setPaused(paused: boolean): void;
97
+ /**
98
+ * Mute or unmute audio via `SoundSystem` when registered.
99
+ * No-op on the audio graph if `SoundSystem` is missing; value is remembered for `isMuted`.
100
+ */
101
+ setMuted(muted: boolean): void;
72
102
  update(e: UpdateParams): void;
73
103
  componentChanged(changed: ComponentChanged): void;
74
104
  /** Re-bind pick targets after dynamic scene changes while enabled. */
@@ -77,7 +107,7 @@ declare class CombosDevelopmentToolSystem extends System<CombosDevelopmentToolSy
77
107
  private collectGameObjects;
78
108
  private isIgnoredPickGo;
79
109
  private stripGameEvent;
80
- private restoreCachedGameEvents;
110
+ private restoreDisabledGameEvents;
81
111
  private detachAllPicks;
82
112
  private ensurePick;
83
113
  private createPickEvent;
@@ -91,6 +121,8 @@ declare class CombosDevelopmentToolSystem extends System<CombosDevelopmentToolSy
91
121
  private getRendererContainer;
92
122
  private releasePick;
93
123
  private postSetSuccess;
124
+ private postStateChanged;
125
+ private getSoundSystem;
94
126
  private ensureOutline;
95
127
  private onSelect;
96
128
  private findGameObjectById;
@@ -136,5 +168,5 @@ declare function readPropertyValue(go: GameObject, componentName: string, path:
136
168
 
137
169
  declare function applyPropertyWithHooks(go: GameObject, componentName: string, path: string[], value: unknown): boolean;
138
170
 
139
- 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 };
171
+ 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_MUTED, COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS, COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED, CombosDevelopmentToolSystem, CombosDevelopmentToolTarget, applyPropertyValue, applyPropertyWithHooks, buildGameObjectSnapshot, readPropertyValue, readSourceAnchor };
140
172
  export type { CombosDevelopmentToolSystemParams, CombosDevelopmentToolTargetParams, SceneEditComponentSnapshot, SceneEditGameObjectSnapshot, SceneEditPropertyRef, SceneSourceAnchor };
@@ -16,6 +16,12 @@ const COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED = 'combos-development-tool:gam
16
16
  const COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY = 'combos-development-tool:apply-property';
17
17
  /** iframe → parent: game scene bootstrap finished; parent may enable pick mode. */
18
18
  const COMBOS_DEVELOPMENT_TOOL_READY = 'combos-development-tool:ready';
19
+ /** Parent → iframe: pause or resume the game loop. Payload: `{ paused: boolean }`. */
20
+ const COMBOS_DEVELOPMENT_TOOL_SET_PAUSED = 'combos-development-tool:set-paused';
21
+ /** Parent → iframe: mute or unmute audio when `SoundSystem` is registered. Payload: `{ muted: boolean }`. */
22
+ const COMBOS_DEVELOPMENT_TOOL_SET_MUTED = 'combos-development-tool:set-muted';
23
+ /** iframe → parent (and `game.emit`): current pause/mute snapshot after a successful change. */
24
+ const COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED = 'combos-development-tool:state-changed';
19
25
 
20
26
  /**
21
27
  * Marks a `GameObject` as selectable in editor pick mode. While the development tool is enabled,
@@ -274,7 +280,7 @@ function applyPropertyWithHooks(go, componentName, path, value) {
274
280
  const OUTLINE_GO_NAME = '__combosDevelopmentToolOutline';
275
281
  /**
276
282
  * **Off** at start. While enabled:
277
- * - strips `Event` from every scene `GameObject` (cached for restore on disable);
283
+ * - soft-disables game `Event` hit targets (`container.interactive = false`, restored on disable);
278
284
  * - attaches pick `Event` + outline only on nodes with {@link CombosDevelopmentToolTarget}.
279
285
  *
280
286
  * Turn on/off via:
@@ -282,6 +288,13 @@ const OUTLINE_GO_NAME = '__combosDevelopmentToolOutline';
282
288
  * - `window.postMessage({ type: COMBOS_DEVELOPMENT_TOOL_SET, enabled: true }, targetOrigin)` (e.g. from parent iframe)
283
289
  * - `game.emit(COMBOS_DEVELOPMENT_TOOL_SET, { enabled: true })` or `getSystem(CombosDevelopmentToolSystem).setEnabled(true)`
284
290
  *
291
+ * Pause / mute (independent of pick mode; parent toolbar or in-game debug UI):
292
+ * - `postMessage({ type: COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, paused: true })`
293
+ * - `postMessage({ type: COMBOS_DEVELOPMENT_TOOL_SET_MUTED, muted: true })`
294
+ * - `game.emit(COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, { paused: true })` or `.setPaused(true)`
295
+ * Mute applies when `SoundSystem` is registered; otherwise the desired value is remembered until it appears.
296
+ * Both emit / post `COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED` with `{ paused, muted }`.
297
+ *
285
298
  * While enabled: `game.emit(COMBOS_DEVELOPMENT_TOOL_REFRESH)`, `window` event `combos-development-tool:refresh`,
286
299
  * or `postMessage({ type: 'combos-development-tool:refresh' })` to re-bind after adding/removing objects.
287
300
  */
@@ -294,18 +307,32 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
294
307
  this.selected = null;
295
308
  this.tapHandlers = new Map();
296
309
  this.tapOwners = new Map();
297
- /** Game `Event` components removed while enabled; restored on disable. */
298
- this.cachedGameEvents = new Map();
310
+ /** Game `Event` hit targets soft-disabled while enabled (`container.interactive = false`). */
311
+ this.disabledGameEventGoIds = new Set();
299
312
  /** Pick `Event` injected for {@link CombosDevelopmentToolTarget} nodes. */
300
313
  this.pickEvents = new Set();
301
314
  this.needsRescan = false;
302
315
  this.lastOutlineBounds = null;
316
+ /** Remembered mute when `SoundSystem` is not registered yet. */
317
+ this.mutedWithoutSoundSystem = false;
303
318
  this.onWindowSet = (e) => {
304
319
  const d = e.detail;
305
320
  if (d && typeof d.enabled === 'boolean') {
306
321
  this.setEnabled(d.enabled);
307
322
  }
308
323
  };
324
+ this.onWindowSetPaused = (e) => {
325
+ const d = e.detail;
326
+ if (d && typeof d.paused === 'boolean') {
327
+ this.setPaused(d.paused);
328
+ }
329
+ };
330
+ this.onWindowSetMuted = (e) => {
331
+ const d = e.detail;
332
+ if (d && typeof d.muted === 'boolean') {
333
+ this.setMuted(d.muted);
334
+ }
335
+ };
309
336
  this.onWindowMessage = (e) => {
310
337
  const d = e.data;
311
338
  if (!d || typeof d !== 'object')
@@ -313,6 +340,12 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
313
340
  if (d.type === COMBOS_DEVELOPMENT_TOOL_SET && typeof d.enabled === 'boolean') {
314
341
  this.setEnabled(d.enabled);
315
342
  }
343
+ else if (d.type === COMBOS_DEVELOPMENT_TOOL_SET_PAUSED && typeof d.paused === 'boolean') {
344
+ this.setPaused(d.paused);
345
+ }
346
+ else if (d.type === COMBOS_DEVELOPMENT_TOOL_SET_MUTED && typeof d.muted === 'boolean') {
347
+ this.setMuted(d.muted);
348
+ }
316
349
  else if (d.type === COMBOS_DEVELOPMENT_TOOL_REFRESH) {
317
350
  this.requestSceneRescan();
318
351
  }
@@ -328,6 +361,16 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
328
361
  this.onGameRefresh = () => {
329
362
  this.requestSceneRescan();
330
363
  };
364
+ this.onGameSetPaused = (payload) => {
365
+ if (payload && typeof payload.paused === 'boolean') {
366
+ this.setPaused(payload.paused);
367
+ }
368
+ };
369
+ this.onGameSetMuted = (payload) => {
370
+ if (payload && typeof payload.muted === 'boolean') {
371
+ this.setMuted(payload.muted);
372
+ }
373
+ };
331
374
  this.onWindowRefresh = () => {
332
375
  this.requestSceneRescan();
333
376
  };
@@ -337,10 +380,14 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
337
380
  this.postMessageOrigin = params?.postMessageOrigin ?? '*';
338
381
  if (typeof window !== 'undefined') {
339
382
  window.addEventListener(COMBOS_DEVELOPMENT_TOOL_SET, this.onWindowSet);
383
+ window.addEventListener(COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, this.onWindowSetPaused);
384
+ window.addEventListener(COMBOS_DEVELOPMENT_TOOL_SET_MUTED, this.onWindowSetMuted);
340
385
  window.addEventListener(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onWindowRefresh);
341
386
  window.addEventListener('message', this.onWindowMessage);
342
387
  }
343
388
  this.game.on(COMBOS_DEVELOPMENT_TOOL_SET, this.onGameSet);
389
+ this.game.on(COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, this.onGameSetPaused);
390
+ this.game.on(COMBOS_DEVELOPMENT_TOOL_SET_MUTED, this.onGameSetMuted);
344
391
  this.game.on(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onGameRefresh);
345
392
  if (this.enabled) {
346
393
  this.needsRescan = true;
@@ -349,13 +396,17 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
349
396
  onDestroy() {
350
397
  if (typeof window !== 'undefined') {
351
398
  window.removeEventListener(COMBOS_DEVELOPMENT_TOOL_SET, this.onWindowSet);
399
+ window.removeEventListener(COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, this.onWindowSetPaused);
400
+ window.removeEventListener(COMBOS_DEVELOPMENT_TOOL_SET_MUTED, this.onWindowSetMuted);
352
401
  window.removeEventListener(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onWindowRefresh);
353
402
  window.removeEventListener('message', this.onWindowMessage);
354
403
  }
355
404
  this.game.off(COMBOS_DEVELOPMENT_TOOL_SET, this.onGameSet);
405
+ this.game.off(COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, this.onGameSetPaused);
406
+ this.game.off(COMBOS_DEVELOPMENT_TOOL_SET_MUTED, this.onGameSetMuted);
356
407
  this.game.off(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onGameRefresh);
357
408
  this.detachAllPicks();
358
- this.restoreCachedGameEvents();
409
+ this.restoreDisabledGameEvents();
359
410
  this.clearSelection();
360
411
  }
361
412
  /** Programmatic toggle (same effect as events). */
@@ -366,7 +417,7 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
366
417
  if (!on) {
367
418
  this.clearSelection();
368
419
  this.detachAllPicks();
369
- this.restoreCachedGameEvents();
420
+ this.restoreDisabledGameEvents();
370
421
  this.postSetSuccess(false);
371
422
  }
372
423
  else {
@@ -376,6 +427,44 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
376
427
  get isEnabled() {
377
428
  return this.enabled;
378
429
  }
430
+ /** Whether the game loop is paused (`!game.playing`). */
431
+ get isPaused() {
432
+ return !this.game.playing;
433
+ }
434
+ /** Master mute when `SoundSystem` exists; otherwise the last requested value. */
435
+ get isMuted() {
436
+ const sound = this.getSoundSystem();
437
+ if (sound) {
438
+ return sound.muted;
439
+ }
440
+ return this.mutedWithoutSoundSystem;
441
+ }
442
+ /** Pause or resume the game loop (same as `game.pause()` / `game.resume()`). */
443
+ setPaused(paused) {
444
+ if (paused) {
445
+ if (this.game.playing) {
446
+ this.game.pause();
447
+ }
448
+ }
449
+ else if (!this.game.playing) {
450
+ this.game.resume();
451
+ }
452
+ this.postStateChanged();
453
+ }
454
+ /**
455
+ * Mute or unmute audio via `SoundSystem` when registered.
456
+ * No-op on the audio graph if `SoundSystem` is missing; value is remembered for `isMuted`.
457
+ */
458
+ setMuted(muted) {
459
+ const sound = this.getSoundSystem();
460
+ if (sound) {
461
+ sound.muted = muted;
462
+ }
463
+ else {
464
+ this.mutedWithoutSoundSystem = muted;
465
+ }
466
+ this.postStateChanged();
467
+ }
379
468
  update(e) {
380
469
  if (this.enabled && this.needsRescan) {
381
470
  this.needsRescan = false;
@@ -443,33 +532,39 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
443
532
  return go.name === OUTLINE_GO_NAME || go === this.outlineGo;
444
533
  }
445
534
  stripGameEvent(go) {
446
- if (this.cachedGameEvents.has(go.id))
535
+ if (this.disabledGameEventGoIds.has(go.id))
447
536
  return;
448
537
  const ev = go.getComponent(Event);
449
538
  if (!ev)
450
539
  return;
540
+ const container = this.getRendererContainer(go);
541
+ if (!container)
542
+ return;
451
543
  try {
452
- const removed = go.removeComponent(Event);
453
- this.cachedGameEvents.set(go.id, removed);
544
+ container.interactive = false;
545
+ this.disabledGameEventGoIds.add(go.id);
454
546
  }
455
547
  catch {
456
548
  /* ignore */
457
549
  }
458
550
  }
459
- restoreCachedGameEvents() {
460
- for (const [id, event] of [...this.cachedGameEvents.entries()]) {
551
+ restoreDisabledGameEvents() {
552
+ for (const id of [...this.disabledGameEventGoIds]) {
461
553
  const go = this.findGameObjectById(id);
462
- if (!go || go.destroyed || go.getComponent(Event)) {
463
- this.cachedGameEvents.delete(id);
554
+ if (!go || go.destroyed) {
555
+ this.disabledGameEventGoIds.delete(id);
464
556
  continue;
465
557
  }
466
- try {
467
- go.addComponent(event);
468
- }
469
- catch {
470
- /* ignore */
558
+ const container = this.getRendererContainer(go);
559
+ if (container) {
560
+ try {
561
+ container.interactive = true;
562
+ }
563
+ catch {
564
+ /* ignore */
565
+ }
471
566
  }
472
- this.cachedGameEvents.delete(id);
567
+ this.disabledGameEventGoIds.delete(id);
473
568
  }
474
569
  }
475
570
  detachAllPicks() {
@@ -480,6 +575,15 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
480
575
  ensurePick(go) {
481
576
  if (this.tapHandlers.has(go.id))
482
577
  return;
578
+ const container = this.getRendererContainer(go);
579
+ if (container) {
580
+ try {
581
+ container.interactive = true;
582
+ }
583
+ catch {
584
+ /* ignore */
585
+ }
586
+ }
483
587
  let ev = go.getComponent(Event);
484
588
  if (!ev) {
485
589
  ev = go.addComponent(this.createPickEvent(go));
@@ -629,6 +733,30 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
629
733
  }
630
734
  this.game.emit(COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS, { enabled });
631
735
  }
736
+ postStateChanged() {
737
+ const state = {
738
+ paused: this.isPaused,
739
+ muted: this.isMuted,
740
+ };
741
+ const payload = {
742
+ type: COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED,
743
+ ...state,
744
+ };
745
+ if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
746
+ window.parent.postMessage(payload, this.postMessageOrigin);
747
+ }
748
+ this.game.emit(COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED, state);
749
+ }
750
+ getSoundSystem() {
751
+ const system = this.game.getSystem('SoundSystem');
752
+ if (!system ||
753
+ typeof system !== 'object' ||
754
+ !('muted' in system) ||
755
+ typeof system.muted !== 'boolean') {
756
+ return null;
757
+ }
758
+ return system;
759
+ }
632
760
  ensureOutline() {
633
761
  if (this.outlineGo)
634
762
  return;
@@ -790,8 +918,8 @@ var CombosDevelopmentToolSystem$1 = CombosDevelopmentToolSystem;
790
918
  /** Auto-generated by scripts/build-package.mjs — do not edit. */
791
919
  Object.assign(CombosDevelopmentToolSystem$1, {
792
920
  packageName: "@combos-fun/plugin-development-tool",
793
- packageVersion: "0.0.20",
921
+ packageVersion: "0.0.22",
794
922
  });
795
923
 
796
- 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 };
924
+ 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_MUTED, COMBOS_DEVELOPMENT_TOOL_SET_PAUSED, COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS, COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED, CombosDevelopmentToolSystem$1 as CombosDevelopmentToolSystem, CombosDevelopmentToolTarget, applyPropertyValue, applyPropertyWithHooks, buildGameObjectSnapshot, readPropertyValue, readSourceAnchor };
797
925
  //# sourceMappingURL=plugin-development-tool.esm.js.map