@combos-fun/plugin-development-tool 0.0.19 → 0.0.21
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/combos-plugin.json +2 -1
- package/dist/plugin-development-tool.cjs.js +180 -103
- 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 +38 -28
- package/dist/plugin-development-tool.esm.js +180 -104
- package/dist/plugin-development-tool.esm.js.map +1 -1
- package/package.json +5 -5
|
@@ -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
|
-
/**
|
|
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
|
-
*
|
|
20
|
-
*
|
|
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,33 @@ function applyPropertyWithHooks(go, componentName, path, value) {
|
|
|
270
273
|
|
|
271
274
|
const OUTLINE_GO_NAME = '__combosDevelopmentToolOutline';
|
|
272
275
|
/**
|
|
273
|
-
* **
|
|
274
|
-
*
|
|
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
|
-
*
|
|
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 `
|
|
293
|
-
this.
|
|
294
|
-
/**
|
|
295
|
-
this.
|
|
296
|
-
this.
|
|
297
|
-
this.
|
|
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;
|
|
302
|
+
this.lastOutlineBounds = null;
|
|
298
303
|
this.onWindowSet = (e) => {
|
|
299
304
|
const d = e.detail;
|
|
300
305
|
if (d && typeof d.enabled === 'boolean') {
|
|
@@ -330,7 +335,6 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
330
335
|
static { this.systemName = 'CombosDevelopmentToolSystem'; }
|
|
331
336
|
init(params) {
|
|
332
337
|
this.postMessageOrigin = params?.postMessageOrigin ?? '*';
|
|
333
|
-
this.scope = params?.scope ?? 'scene';
|
|
334
338
|
if (typeof window !== 'undefined') {
|
|
335
339
|
window.addEventListener(COMBOS_DEVELOPMENT_TOOL_SET, this.onWindowSet);
|
|
336
340
|
window.addEventListener(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onWindowRefresh);
|
|
@@ -338,11 +342,8 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
338
342
|
}
|
|
339
343
|
this.game.on(COMBOS_DEVELOPMENT_TOOL_SET, this.onGameSet);
|
|
340
344
|
this.game.on(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onGameRefresh);
|
|
341
|
-
if (this.enabled
|
|
342
|
-
this.
|
|
343
|
-
}
|
|
344
|
-
else if (this.enabled && this.scope === 'tagged') {
|
|
345
|
-
this.needsTaggedRescan = true;
|
|
345
|
+
if (this.enabled) {
|
|
346
|
+
this.needsRescan = true;
|
|
346
347
|
}
|
|
347
348
|
}
|
|
348
349
|
onDestroy() {
|
|
@@ -353,7 +354,8 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
353
354
|
}
|
|
354
355
|
this.game.off(COMBOS_DEVELOPMENT_TOOL_SET, this.onGameSet);
|
|
355
356
|
this.game.off(COMBOS_DEVELOPMENT_TOOL_REFRESH, this.onGameRefresh);
|
|
356
|
-
this.
|
|
357
|
+
this.detachAllPicks();
|
|
358
|
+
this.restoreCachedGameEvents();
|
|
357
359
|
this.clearSelection();
|
|
358
360
|
}
|
|
359
361
|
/** Programmatic toggle (same effect as events). */
|
|
@@ -363,99 +365,72 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
363
365
|
this.enabled = on;
|
|
364
366
|
if (!on) {
|
|
365
367
|
this.clearSelection();
|
|
366
|
-
this.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
this.needsSceneRescan = true;
|
|
368
|
+
this.detachAllPicks();
|
|
369
|
+
this.restoreCachedGameEvents();
|
|
370
|
+
this.postSetSuccess(false);
|
|
370
371
|
}
|
|
371
372
|
else {
|
|
372
|
-
this.
|
|
373
|
+
this.needsRescan = true;
|
|
373
374
|
}
|
|
374
375
|
}
|
|
375
376
|
get isEnabled() {
|
|
376
377
|
return this.enabled;
|
|
377
378
|
}
|
|
378
379
|
update(e) {
|
|
379
|
-
if (this.enabled && this.
|
|
380
|
-
this.
|
|
381
|
-
this.
|
|
382
|
-
|
|
383
|
-
if (this.enabled && this.needsTaggedRescan && this.scope === 'tagged') {
|
|
384
|
-
this.needsTaggedRescan = false;
|
|
385
|
-
this.attachTaggedObjects();
|
|
380
|
+
if (this.enabled && this.needsRescan) {
|
|
381
|
+
this.needsRescan = false;
|
|
382
|
+
this.attachEditMode();
|
|
383
|
+
this.postSetSuccess(true);
|
|
386
384
|
}
|
|
387
385
|
for (const go of [...this.tapOwners.values()]) {
|
|
388
386
|
if (go.destroyed) {
|
|
389
|
-
this.
|
|
387
|
+
this.releasePick(go);
|
|
390
388
|
}
|
|
391
389
|
}
|
|
392
390
|
if (!this.enabled || !this.selected || !this.outlineGo)
|
|
393
391
|
return;
|
|
394
|
-
|
|
395
|
-
if (!gfxComp?.graphics)
|
|
396
|
-
return;
|
|
397
|
-
const bounds = this.resolvePickBounds(this.selected);
|
|
398
|
-
const g = gfxComp.graphics;
|
|
399
|
-
g.clear();
|
|
400
|
-
const t = typeof performance !== 'undefined' ? performance.now() : e.time;
|
|
401
|
-
const pulse = 0.35 + 0.65 * (0.5 + 0.5 * Math.sin(t * 0.012));
|
|
402
|
-
g.rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
|
403
|
-
g.stroke({ width: 4, color: 0x55ffaa, alpha: pulse });
|
|
392
|
+
this.updateSelectionOutline();
|
|
404
393
|
}
|
|
405
394
|
componentChanged(changed) {
|
|
406
|
-
if (this.
|
|
395
|
+
if (!this.enabled)
|
|
407
396
|
return;
|
|
408
397
|
const { type, gameObject, componentName } = changed;
|
|
409
398
|
if (!gameObject || componentName !== 'CombosDevelopmentToolTarget')
|
|
410
399
|
return;
|
|
411
400
|
if (type === OBSERVER_TYPE.ADD) {
|
|
412
|
-
this.
|
|
401
|
+
this.stripGameEvent(gameObject);
|
|
402
|
+
this.ensurePick(gameObject);
|
|
413
403
|
}
|
|
414
404
|
else if (type === OBSERVER_TYPE.REMOVE) {
|
|
415
|
-
this.
|
|
405
|
+
this.releasePick(gameObject);
|
|
416
406
|
if (this.selected === gameObject) {
|
|
417
407
|
this.clearSelection();
|
|
418
408
|
}
|
|
419
409
|
}
|
|
420
410
|
}
|
|
421
|
-
/** Re-bind
|
|
411
|
+
/** Re-bind pick targets after dynamic scene changes while enabled. */
|
|
422
412
|
requestSceneRescan() {
|
|
423
413
|
if (!this.enabled)
|
|
424
414
|
return;
|
|
425
|
-
|
|
426
|
-
this.needsSceneRescan = true;
|
|
427
|
-
}
|
|
428
|
-
else {
|
|
429
|
-
this.needsTaggedRescan = true;
|
|
430
|
-
}
|
|
415
|
+
this.needsRescan = true;
|
|
431
416
|
}
|
|
432
|
-
|
|
417
|
+
attachEditMode() {
|
|
418
|
+
this.detachAllPicks();
|
|
433
419
|
const list = [];
|
|
434
420
|
for (const tr of this.game.scene.transform.children) {
|
|
435
421
|
this.collectGameObjects(tr.gameObject, list);
|
|
436
422
|
}
|
|
437
423
|
for (const go of list) {
|
|
438
|
-
if (go
|
|
439
|
-
continue;
|
|
440
|
-
if (go === this.outlineGo)
|
|
424
|
+
if (this.isIgnoredPickGo(go))
|
|
441
425
|
continue;
|
|
442
|
-
|
|
443
|
-
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);
|
|
426
|
+
this.stripGameEvent(go);
|
|
452
427
|
}
|
|
453
428
|
for (const go of list) {
|
|
454
|
-
if (go
|
|
429
|
+
if (this.isIgnoredPickGo(go))
|
|
455
430
|
continue;
|
|
456
|
-
if (go
|
|
431
|
+
if (!go.getComponent(CombosDevelopmentToolTarget))
|
|
457
432
|
continue;
|
|
458
|
-
this.
|
|
433
|
+
this.ensurePick(go);
|
|
459
434
|
}
|
|
460
435
|
}
|
|
461
436
|
collectGameObjects(go, out) {
|
|
@@ -464,30 +439,58 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
464
439
|
this.collectGameObjects(tr.gameObject, out);
|
|
465
440
|
}
|
|
466
441
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
442
|
+
isIgnoredPickGo(go) {
|
|
443
|
+
return go.name === OUTLINE_GO_NAME || go === this.outlineGo;
|
|
444
|
+
}
|
|
445
|
+
stripGameEvent(go) {
|
|
446
|
+
if (this.cachedGameEvents.has(go.id))
|
|
447
|
+
return;
|
|
448
|
+
const ev = go.getComponent(Event);
|
|
449
|
+
if (!ev)
|
|
450
|
+
return;
|
|
451
|
+
try {
|
|
452
|
+
const removed = go.removeComponent(Event);
|
|
453
|
+
this.cachedGameEvents.set(go.id, removed);
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
/* ignore */
|
|
470
457
|
}
|
|
471
458
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
459
|
+
restoreCachedGameEvents() {
|
|
460
|
+
for (const [id, event] of [...this.cachedGameEvents.entries()]) {
|
|
461
|
+
const go = this.findGameObjectById(id);
|
|
462
|
+
if (!go || go.destroyed || go.getComponent(Event)) {
|
|
463
|
+
this.cachedGameEvents.delete(id);
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
try {
|
|
467
|
+
go.addComponent(event);
|
|
468
|
+
}
|
|
469
|
+
catch {
|
|
470
|
+
/* ignore */
|
|
471
|
+
}
|
|
472
|
+
this.cachedGameEvents.delete(id);
|
|
477
473
|
}
|
|
474
|
+
}
|
|
475
|
+
detachAllPicks() {
|
|
476
|
+
for (const go of [...this.tapOwners.values()]) {
|
|
477
|
+
this.releasePick(go);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
ensurePick(go) {
|
|
478
481
|
if (this.tapHandlers.has(go.id))
|
|
479
482
|
return;
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
this.
|
|
483
|
+
let ev = go.getComponent(Event);
|
|
484
|
+
if (!ev) {
|
|
485
|
+
ev = go.addComponent(this.createPickEvent(go));
|
|
486
|
+
this.pickEvents.add(go.id);
|
|
483
487
|
}
|
|
484
|
-
ev.removeAllListeners('tap');
|
|
485
488
|
const handler = payload => this.onSelect(go, payload);
|
|
486
489
|
this.tapHandlers.set(go.id, handler);
|
|
487
490
|
this.tapOwners.set(go.id, go);
|
|
488
491
|
ev.on('tap', handler);
|
|
489
492
|
}
|
|
490
|
-
|
|
493
|
+
createPickEvent(go) {
|
|
491
494
|
const bounds = this.resolvePickBounds(go);
|
|
492
495
|
if (bounds.width > 0 && bounds.height > 0) {
|
|
493
496
|
return new Event({
|
|
@@ -502,13 +505,14 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
502
505
|
},
|
|
503
506
|
});
|
|
504
507
|
}
|
|
505
|
-
// Let Pixi use natural rendered bounds instead of forcing a 1×1 hit area.
|
|
506
508
|
return new Event();
|
|
507
509
|
}
|
|
508
510
|
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
511
|
if (this.shouldPreferRenderedBounds(go)) {
|
|
512
|
+
const fromOwnGraphics = this.resolveOwnGraphicsLocalBounds(go);
|
|
513
|
+
if (fromOwnGraphics) {
|
|
514
|
+
return fromOwnGraphics;
|
|
515
|
+
}
|
|
512
516
|
const fromGraphics = this.resolveContainerLocalBounds(go);
|
|
513
517
|
if (fromGraphics) {
|
|
514
518
|
return fromGraphics;
|
|
@@ -527,10 +531,37 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
527
531
|
shouldPreferRenderedBounds(go) {
|
|
528
532
|
return go.getComponent(Graphics) != null;
|
|
529
533
|
}
|
|
534
|
+
/** Bounds of this GO's own Graphics only — excludes child GOs such as the selection outline. */
|
|
535
|
+
resolveOwnGraphicsLocalBounds(go) {
|
|
536
|
+
const gfx = go.getComponent(Graphics);
|
|
537
|
+
if (!gfx?.graphics)
|
|
538
|
+
return null;
|
|
539
|
+
try {
|
|
540
|
+
const bounds = gfx.graphics.getLocalBounds();
|
|
541
|
+
if (bounds.width > 0 && bounds.height > 0) {
|
|
542
|
+
return {
|
|
543
|
+
x: bounds.x,
|
|
544
|
+
y: bounds.y,
|
|
545
|
+
width: bounds.width,
|
|
546
|
+
height: bounds.height,
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
catch {
|
|
551
|
+
/* ignore */
|
|
552
|
+
}
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
530
555
|
resolveContainerLocalBounds(go) {
|
|
531
556
|
const container = this.getRendererContainer(go);
|
|
532
557
|
if (!container)
|
|
533
558
|
return null;
|
|
559
|
+
const outlineContainer = this.getOutlineContainerIfChildOf(go);
|
|
560
|
+
let outlineDetached = false;
|
|
561
|
+
if (outlineContainer?.parent === container) {
|
|
562
|
+
container.removeChild(outlineContainer);
|
|
563
|
+
outlineDetached = true;
|
|
564
|
+
}
|
|
534
565
|
try {
|
|
535
566
|
const bounds = container.getLocalBounds();
|
|
536
567
|
if (bounds.width > 0 && bounds.height > 0) {
|
|
@@ -545,8 +576,20 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
545
576
|
catch {
|
|
546
577
|
/* ignore */
|
|
547
578
|
}
|
|
579
|
+
finally {
|
|
580
|
+
if (outlineDetached && outlineContainer) {
|
|
581
|
+
container.addChild(outlineContainer);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
548
584
|
return null;
|
|
549
585
|
}
|
|
586
|
+
/** Outline is parented under the selected GO; exclude it when measuring content bounds. */
|
|
587
|
+
getOutlineContainerIfChildOf(go) {
|
|
588
|
+
if (!this.outlineGo || this.outlineGo.parent !== go) {
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
return this.getRendererContainer(this.outlineGo);
|
|
592
|
+
}
|
|
550
593
|
getRendererContainer(go) {
|
|
551
594
|
const rendererSystem = this.game.getSystem(RendererSystem);
|
|
552
595
|
if (!rendererSystem?.containerManager)
|
|
@@ -558,7 +601,7 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
558
601
|
return null;
|
|
559
602
|
}
|
|
560
603
|
}
|
|
561
|
-
|
|
604
|
+
releasePick(go) {
|
|
562
605
|
const handler = this.tapHandlers.get(go.id);
|
|
563
606
|
if (!handler)
|
|
564
607
|
return;
|
|
@@ -566,25 +609,26 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
566
609
|
ev?.off('tap', handler);
|
|
567
610
|
this.tapHandlers.delete(go.id);
|
|
568
611
|
this.tapOwners.delete(go.id);
|
|
569
|
-
if (
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
for (const fn of saved) {
|
|
573
|
-
ev.on('tap', fn);
|
|
574
|
-
}
|
|
612
|
+
if (this.pickEvents.has(go.id)) {
|
|
613
|
+
try {
|
|
614
|
+
go.removeComponent(Event);
|
|
575
615
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
try {
|
|
579
|
-
go.removeComponent(Event);
|
|
580
|
-
}
|
|
581
|
-
catch {
|
|
582
|
-
/* ignore */
|
|
583
|
-
}
|
|
584
|
-
this.injectedEvents.delete(go.id);
|
|
616
|
+
catch {
|
|
617
|
+
/* ignore */
|
|
585
618
|
}
|
|
619
|
+
this.pickEvents.delete(go.id);
|
|
586
620
|
}
|
|
587
621
|
}
|
|
622
|
+
postSetSuccess(enabled) {
|
|
623
|
+
const payload = {
|
|
624
|
+
type: COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS,
|
|
625
|
+
enabled,
|
|
626
|
+
};
|
|
627
|
+
if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
|
|
628
|
+
window.parent.postMessage(payload, this.postMessageOrigin);
|
|
629
|
+
}
|
|
630
|
+
this.game.emit(COMBOS_DEVELOPMENT_TOOL_SET_SUCCESS, { enabled });
|
|
631
|
+
}
|
|
588
632
|
ensureOutline() {
|
|
589
633
|
if (this.outlineGo)
|
|
590
634
|
return;
|
|
@@ -608,6 +652,8 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
608
652
|
this.outlineGo.remove();
|
|
609
653
|
}
|
|
610
654
|
go.addChild(this.outlineGo);
|
|
655
|
+
this.invalidateOutlineBounds();
|
|
656
|
+
this.updateSelectionOutline();
|
|
611
657
|
const snapshot = buildGameObjectSnapshot(go);
|
|
612
658
|
const payload = {
|
|
613
659
|
type: COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED,
|
|
@@ -679,6 +725,8 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
679
725
|
if (!applied)
|
|
680
726
|
return;
|
|
681
727
|
if (this.selected?.id === go.id) {
|
|
728
|
+
this.invalidateOutlineBounds();
|
|
729
|
+
this.updateSelectionOutline();
|
|
682
730
|
this.postSnapshotUpdate(go);
|
|
683
731
|
}
|
|
684
732
|
}
|
|
@@ -695,6 +743,7 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
695
743
|
}
|
|
696
744
|
clearSelection() {
|
|
697
745
|
this.selected = null;
|
|
746
|
+
this.invalidateOutlineBounds();
|
|
698
747
|
if (this.outlineGo?.parent) {
|
|
699
748
|
this.outlineGo.remove();
|
|
700
749
|
}
|
|
@@ -703,6 +752,33 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends Syst
|
|
|
703
752
|
gfx.graphics.clear();
|
|
704
753
|
}
|
|
705
754
|
}
|
|
755
|
+
/** Redraw the green outline only when content bounds change (movement follows via child transform). */
|
|
756
|
+
updateSelectionOutline() {
|
|
757
|
+
if (!this.enabled || !this.selected || !this.outlineGo)
|
|
758
|
+
return;
|
|
759
|
+
const gfxComp = this.outlineGo.getComponent(Graphics);
|
|
760
|
+
if (!gfxComp?.graphics)
|
|
761
|
+
return;
|
|
762
|
+
const bounds = this.resolvePickBounds(this.selected);
|
|
763
|
+
if (this.lastOutlineBounds && this.pickBoundsEqual(this.lastOutlineBounds, bounds)) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
this.lastOutlineBounds = bounds;
|
|
767
|
+
const g = gfxComp.graphics;
|
|
768
|
+
g.clear();
|
|
769
|
+
g.rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
|
770
|
+
g.stroke({ width: 4, color: 0x55ffaa, alpha: 1 });
|
|
771
|
+
}
|
|
772
|
+
invalidateOutlineBounds() {
|
|
773
|
+
this.lastOutlineBounds = null;
|
|
774
|
+
}
|
|
775
|
+
pickBoundsEqual(a, b) {
|
|
776
|
+
const eps = 0.01;
|
|
777
|
+
return (Math.abs(a.x - b.x) < eps &&
|
|
778
|
+
Math.abs(a.y - b.y) < eps &&
|
|
779
|
+
Math.abs(a.width - b.width) < eps &&
|
|
780
|
+
Math.abs(a.height - b.height) < eps);
|
|
781
|
+
}
|
|
706
782
|
};
|
|
707
783
|
CombosDevelopmentToolSystem = __decorate([
|
|
708
784
|
decorators.componentObserver({
|
|
@@ -714,8 +790,8 @@ var CombosDevelopmentToolSystem$1 = CombosDevelopmentToolSystem;
|
|
|
714
790
|
/** Auto-generated by scripts/build-package.mjs — do not edit. */
|
|
715
791
|
Object.assign(CombosDevelopmentToolSystem$1, {
|
|
716
792
|
packageName: "@combos-fun/plugin-development-tool",
|
|
717
|
-
packageVersion: "0.0.
|
|
793
|
+
packageVersion: "0.0.20",
|
|
718
794
|
});
|
|
719
795
|
|
|
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 };
|
|
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 };
|
|
721
797
|
//# sourceMappingURL=plugin-development-tool.esm.js.map
|