@combos-fun/plugin-development-tool 0.0.27 → 0.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-skill.md +24 -0
- package/dist/plugin-development-tool.cjs.js +246 -6
- package/dist/plugin-development-tool.cjs.js.map +1 -1
- package/dist/plugin-development-tool.cjs.prod.js +1 -1
- package/dist/plugin-development-tool.d.ts +102 -4
- package/dist/plugin-development-tool.esm.js +241 -7
- package/dist/plugin-development-tool.esm.js.map +1 -1
- package/package.json +5 -5
package/agent-skill.md
CHANGED
|
@@ -78,8 +78,32 @@ Outbound `postMessageOrigin` is separate — it limits which parent origin recei
|
|
|
78
78
|
| parent → iframe | `combos-development-tool:set` | `{ enabled: boolean }` | Enable/disable pick mode |
|
|
79
79
|
| parent → iframe | `combos-development-tool:clear-selection` | `{}` | Clear in-canvas outline |
|
|
80
80
|
| parent → iframe | `combos-development-tool:apply-property` | component field mutation | Live preview |
|
|
81
|
+
| parent → iframe | `combos-development-tool:set-marker-overlay` | `{ enabled: boolean }` | Toggle the marker overlay (independent of pick mode) |
|
|
81
82
|
| iframe → parent | `combos-development-tool:gameobject-selected` | `{ snapshot, pointer }` | Object picked |
|
|
82
83
|
| iframe → parent | `combos-development-tool:gameobject-deselected` | `{ reason }` | Selection cleared (`parent-request`, `pick-disabled`, `target-removed`) |
|
|
84
|
+
| iframe → parent | `combos-development-tool:marker-overlay-success` | `{ enabled, total, markers: { componentName, count }[] }` | Marker overlay finished (re)building |
|
|
85
|
+
|
|
86
|
+
## Marker overlay (surface invisible components)
|
|
87
|
+
|
|
88
|
+
A reusable "pin a persistent icon on every object owning an otherwise invisible
|
|
89
|
+
component" layer. Registry-driven (`markerLayer.ts` → `MARKER_COMPONENTS`).
|
|
90
|
+
**For now it is `Sound` only** — the mechanism is generic (append `Physics` / `Camera` /
|
|
91
|
+
triggers / spawn points later) but nothing else is registered yet.
|
|
92
|
+
|
|
93
|
+
- Independent toggle, orthogonal to pick mode and mute: `setMarkerOverlay(true)` or
|
|
94
|
+
`postMessage({ type: 'combos-development-tool:set-marker-overlay', enabled: true })`
|
|
95
|
+
(also `window` CustomEvent / `game.emit`).
|
|
96
|
+
- Draws the icon **in-engine** (a `Graphics` child GO pinned to the owner, so it
|
|
97
|
+
follows the object). The layer is **purely visual** — it does not wire up its own
|
|
98
|
+
selection. Because the icon adds to the owner's rendered bounds, the owner's own
|
|
99
|
+
`CombosDevelopmentToolTarget` pick gets a clickable hit area, so selecting and
|
|
100
|
+
editing (e.g. `Sound.config.volume`) go through the normal
|
|
101
|
+
selection → snapshot → `apply-property` flow and **persist to source** like any
|
|
102
|
+
other scene edit. **The marked object must therefore carry a
|
|
103
|
+
`CombosDevelopmentToolTarget`** (added by the game code — see the game template's
|
|
104
|
+
Scene Edit rules; objects with a `Sound` component must be given a Target even
|
|
105
|
+
when they render nothing).
|
|
106
|
+
- On (re)build it posts `combos-development-tool:marker-overlay-success` with per-component counts.
|
|
83
107
|
|
|
84
108
|
## Verification
|
|
85
109
|
|
|
@@ -31,6 +31,18 @@ const COMBOS_DEVELOPMENT_TOOL_READY = 'combos-development-tool:ready';
|
|
|
31
31
|
const COMBOS_DEVELOPMENT_TOOL_SET_MUTED = 'combos-development-tool:set-muted';
|
|
32
32
|
/** iframe → parent (and `game.emit`): current mute snapshot after a successful change. */
|
|
33
33
|
const COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED = 'combos-development-tool:state-changed';
|
|
34
|
+
/**
|
|
35
|
+
* Parent → iframe (also `window` CustomEvent / `game.emit`): toggle the marker
|
|
36
|
+
* overlay — a persistent, clickable icon on every object owning an otherwise
|
|
37
|
+
* invisible registered component (Sound first). Independent of pick mode and
|
|
38
|
+
* mute. Payload: `{ enabled: boolean }`.
|
|
39
|
+
*/
|
|
40
|
+
const COMBOS_DEVELOPMENT_TOOL_SET_MARKER_OVERLAY = 'combos-development-tool:set-marker-overlay';
|
|
41
|
+
/**
|
|
42
|
+
* iframe → parent (and `game.emit`): marker overlay finished (re)building.
|
|
43
|
+
* Payload: `{ enabled: boolean, total: number, markers: { componentName, count }[] }`.
|
|
44
|
+
*/
|
|
45
|
+
const COMBOS_DEVELOPMENT_TOOL_MARKER_OVERLAY_SUCCESS = 'combos-development-tool:marker-overlay-success';
|
|
34
46
|
|
|
35
47
|
/**
|
|
36
48
|
* Marks a `GameObject` as selectable in editor pick mode. While the development tool is enabled,
|
|
@@ -48,6 +60,73 @@ class CombosDevelopmentToolTarget extends engine.Component {
|
|
|
48
60
|
}
|
|
49
61
|
}
|
|
50
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Registered marker kinds, in priority order: a GameObject is marked by the
|
|
65
|
+
* first registered component it owns. For now this is **`Sound` only**; the
|
|
66
|
+
* mechanism is generic (append Physics / Camera / triggers / spawn points later
|
|
67
|
+
* to reuse the same layer) but only audio is wanted right now.
|
|
68
|
+
*/
|
|
69
|
+
const MARKER_COMPONENTS = [
|
|
70
|
+
{ componentName: 'Sound', badgeColor: 0x8b5cf6, glyph: 'speaker' },
|
|
71
|
+
];
|
|
72
|
+
/** Fixed badge size in the owner's local space. */
|
|
73
|
+
const MARKER_ICON_SIZE = 28;
|
|
74
|
+
/**
|
|
75
|
+
* First registered marker def whose component is present on `go`, else `null`.
|
|
76
|
+
* Priority follows {@link MARKER_COMPONENTS} order.
|
|
77
|
+
*/
|
|
78
|
+
function resolveMarkerDef(go, registry = MARKER_COMPONENTS) {
|
|
79
|
+
for (const def of registry) {
|
|
80
|
+
if (go.getComponent(def.componentName)) {
|
|
81
|
+
return def;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const GLYPH_COLOR = 0xffffff;
|
|
87
|
+
/** Draw the rounded badge background shared by every glyph. */
|
|
88
|
+
function drawBadge(g, def, size) {
|
|
89
|
+
g.clear();
|
|
90
|
+
g.roundRect(0, 0, size, size, size * 0.22);
|
|
91
|
+
g.fill({ color: def.badgeColor, alpha: 0.92 });
|
|
92
|
+
g.roundRect(0, 0, size, size, size * 0.22);
|
|
93
|
+
g.stroke({ width: Math.max(1, size * 0.05), color: 0xffffff, alpha: 0.6 });
|
|
94
|
+
}
|
|
95
|
+
/** A speaker cone + two volume bars, normalized to the `size` box. */
|
|
96
|
+
function drawSpeakerGlyph(g, s) {
|
|
97
|
+
g.poly([
|
|
98
|
+
s * 0.28, s * 0.4,
|
|
99
|
+
s * 0.42, s * 0.4,
|
|
100
|
+
s * 0.55, s * 0.26,
|
|
101
|
+
s * 0.55, s * 0.74,
|
|
102
|
+
s * 0.42, s * 0.6,
|
|
103
|
+
s * 0.28, s * 0.6,
|
|
104
|
+
]);
|
|
105
|
+
g.fill({ color: GLYPH_COLOR, alpha: 0.96 });
|
|
106
|
+
g.rect(s * 0.62, s * 0.44, s * 0.045, s * 0.12);
|
|
107
|
+
g.fill({ color: GLYPH_COLOR, alpha: 0.96 });
|
|
108
|
+
g.rect(s * 0.71, s * 0.39, s * 0.045, s * 0.22);
|
|
109
|
+
g.fill({ color: GLYPH_COLOR, alpha: 0.96 });
|
|
110
|
+
}
|
|
111
|
+
/** Generic fallback glyph for component kinds without a dedicated icon. */
|
|
112
|
+
function drawDotGlyph(g, s) {
|
|
113
|
+
g.circle(s * 0.5, s * 0.5, s * 0.18);
|
|
114
|
+
g.fill({ color: GLYPH_COLOR, alpha: 0.96 });
|
|
115
|
+
}
|
|
116
|
+
/** Render a full marker (badge + glyph) into `g`, sized to `size` (local units). */
|
|
117
|
+
function drawMarkerIcon(g, def, size = MARKER_ICON_SIZE) {
|
|
118
|
+
drawBadge(g, def, size);
|
|
119
|
+
switch (def.glyph) {
|
|
120
|
+
case 'speaker':
|
|
121
|
+
drawSpeakerGlyph(g, size);
|
|
122
|
+
break;
|
|
123
|
+
case 'dot':
|
|
124
|
+
default:
|
|
125
|
+
drawDotGlyph(g, size);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
51
130
|
/** Default inbound postMessage host suffixes (host + all subdomains). */
|
|
52
131
|
const DEFAULT_ALLOWED_MESSAGE_HOST_SUFFIXES = [
|
|
53
132
|
'knoffice.tech',
|
|
@@ -371,6 +450,7 @@ function isClearSelectionMessage(data) {
|
|
|
371
450
|
}
|
|
372
451
|
|
|
373
452
|
const OUTLINE_GO_NAME = '__combosDevelopmentToolOutline';
|
|
453
|
+
const MARKER_GO_NAME_PREFIX = '__combosDevelopmentToolMarker:';
|
|
374
454
|
/**
|
|
375
455
|
* **Off** at start. While enabled:
|
|
376
456
|
* - soft-disables game `Event` hit targets (`container.interactive = false`, restored on disable);
|
|
@@ -411,6 +491,18 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
411
491
|
this.lastOutlineBounds = null;
|
|
412
492
|
/** Remembered mute when `SoundSystem` is not registered yet. */
|
|
413
493
|
this.mutedWithoutSoundSystem = false;
|
|
494
|
+
/**
|
|
495
|
+
* Marker overlay (see {@link markerLayer}): a visual-only icon layer, toggled
|
|
496
|
+
* independently of pick mode + mute. Selection/persistence are NOT handled here
|
|
497
|
+
* — a marked object (e.g. Sound) carries its own `CombosDevelopmentToolTarget`
|
|
498
|
+
* (added by the game code), so it is picked and serialized through the normal
|
|
499
|
+
* Target path. The icon just makes the invisible object visible and, by adding
|
|
500
|
+
* to the owner's rendered bounds, gives its Target pick a clickable hit area.
|
|
501
|
+
*/
|
|
502
|
+
this.markerOverlayEnabled = false;
|
|
503
|
+
this.needsMarkerRescan = false;
|
|
504
|
+
/** ownerGoId → its marker GO (icon child, Graphics only). */
|
|
505
|
+
this.markerGoByOwner = new Map();
|
|
414
506
|
this.onWindowSet = (e) => {
|
|
415
507
|
const d = e.detail;
|
|
416
508
|
if (d && typeof d.enabled === 'boolean') {
|
|
@@ -423,6 +515,17 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
423
515
|
this.setMuted(d.muted);
|
|
424
516
|
}
|
|
425
517
|
};
|
|
518
|
+
this.onWindowSetMarkerOverlay = (e) => {
|
|
519
|
+
const d = e.detail;
|
|
520
|
+
if (d && typeof d.enabled === 'boolean') {
|
|
521
|
+
this.setMarkerOverlay(d.enabled);
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
this.onGameSetMarkerOverlay = (payload) => {
|
|
525
|
+
if (payload && typeof payload.enabled === 'boolean') {
|
|
526
|
+
this.setMarkerOverlay(payload.enabled);
|
|
527
|
+
}
|
|
528
|
+
};
|
|
426
529
|
this.onWindowMessage = (e) => {
|
|
427
530
|
if (!isAllowedMessageOrigin(e.origin, this.allowedMessageOrigins)) {
|
|
428
531
|
return;
|
|
@@ -436,6 +539,10 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
436
539
|
else if (d.type === COMBOS_DEVELOPMENT_TOOL_SET_MUTED && typeof d.muted === 'boolean') {
|
|
437
540
|
this.setMuted(d.muted);
|
|
438
541
|
}
|
|
542
|
+
else if (d.type === COMBOS_DEVELOPMENT_TOOL_SET_MARKER_OVERLAY &&
|
|
543
|
+
typeof d.enabled === 'boolean') {
|
|
544
|
+
this.setMarkerOverlay(d.enabled);
|
|
545
|
+
}
|
|
439
546
|
else if (d.type === COMBOS_DEVELOPMENT_TOOL_REFRESH) {
|
|
440
547
|
this.requestSceneRescan();
|
|
441
548
|
}
|
|
@@ -470,11 +577,13 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
470
577
|
if (typeof window !== 'undefined') {
|
|
471
578
|
window.addEventListener(COMBOS_DEVELOPMENT_TOOL_SET, this.onWindowSet);
|
|
472
579
|
window.addEventListener(COMBOS_DEVELOPMENT_TOOL_SET_MUTED, this.onWindowSetMuted);
|
|
580
|
+
window.addEventListener(COMBOS_DEVELOPMENT_TOOL_SET_MARKER_OVERLAY, this.onWindowSetMarkerOverlay);
|
|
473
581
|
window.addEventListener(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onWindowRefresh);
|
|
474
582
|
window.addEventListener('message', this.onWindowMessage);
|
|
475
583
|
}
|
|
476
584
|
this.game.on(COMBOS_DEVELOPMENT_TOOL_SET, this.onGameSet);
|
|
477
585
|
this.game.on(COMBOS_DEVELOPMENT_TOOL_SET_MUTED, this.onGameSetMuted);
|
|
586
|
+
this.game.on(COMBOS_DEVELOPMENT_TOOL_SET_MARKER_OVERLAY, this.onGameSetMarkerOverlay);
|
|
478
587
|
this.game.on(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onGameRefresh);
|
|
479
588
|
if (this.enabled) {
|
|
480
589
|
this.needsRescan = true;
|
|
@@ -484,13 +593,16 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
484
593
|
if (typeof window !== 'undefined') {
|
|
485
594
|
window.removeEventListener(COMBOS_DEVELOPMENT_TOOL_SET, this.onWindowSet);
|
|
486
595
|
window.removeEventListener(COMBOS_DEVELOPMENT_TOOL_SET_MUTED, this.onWindowSetMuted);
|
|
596
|
+
window.removeEventListener(COMBOS_DEVELOPMENT_TOOL_SET_MARKER_OVERLAY, this.onWindowSetMarkerOverlay);
|
|
487
597
|
window.removeEventListener(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onWindowRefresh);
|
|
488
598
|
window.removeEventListener('message', this.onWindowMessage);
|
|
489
599
|
}
|
|
490
600
|
this.game.off(COMBOS_DEVELOPMENT_TOOL_SET, this.onGameSet);
|
|
491
601
|
this.game.off(COMBOS_DEVELOPMENT_TOOL_SET_MUTED, this.onGameSetMuted);
|
|
602
|
+
this.game.off(COMBOS_DEVELOPMENT_TOOL_SET_MARKER_OVERLAY, this.onGameSetMarkerOverlay);
|
|
492
603
|
this.game.off(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onGameRefresh);
|
|
493
604
|
this.detachAllPicks();
|
|
605
|
+
this.detachAllMarkers();
|
|
494
606
|
this.restoreDisabledGameEvents();
|
|
495
607
|
this.clearSelectionAndNotify('pick-disabled');
|
|
496
608
|
}
|
|
@@ -512,6 +624,35 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
512
624
|
get isEnabled() {
|
|
513
625
|
return this.enabled;
|
|
514
626
|
}
|
|
627
|
+
/**
|
|
628
|
+
* Toggle the marker overlay: pin a persistent icon on every object that owns a
|
|
629
|
+
* registered invisible component ({@link markerLayer}, Sound first). Independent
|
|
630
|
+
* of pick mode / mute. This layer is purely visual — the icon makes the object
|
|
631
|
+
* visible and adds to its rendered bounds so the owner's own
|
|
632
|
+
* `CombosDevelopmentToolTarget` pick gets a clickable hit area. Selecting and
|
|
633
|
+
* persisting edits (e.g. volume) still go through that Target, exactly like any
|
|
634
|
+
* other scene edit, so the object must carry a Target (added by the game code).
|
|
635
|
+
*/
|
|
636
|
+
setMarkerOverlay(on) {
|
|
637
|
+
if (this.markerOverlayEnabled === on)
|
|
638
|
+
return;
|
|
639
|
+
this.markerOverlayEnabled = on;
|
|
640
|
+
if (on) {
|
|
641
|
+
// `attachMarkers` requests the pick rescan itself, once the icons exist.
|
|
642
|
+
this.needsMarkerRescan = true;
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
this.detachAllMarkers();
|
|
646
|
+
this.postMarkerOverlaySuccess(false, []);
|
|
647
|
+
// Shrink owners' pick hit areas back now that the icons are gone.
|
|
648
|
+
if (this.enabled) {
|
|
649
|
+
this.needsRescan = true;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
get isMarkerOverlayEnabled() {
|
|
654
|
+
return this.markerOverlayEnabled;
|
|
655
|
+
}
|
|
515
656
|
/** Master mute when `SoundSystem` exists; otherwise the last requested value. */
|
|
516
657
|
get isMuted() {
|
|
517
658
|
const sound = this.getSoundSystem();
|
|
@@ -540,11 +681,26 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
540
681
|
this.attachEditMode();
|
|
541
682
|
this.postSetSuccess(true);
|
|
542
683
|
}
|
|
684
|
+
// Attaching markers is deferred to run *after* the pick rescan above so that a
|
|
685
|
+
// newly drawn icon's rebuild lands on a later frame (see `attachMarkers`): the
|
|
686
|
+
// icon child needs a rendered container before it contributes to the owner's
|
|
687
|
+
// bounds, and only then does the owner's Target pick get a hit area over it.
|
|
688
|
+
if (this.markerOverlayEnabled && this.needsMarkerRescan) {
|
|
689
|
+
this.needsMarkerRescan = false;
|
|
690
|
+
this.attachMarkers();
|
|
691
|
+
}
|
|
543
692
|
for (const go of [...this.tapOwners.values()]) {
|
|
544
693
|
if (go.destroyed) {
|
|
545
694
|
this.releasePick(go);
|
|
546
695
|
}
|
|
547
696
|
}
|
|
697
|
+
// Drop markers whose owner disappeared while the overlay is on.
|
|
698
|
+
for (const [ownerId, marker] of [...this.markerGoByOwner.entries()]) {
|
|
699
|
+
const owner = this.findGameObjectById(ownerId);
|
|
700
|
+
if (!owner || owner.destroyed || marker.destroyed) {
|
|
701
|
+
this.removeMarker(ownerId);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
548
704
|
if (!this.enabled || !this.selected || !this.outlineGo)
|
|
549
705
|
return;
|
|
550
706
|
this.updateSelectionOutline();
|
|
@@ -566,11 +722,14 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
566
722
|
}
|
|
567
723
|
}
|
|
568
724
|
}
|
|
569
|
-
/** Re-bind pick targets after dynamic scene changes while
|
|
725
|
+
/** Re-bind pick targets / markers after dynamic scene changes while active. */
|
|
570
726
|
requestSceneRescan() {
|
|
571
|
-
if (
|
|
572
|
-
|
|
573
|
-
|
|
727
|
+
if (this.enabled) {
|
|
728
|
+
this.needsRescan = true;
|
|
729
|
+
}
|
|
730
|
+
if (this.markerOverlayEnabled) {
|
|
731
|
+
this.needsMarkerRescan = true;
|
|
732
|
+
}
|
|
574
733
|
}
|
|
575
734
|
attachEditMode() {
|
|
576
735
|
this.detachAllPicks();
|
|
@@ -598,7 +757,10 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
598
757
|
}
|
|
599
758
|
}
|
|
600
759
|
isIgnoredPickGo(go) {
|
|
601
|
-
return go.name === OUTLINE_GO_NAME || go === this.outlineGo;
|
|
760
|
+
return go.name === OUTLINE_GO_NAME || go === this.outlineGo || this.isMarkerGo(go);
|
|
761
|
+
}
|
|
762
|
+
isMarkerGo(go) {
|
|
763
|
+
return typeof go.name === 'string' && go.name.startsWith(MARKER_GO_NAME_PREFIX);
|
|
602
764
|
}
|
|
603
765
|
stripGameEvent(go) {
|
|
604
766
|
if (this.disabledGameEventGoIds.has(go.id))
|
|
@@ -815,6 +977,78 @@ let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends en
|
|
|
815
977
|
}
|
|
816
978
|
this.game.emit(COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED, state);
|
|
817
979
|
}
|
|
980
|
+
/** (Re)build markers for every object owning a registered marker component. */
|
|
981
|
+
attachMarkers() {
|
|
982
|
+
this.detachAllMarkers();
|
|
983
|
+
const list = [];
|
|
984
|
+
for (const tr of this.game.scene.transform.children) {
|
|
985
|
+
this.collectGameObjects(tr.gameObject, list);
|
|
986
|
+
}
|
|
987
|
+
const counts = new Map();
|
|
988
|
+
for (const go of list) {
|
|
989
|
+
if (this.isIgnoredPickGo(go))
|
|
990
|
+
continue;
|
|
991
|
+
const def = resolveMarkerDef(go);
|
|
992
|
+
if (!def)
|
|
993
|
+
continue;
|
|
994
|
+
this.createMarker(go, def);
|
|
995
|
+
counts.set(def.componentName, (counts.get(def.componentName) ?? 0) + 1);
|
|
996
|
+
}
|
|
997
|
+
const markers = [...counts.entries()].map(([componentName, count]) => ({
|
|
998
|
+
componentName,
|
|
999
|
+
count,
|
|
1000
|
+
}));
|
|
1001
|
+
this.postMarkerOverlaySuccess(true, markers);
|
|
1002
|
+
// Rebuild picks next frame: the icons just added need a rendered container
|
|
1003
|
+
// before they enlarge their owners' bounds into a clickable hit area. Runs on
|
|
1004
|
+
// a later frame because the pick rescan block already executed above.
|
|
1005
|
+
if (this.enabled) {
|
|
1006
|
+
this.needsRescan = true;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
createMarker(owner, def) {
|
|
1010
|
+
if (this.markerGoByOwner.has(owner.id))
|
|
1011
|
+
return;
|
|
1012
|
+
const bounds = this.resolvePickBounds(owner);
|
|
1013
|
+
const marker = new engine.GameObject(MARKER_GO_NAME_PREFIX + owner.id, {
|
|
1014
|
+
size: { width: MARKER_ICON_SIZE, height: MARKER_ICON_SIZE },
|
|
1015
|
+
position: { x: bounds.x, y: bounds.y },
|
|
1016
|
+
origin: { x: 0, y: 0 },
|
|
1017
|
+
});
|
|
1018
|
+
const gfx = marker.addComponent(new pluginRendererGraphics.Graphics());
|
|
1019
|
+
if (gfx?.graphics) {
|
|
1020
|
+
drawMarkerIcon(gfx.graphics, def, MARKER_ICON_SIZE);
|
|
1021
|
+
}
|
|
1022
|
+
owner.addChild(marker);
|
|
1023
|
+
this.markerGoByOwner.set(owner.id, marker);
|
|
1024
|
+
}
|
|
1025
|
+
removeMarker(ownerId) {
|
|
1026
|
+
const marker = this.markerGoByOwner.get(ownerId);
|
|
1027
|
+
if (!marker)
|
|
1028
|
+
return;
|
|
1029
|
+
this.markerGoByOwner.delete(ownerId);
|
|
1030
|
+
if (!marker.destroyed) {
|
|
1031
|
+
marker.destroy();
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
detachAllMarkers() {
|
|
1035
|
+
for (const ownerId of [...this.markerGoByOwner.keys()]) {
|
|
1036
|
+
this.removeMarker(ownerId);
|
|
1037
|
+
}
|
|
1038
|
+
this.markerGoByOwner.clear();
|
|
1039
|
+
}
|
|
1040
|
+
postMarkerOverlaySuccess(enabled, markers) {
|
|
1041
|
+
const total = markers.reduce((sum, m) => sum + m.count, 0);
|
|
1042
|
+
const state = { enabled, total, markers };
|
|
1043
|
+
const payload = {
|
|
1044
|
+
type: COMBOS_DEVELOPMENT_TOOL_MARKER_OVERLAY_SUCCESS,
|
|
1045
|
+
...state,
|
|
1046
|
+
};
|
|
1047
|
+
if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
|
|
1048
|
+
window.parent.postMessage(payload, this.postMessageOrigin);
|
|
1049
|
+
}
|
|
1050
|
+
this.game.emit(COMBOS_DEVELOPMENT_TOOL_MARKER_OVERLAY_SUCCESS, state);
|
|
1051
|
+
}
|
|
818
1052
|
getSoundSystem() {
|
|
819
1053
|
const system = this.game.getSystem('SoundSystem');
|
|
820
1054
|
if (!system ||
|
|
@@ -1001,30 +1235,36 @@ var CombosDevelopmentToolSystem = CombosDevelopmentToolSystem$1;
|
|
|
1001
1235
|
/** Auto-generated by scripts/build-package.mjs — do not edit. */
|
|
1002
1236
|
Object.assign(CombosDevelopmentToolSystem, {
|
|
1003
1237
|
packageName: "@combos-fun/plugin-development-tool",
|
|
1004
|
-
packageVersion: "0.0.
|
|
1238
|
+
packageVersion: "0.0.28",
|
|
1005
1239
|
});
|
|
1006
1240
|
|
|
1007
1241
|
exports.COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY = COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY;
|
|
1008
1242
|
exports.COMBOS_DEVELOPMENT_TOOL_CLEAR_SELECTION = COMBOS_DEVELOPMENT_TOOL_CLEAR_SELECTION;
|
|
1009
1243
|
exports.COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_DESELECTED = COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_DESELECTED;
|
|
1010
1244
|
exports.COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED = COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED;
|
|
1245
|
+
exports.COMBOS_DEVELOPMENT_TOOL_MARKER_OVERLAY_SUCCESS = COMBOS_DEVELOPMENT_TOOL_MARKER_OVERLAY_SUCCESS;
|
|
1011
1246
|
exports.COMBOS_DEVELOPMENT_TOOL_READY = COMBOS_DEVELOPMENT_TOOL_READY;
|
|
1012
1247
|
exports.COMBOS_DEVELOPMENT_TOOL_REFRESH = COMBOS_DEVELOPMENT_TOOL_REFRESH;
|
|
1013
1248
|
exports.COMBOS_DEVELOPMENT_TOOL_SET = COMBOS_DEVELOPMENT_TOOL_SET;
|
|
1249
|
+
exports.COMBOS_DEVELOPMENT_TOOL_SET_MARKER_OVERLAY = COMBOS_DEVELOPMENT_TOOL_SET_MARKER_OVERLAY;
|
|
1014
1250
|
exports.COMBOS_DEVELOPMENT_TOOL_SET_MUTED = COMBOS_DEVELOPMENT_TOOL_SET_MUTED;
|
|
1015
1251
|
exports.COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS = COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS;
|
|
1016
1252
|
exports.COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED = COMBOS_DEVELOPMENT_TOOL_STATE_CHANGED;
|
|
1017
1253
|
exports.CombosDevelopmentToolSystem = CombosDevelopmentToolSystem;
|
|
1018
1254
|
exports.CombosDevelopmentToolTarget = CombosDevelopmentToolTarget;
|
|
1019
1255
|
exports.DEFAULT_ALLOWED_MESSAGE_HOST_SUFFIXES = DEFAULT_ALLOWED_MESSAGE_HOST_SUFFIXES;
|
|
1256
|
+
exports.MARKER_COMPONENTS = MARKER_COMPONENTS;
|
|
1257
|
+
exports.MARKER_ICON_SIZE = MARKER_ICON_SIZE;
|
|
1020
1258
|
exports.applyPropertyValue = applyPropertyValue;
|
|
1021
1259
|
exports.applyPropertyWithHooks = applyPropertyWithHooks;
|
|
1022
1260
|
exports.buildGameObjectDeselectedPayload = buildGameObjectDeselectedPayload;
|
|
1023
1261
|
exports.buildGameObjectSnapshot = buildGameObjectSnapshot;
|
|
1262
|
+
exports.drawMarkerIcon = drawMarkerIcon;
|
|
1024
1263
|
exports.isAllowedMessageOrigin = isAllowedMessageOrigin;
|
|
1025
1264
|
exports.isClearSelectionMessage = isClearSelectionMessage;
|
|
1026
1265
|
exports.mergeAllowedMessageOrigins = mergeAllowedMessageOrigins;
|
|
1027
1266
|
exports.readPropertyValue = readPropertyValue;
|
|
1028
1267
|
exports.readSourceAnchor = readSourceAnchor;
|
|
1268
|
+
exports.resolveMarkerDef = resolveMarkerDef;
|
|
1029
1269
|
exports.shouldNotifyGameObjectDeselected = shouldNotifyGameObjectDeselected;
|
|
1030
1270
|
//# sourceMappingURL=plugin-development-tool.cjs.js.map
|