@combos-fun/plugin-development-tool 0.0.13 → 0.0.15
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/dist/plugin-development-tool.cjs.js +454 -40
- 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 +49 -4
- package/dist/plugin-development-tool.esm.js +444 -37
- package/dist/plugin-development-tool.esm.js.map +1 -1
- package/package.json +5 -4
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var engine = require('@combos-fun/engine');
|
|
4
3
|
var tslib = require('tslib');
|
|
4
|
+
var engine = require('@combos-fun/engine');
|
|
5
|
+
var pluginRenderer = require('@combos-fun/plugin-renderer');
|
|
5
6
|
var pluginRendererGraphics = require('@combos-fun/plugin-renderer-graphics');
|
|
6
7
|
var pluginRendererEvent = require('@combos-fun/plugin-renderer-event');
|
|
7
8
|
|
|
@@ -11,6 +12,10 @@ const COMBOS_DEVELOPMENT_TOOL_SET = 'combos-development-tool:set';
|
|
|
11
12
|
const COMBOS_DEVELOPMENT_TOOL_REFRESH = 'combos-development-tool:refresh';
|
|
12
13
|
/** Emitted to `window.parent` when an object is selected while the tool is on. */
|
|
13
14
|
const COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED = 'combos-development-tool:gameobject-selected';
|
|
15
|
+
/** Parent → iframe: apply a value to a component field (live preview). */
|
|
16
|
+
const COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY = 'combos-development-tool:apply-property';
|
|
17
|
+
/** iframe → parent: game scene bootstrap finished; parent may enable pick mode. */
|
|
18
|
+
const COMBOS_DEVELOPMENT_TOOL_READY = 'combos-development-tool:ready';
|
|
14
19
|
|
|
15
20
|
/**
|
|
16
21
|
* Optional marker when using `CombosDevelopmentToolSystem` with `scope: 'tagged'`, or to attach
|
|
@@ -27,6 +32,243 @@ class CombosDevelopmentToolTarget extends engine.Component {
|
|
|
27
32
|
}
|
|
28
33
|
}
|
|
29
34
|
|
|
35
|
+
function isSceneSourceAnchor(v) {
|
|
36
|
+
return (!!v &&
|
|
37
|
+
typeof v === 'object' &&
|
|
38
|
+
typeof v.file === 'string');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const SKIP_KEYS = new Set([
|
|
42
|
+
'gameObject',
|
|
43
|
+
'name',
|
|
44
|
+
'started',
|
|
45
|
+
'__componentDefaultParams',
|
|
46
|
+
'destroyed',
|
|
47
|
+
'inScene',
|
|
48
|
+
'worldTransform',
|
|
49
|
+
'children',
|
|
50
|
+
'_parent',
|
|
51
|
+
]);
|
|
52
|
+
const COMPONENT_SKIP_KEYS = {
|
|
53
|
+
Physics: new Set([
|
|
54
|
+
'body',
|
|
55
|
+
'Body',
|
|
56
|
+
'PhysicsEngine',
|
|
57
|
+
'World',
|
|
58
|
+
'Constraint',
|
|
59
|
+
'mouseConstraint',
|
|
60
|
+
'bodyParams',
|
|
61
|
+
]),
|
|
62
|
+
Event: new Set(['hitArea']),
|
|
63
|
+
};
|
|
64
|
+
function cloneJsonSafe(value, depth = 0) {
|
|
65
|
+
if (value === null || value === undefined)
|
|
66
|
+
return value;
|
|
67
|
+
if (typeof value === 'number' || typeof value === 'string' || typeof value === 'boolean') {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
if (depth > 6)
|
|
71
|
+
return undefined;
|
|
72
|
+
if (Array.isArray(value)) {
|
|
73
|
+
return value.map(item => cloneJsonSafe(item, depth + 1));
|
|
74
|
+
}
|
|
75
|
+
if (typeof value === 'object') {
|
|
76
|
+
const out = {};
|
|
77
|
+
for (const [k, v] of Object.entries(value)) {
|
|
78
|
+
if (typeof v === 'function')
|
|
79
|
+
continue;
|
|
80
|
+
const cloned = cloneJsonSafe(v, depth + 1);
|
|
81
|
+
if (cloned !== undefined)
|
|
82
|
+
out[k] = cloned;
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
function serializeComponent(comp) {
|
|
89
|
+
const out = {};
|
|
90
|
+
const componentSkips = COMPONENT_SKIP_KEYS[comp.name];
|
|
91
|
+
for (const key of Object.keys(comp)) {
|
|
92
|
+
if (SKIP_KEYS.has(key) || key.startsWith('_'))
|
|
93
|
+
continue;
|
|
94
|
+
if (componentSkips?.has(key))
|
|
95
|
+
continue;
|
|
96
|
+
const value = comp[key];
|
|
97
|
+
if (typeof value === 'function')
|
|
98
|
+
continue;
|
|
99
|
+
const cloned = cloneJsonSafe(value);
|
|
100
|
+
if (cloned !== undefined)
|
|
101
|
+
out[key] = cloned;
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
function readSourceAnchor(go) {
|
|
106
|
+
const tag = go.getComponent(CombosDevelopmentToolTarget);
|
|
107
|
+
const raw = tag?.payload?.source;
|
|
108
|
+
if (!isSceneSourceAnchor(raw))
|
|
109
|
+
return undefined;
|
|
110
|
+
return {
|
|
111
|
+
file: raw.file,
|
|
112
|
+
anchor: raw.anchor ?? go.name,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function buildGameObjectSnapshot(go) {
|
|
116
|
+
const components = go.components
|
|
117
|
+
.filter(c => c.name !== 'CombosDevelopmentToolTarget')
|
|
118
|
+
.map(c => ({
|
|
119
|
+
componentName: c.name,
|
|
120
|
+
fields: serializeComponent(c),
|
|
121
|
+
}));
|
|
122
|
+
return {
|
|
123
|
+
id: go.id,
|
|
124
|
+
name: go.name,
|
|
125
|
+
components,
|
|
126
|
+
source: readSourceAnchor(go),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function applyPropertyValue(go, componentName, path, value) {
|
|
130
|
+
const comp = go.getComponent(componentName);
|
|
131
|
+
if (!comp || !path.length)
|
|
132
|
+
return false;
|
|
133
|
+
let target = comp;
|
|
134
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
135
|
+
const key = path[i];
|
|
136
|
+
if (target[key] === undefined || target[key] === null) {
|
|
137
|
+
target[key] = {};
|
|
138
|
+
}
|
|
139
|
+
target = target[key];
|
|
140
|
+
}
|
|
141
|
+
target[path[path.length - 1]] = value;
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
function readPropertyValue(go, componentName, path) {
|
|
145
|
+
const comp = go.getComponent(componentName);
|
|
146
|
+
if (!comp || !path.length)
|
|
147
|
+
return undefined;
|
|
148
|
+
let target = comp;
|
|
149
|
+
for (const key of path) {
|
|
150
|
+
if (target === null || target === undefined || typeof target !== 'object') {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
target = target[key];
|
|
154
|
+
}
|
|
155
|
+
return target;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const TRANSFORM_VECTOR_KEYS = new Set([
|
|
159
|
+
'position',
|
|
160
|
+
'size',
|
|
161
|
+
'origin',
|
|
162
|
+
'anchor',
|
|
163
|
+
'scale',
|
|
164
|
+
'skew',
|
|
165
|
+
]);
|
|
166
|
+
function asNumber(value) {
|
|
167
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
168
|
+
return value;
|
|
169
|
+
}
|
|
170
|
+
if (typeof value === 'string' && value.trim() !== '') {
|
|
171
|
+
const next = Number(value);
|
|
172
|
+
return Number.isFinite(next) ? next : undefined;
|
|
173
|
+
}
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
function syncPhysicsBodyFromTransform(go) {
|
|
177
|
+
const physics = go.getComponent('Physics');
|
|
178
|
+
if (!physics?.body) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const { x, y } = go.transform.position;
|
|
182
|
+
if (physics.Body?.setPosition) {
|
|
183
|
+
physics.Body.setPosition(physics.body, { x, y });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
physics.body.position.x = x;
|
|
187
|
+
physics.body.position.y = y;
|
|
188
|
+
}
|
|
189
|
+
function syncMoverOriginFromTransform(go) {
|
|
190
|
+
const mover = go.getComponent('PlatformerMover');
|
|
191
|
+
if (!mover) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
mover.originX = go.transform.position.x;
|
|
195
|
+
mover.originY = go.transform.position.y;
|
|
196
|
+
}
|
|
197
|
+
function applyTransformProperty(go, comp, path, value) {
|
|
198
|
+
const transform = go.transform ?? comp;
|
|
199
|
+
const transformRecord = transform;
|
|
200
|
+
if (path.length === 1 && path[0] === 'rotation') {
|
|
201
|
+
const next = asNumber(value);
|
|
202
|
+
if (next === undefined) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
transform.rotation = next;
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
if (path.length === 2 && TRANSFORM_VECTOR_KEYS.has(path[0])) {
|
|
209
|
+
const groupKey = path[0];
|
|
210
|
+
const leafKey = path[1];
|
|
211
|
+
const next = asNumber(value);
|
|
212
|
+
if (next === undefined) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
const group = transformRecord[groupKey];
|
|
216
|
+
if (!group || typeof group !== 'object') {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
group[leafKey] = next;
|
|
220
|
+
if (groupKey === 'position') {
|
|
221
|
+
syncPhysicsBodyFromTransform(go);
|
|
222
|
+
syncMoverOriginFromTransform(go);
|
|
223
|
+
}
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
function applyTextProperty(_go, comp, path, value) {
|
|
229
|
+
const textComp = comp;
|
|
230
|
+
if (path.length === 1 && path[0] === 'text') {
|
|
231
|
+
textComp.text = String(value ?? '');
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
if (path.length === 2 && path[0] === 'style') {
|
|
235
|
+
const styleKey = path[1];
|
|
236
|
+
const nextStyle = { ...(textComp.style ?? {}), [styleKey]: value };
|
|
237
|
+
textComp.style = nextStyle;
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
function applySoundProperty(_go, comp, path, value) {
|
|
243
|
+
const soundComp = comp;
|
|
244
|
+
if ((path.length === 1 && path[0] === 'volume') ||
|
|
245
|
+
(path.length === 2 && path[0] === 'config' && path[1] === 'volume')) {
|
|
246
|
+
const next = asNumber(value);
|
|
247
|
+
if (next === undefined) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
soundComp.volume = next;
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
const APPLY_HOOKS = {
|
|
256
|
+
Transform: applyTransformProperty,
|
|
257
|
+
Text: applyTextProperty,
|
|
258
|
+
Sound: applySoundProperty,
|
|
259
|
+
};
|
|
260
|
+
function applyPropertyWithHooks(go, componentName, path, value) {
|
|
261
|
+
const comp = go.getComponent(componentName);
|
|
262
|
+
if (!comp || !path.length) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
const hook = APPLY_HOOKS[componentName];
|
|
266
|
+
if (hook?.(go, comp, path, value)) {
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
return applyPropertyValue(go, componentName, path, value);
|
|
270
|
+
}
|
|
271
|
+
|
|
30
272
|
const OUTLINE_GO_NAME = '__combosDevelopmentToolOutline';
|
|
31
273
|
/**
|
|
32
274
|
* **Defaults:** `scope: 'scene'`, **off** at start (no tap hijack until enabled).
|
|
@@ -37,7 +279,7 @@ const OUTLINE_GO_NAME = '__combosDevelopmentToolOutline';
|
|
|
37
279
|
*
|
|
38
280
|
* With `scope: 'scene'`, while enabled: `game.emit(COMBOS_DEVELOPMENT_TOOL_REFRESH)`, `window` event `combos-development-tool:refresh`, or `postMessage({ type: 'combos-development-tool:refresh' })` to re-bind after adding/removing objects.
|
|
39
281
|
*/
|
|
40
|
-
let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engine.System {
|
|
282
|
+
let CombosDevelopmentToolSystem$1 = class CombosDevelopmentToolSystem extends engine.System {
|
|
41
283
|
constructor() {
|
|
42
284
|
super(...arguments);
|
|
43
285
|
this.postMessageOrigin = '*';
|
|
@@ -50,6 +292,7 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
50
292
|
/** We added `Event` for hit-testing; remove on teardown when disabling / releaseTap. */
|
|
51
293
|
this.injectedEvents = new Set();
|
|
52
294
|
this.needsSceneRescan = false;
|
|
295
|
+
this.needsTaggedRescan = false;
|
|
53
296
|
this.onWindowSet = (e) => {
|
|
54
297
|
const d = e.detail;
|
|
55
298
|
if (d && typeof d.enabled === 'boolean') {
|
|
@@ -66,6 +309,9 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
66
309
|
else if (d.type === COMBOS_DEVELOPMENT_TOOL_REFRESH) {
|
|
67
310
|
this.requestSceneRescan();
|
|
68
311
|
}
|
|
312
|
+
else if (d.type === COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY) {
|
|
313
|
+
this.handleApplyProperty(d);
|
|
314
|
+
}
|
|
69
315
|
};
|
|
70
316
|
this.onGameSet = (payload) => {
|
|
71
317
|
if (payload && typeof payload.enabled === 'boolean') {
|
|
@@ -93,6 +339,9 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
93
339
|
if (this.enabled && this.scope === 'scene') {
|
|
94
340
|
this.needsSceneRescan = true;
|
|
95
341
|
}
|
|
342
|
+
else if (this.enabled && this.scope === 'tagged') {
|
|
343
|
+
this.needsTaggedRescan = true;
|
|
344
|
+
}
|
|
96
345
|
}
|
|
97
346
|
onDestroy() {
|
|
98
347
|
if (typeof window !== 'undefined') {
|
|
@@ -112,22 +361,27 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
112
361
|
this.enabled = on;
|
|
113
362
|
if (!on) {
|
|
114
363
|
this.clearSelection();
|
|
115
|
-
|
|
116
|
-
this.detachAllTaps();
|
|
117
|
-
}
|
|
364
|
+
this.detachAllTaps();
|
|
118
365
|
}
|
|
119
366
|
else if (this.scope === 'scene') {
|
|
120
367
|
this.needsSceneRescan = true;
|
|
121
368
|
}
|
|
369
|
+
else {
|
|
370
|
+
this.needsTaggedRescan = true;
|
|
371
|
+
}
|
|
122
372
|
}
|
|
123
373
|
get isEnabled() {
|
|
124
374
|
return this.enabled;
|
|
125
375
|
}
|
|
126
376
|
update(e) {
|
|
127
|
-
if (this.
|
|
377
|
+
if (this.enabled && this.needsSceneRescan && this.scope === 'scene') {
|
|
128
378
|
this.needsSceneRescan = false;
|
|
129
379
|
this.attachSceneTree();
|
|
130
380
|
}
|
|
381
|
+
if (this.enabled && this.needsTaggedRescan && this.scope === 'tagged') {
|
|
382
|
+
this.needsTaggedRescan = false;
|
|
383
|
+
this.attachTaggedObjects();
|
|
384
|
+
}
|
|
131
385
|
for (const go of [...this.tapOwners.values()]) {
|
|
132
386
|
if (go.destroyed) {
|
|
133
387
|
this.releaseTap(go);
|
|
@@ -138,12 +392,12 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
138
392
|
const gfxComp = this.outlineGo.getComponent(pluginRendererGraphics.Graphics);
|
|
139
393
|
if (!gfxComp?.graphics)
|
|
140
394
|
return;
|
|
141
|
-
const
|
|
395
|
+
const bounds = this.resolvePickBounds(this.selected);
|
|
142
396
|
const g = gfxComp.graphics;
|
|
143
397
|
g.clear();
|
|
144
398
|
const t = typeof performance !== 'undefined' ? performance.now() : e.time;
|
|
145
399
|
const pulse = 0.35 + 0.65 * (0.5 + 0.5 * Math.sin(t * 0.012));
|
|
146
|
-
g.rect(
|
|
400
|
+
g.rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
|
147
401
|
g.stroke({ width: 4, color: 0x55ffaa, alpha: pulse });
|
|
148
402
|
}
|
|
149
403
|
componentChanged(changed) {
|
|
@@ -164,9 +418,29 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
164
418
|
}
|
|
165
419
|
/** Re-bind scene taps when `scope === 'scene'` (e.g. after dynamic spawn). */
|
|
166
420
|
requestSceneRescan() {
|
|
167
|
-
if (
|
|
421
|
+
if (!this.enabled)
|
|
168
422
|
return;
|
|
169
|
-
this.
|
|
423
|
+
if (this.scope === 'scene') {
|
|
424
|
+
this.needsSceneRescan = true;
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
this.needsTaggedRescan = true;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
attachTaggedObjects() {
|
|
431
|
+
const list = [];
|
|
432
|
+
for (const tr of this.game.scene.transform.children) {
|
|
433
|
+
this.collectGameObjects(tr.gameObject, list);
|
|
434
|
+
}
|
|
435
|
+
for (const go of list) {
|
|
436
|
+
if (go.name === OUTLINE_GO_NAME)
|
|
437
|
+
continue;
|
|
438
|
+
if (go === this.outlineGo)
|
|
439
|
+
continue;
|
|
440
|
+
if (!go.getComponent(CombosDevelopmentToolTarget))
|
|
441
|
+
continue;
|
|
442
|
+
this.ensureTap(go);
|
|
443
|
+
}
|
|
170
444
|
}
|
|
171
445
|
attachSceneTree() {
|
|
172
446
|
this.detachAllTaps();
|
|
@@ -196,22 +470,85 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
196
470
|
ensureTap(go) {
|
|
197
471
|
let ev = go.getComponent(pluginRendererEvent.Event);
|
|
198
472
|
if (!ev) {
|
|
199
|
-
|
|
200
|
-
ev = go.addComponent(new pluginRendererEvent.Event({
|
|
201
|
-
hitArea: {
|
|
202
|
-
type: pluginRendererEvent.HIT_AREA_TYPE.Rect,
|
|
203
|
-
style: { x: 0, y: 0, width: width || 1, height: height || 1 },
|
|
204
|
-
},
|
|
205
|
-
}));
|
|
473
|
+
ev = go.addComponent(this.createInjectedEvent(go));
|
|
206
474
|
this.injectedEvents.add(go.id);
|
|
207
475
|
}
|
|
208
476
|
if (this.tapHandlers.has(go.id))
|
|
209
477
|
return;
|
|
210
|
-
const handler = () => this.onSelect(go);
|
|
478
|
+
const handler = (payload) => this.onSelect(go, payload);
|
|
211
479
|
this.tapHandlers.set(go.id, handler);
|
|
212
480
|
this.tapOwners.set(go.id, go);
|
|
213
481
|
ev.on('tap', handler);
|
|
214
482
|
}
|
|
483
|
+
createInjectedEvent(go) {
|
|
484
|
+
const { width, height } = go.transform.size;
|
|
485
|
+
if (width > 0 && height > 0) {
|
|
486
|
+
return new pluginRendererEvent.Event({
|
|
487
|
+
hitArea: {
|
|
488
|
+
type: pluginRendererEvent.HIT_AREA_TYPE.Rect,
|
|
489
|
+
style: { x: 0, y: 0, width, height },
|
|
490
|
+
},
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
const bounds = this.resolveContainerLocalBounds(go);
|
|
494
|
+
if (bounds) {
|
|
495
|
+
return new pluginRendererEvent.Event({
|
|
496
|
+
hitArea: {
|
|
497
|
+
type: pluginRendererEvent.HIT_AREA_TYPE.Rect,
|
|
498
|
+
style: {
|
|
499
|
+
x: bounds.x,
|
|
500
|
+
y: bounds.y,
|
|
501
|
+
width: bounds.width,
|
|
502
|
+
height: bounds.height,
|
|
503
|
+
},
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
// Let Pixi use natural rendered bounds instead of forcing a 1×1 hit area.
|
|
508
|
+
return new pluginRendererEvent.Event();
|
|
509
|
+
}
|
|
510
|
+
resolvePickBounds(go) {
|
|
511
|
+
const { width, height } = go.transform.size;
|
|
512
|
+
if (width > 0 && height > 0) {
|
|
513
|
+
return { x: 0, y: 0, width, height };
|
|
514
|
+
}
|
|
515
|
+
const fromContainer = this.resolveContainerLocalBounds(go);
|
|
516
|
+
if (fromContainer) {
|
|
517
|
+
return fromContainer;
|
|
518
|
+
}
|
|
519
|
+
return { x: 0, y: 0, width: 1, height: 1 };
|
|
520
|
+
}
|
|
521
|
+
resolveContainerLocalBounds(go) {
|
|
522
|
+
const container = this.getRendererContainer(go);
|
|
523
|
+
if (!container)
|
|
524
|
+
return null;
|
|
525
|
+
try {
|
|
526
|
+
const bounds = container.getLocalBounds();
|
|
527
|
+
if (bounds.width > 0 && bounds.height > 0) {
|
|
528
|
+
return {
|
|
529
|
+
x: bounds.x,
|
|
530
|
+
y: bounds.y,
|
|
531
|
+
width: bounds.width,
|
|
532
|
+
height: bounds.height,
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
catch {
|
|
537
|
+
/* ignore */
|
|
538
|
+
}
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
getRendererContainer(go) {
|
|
542
|
+
const rendererSystem = this.game.getSystem(pluginRenderer.RendererSystem);
|
|
543
|
+
if (!rendererSystem?.containerManager)
|
|
544
|
+
return null;
|
|
545
|
+
try {
|
|
546
|
+
return rendererSystem.containerManager.getContainer(go.id);
|
|
547
|
+
}
|
|
548
|
+
catch {
|
|
549
|
+
return null;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
215
552
|
releaseTap(go) {
|
|
216
553
|
const handler = this.tapHandlers.get(go.id);
|
|
217
554
|
if (!handler)
|
|
@@ -241,7 +578,7 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
241
578
|
go.addComponent(new pluginRendererGraphics.Graphics());
|
|
242
579
|
this.outlineGo = go;
|
|
243
580
|
}
|
|
244
|
-
onSelect(go) {
|
|
581
|
+
onSelect(go, tap) {
|
|
245
582
|
if (!this.enabled)
|
|
246
583
|
return;
|
|
247
584
|
this.ensureOutline();
|
|
@@ -252,11 +589,91 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
252
589
|
this.outlineGo.remove();
|
|
253
590
|
}
|
|
254
591
|
go.addChild(this.outlineGo);
|
|
255
|
-
const
|
|
592
|
+
const snapshot = buildGameObjectSnapshot(go);
|
|
593
|
+
const payload = {
|
|
594
|
+
type: COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED,
|
|
595
|
+
snapshot,
|
|
596
|
+
pointer: tap?.data?.position ?? null,
|
|
597
|
+
};
|
|
256
598
|
if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
|
|
257
599
|
window.parent.postMessage(payload, this.postMessageOrigin);
|
|
258
600
|
}
|
|
259
601
|
}
|
|
602
|
+
findGameObjectById(id) {
|
|
603
|
+
const stack = [];
|
|
604
|
+
for (const tr of this.game.scene.transform.children) {
|
|
605
|
+
this.collectGameObjects(tr.gameObject, stack);
|
|
606
|
+
}
|
|
607
|
+
return stack.find(go => go.id === id) ?? null;
|
|
608
|
+
}
|
|
609
|
+
findGameObjectBySource(source) {
|
|
610
|
+
const stack = [];
|
|
611
|
+
for (const tr of this.game.scene.transform.children) {
|
|
612
|
+
this.collectGameObjects(tr.gameObject, stack);
|
|
613
|
+
}
|
|
614
|
+
const wantFile = source.file.trim();
|
|
615
|
+
const wantAnchor = (source.anchor ?? '').trim();
|
|
616
|
+
if (!wantAnchor) {
|
|
617
|
+
return null;
|
|
618
|
+
}
|
|
619
|
+
for (const go of stack) {
|
|
620
|
+
const anchor = readSourceAnchor(go);
|
|
621
|
+
if (!anchor || anchor.file !== wantFile) {
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
const resolvedAnchor = anchor.anchor ?? go.name;
|
|
625
|
+
if (resolvedAnchor === wantAnchor) {
|
|
626
|
+
return go;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
resolveApplyTarget(payload) {
|
|
632
|
+
if (typeof payload.gameObjectId === 'number') {
|
|
633
|
+
const byId = this.findGameObjectById(payload.gameObjectId);
|
|
634
|
+
if (byId) {
|
|
635
|
+
return byId;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
const file = payload.source?.file?.trim();
|
|
639
|
+
const anchor = payload.source?.anchor?.trim();
|
|
640
|
+
if (!file || !anchor) {
|
|
641
|
+
return null;
|
|
642
|
+
}
|
|
643
|
+
return this.findGameObjectBySource({ file, anchor });
|
|
644
|
+
}
|
|
645
|
+
handleApplyProperty(payload) {
|
|
646
|
+
const componentName = payload.componentName;
|
|
647
|
+
const path = payload.path;
|
|
648
|
+
const hasId = typeof payload.gameObjectId === 'number';
|
|
649
|
+
const hasSource = Boolean(payload.source?.file?.trim()) && Boolean(payload.source?.anchor?.trim());
|
|
650
|
+
if ((!hasId && !hasSource) ||
|
|
651
|
+
typeof componentName !== 'string' ||
|
|
652
|
+
!Array.isArray(path) ||
|
|
653
|
+
path.length === 0) {
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
const go = this.resolveApplyTarget(payload);
|
|
657
|
+
if (!go)
|
|
658
|
+
return;
|
|
659
|
+
const applied = applyPropertyWithHooks(go, componentName, path, payload.value);
|
|
660
|
+
if (!applied)
|
|
661
|
+
return;
|
|
662
|
+
if (this.selected?.id === go.id) {
|
|
663
|
+
this.postSnapshotUpdate(go);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
postSnapshotUpdate(go) {
|
|
667
|
+
const snapshot = buildGameObjectSnapshot(go);
|
|
668
|
+
if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
|
|
669
|
+
window.parent.postMessage({
|
|
670
|
+
type: COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED,
|
|
671
|
+
snapshot,
|
|
672
|
+
pointer: null,
|
|
673
|
+
source: 'property-applied',
|
|
674
|
+
}, this.postMessageOrigin);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
260
677
|
clearSelection() {
|
|
261
678
|
this.selected = null;
|
|
262
679
|
if (this.outlineGo?.parent) {
|
|
@@ -267,33 +684,30 @@ let CombosDevelopmentToolSystem = class CombosDevelopmentToolSystem extends engi
|
|
|
267
684
|
gfx.graphics.clear();
|
|
268
685
|
}
|
|
269
686
|
}
|
|
270
|
-
serializeGameObject(go) {
|
|
271
|
-
const tag = go.getComponent(CombosDevelopmentToolTarget);
|
|
272
|
-
const pos = go.transform.position;
|
|
273
|
-
const size = go.transform.size;
|
|
274
|
-
return {
|
|
275
|
-
type: COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED,
|
|
276
|
-
gameObject: {
|
|
277
|
-
name: go.name,
|
|
278
|
-
id: go.id,
|
|
279
|
-
position: { x: pos.x, y: pos.y },
|
|
280
|
-
size: { width: size.width, height: size.height },
|
|
281
|
-
rotation: go.transform.rotation,
|
|
282
|
-
payload: tag?.payload ?? {},
|
|
283
|
-
},
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
687
|
};
|
|
287
|
-
CombosDevelopmentToolSystem = tslib.__decorate([
|
|
688
|
+
CombosDevelopmentToolSystem$1 = tslib.__decorate([
|
|
288
689
|
engine.decorators.componentObserver({
|
|
289
690
|
CombosDevelopmentToolTarget: [],
|
|
290
691
|
})
|
|
291
|
-
], CombosDevelopmentToolSystem);
|
|
292
|
-
var
|
|
692
|
+
], CombosDevelopmentToolSystem$1);
|
|
693
|
+
var CombosDevelopmentToolSystem = CombosDevelopmentToolSystem$1;
|
|
694
|
+
|
|
695
|
+
/** Auto-generated by scripts/build-package.mjs — do not edit. */
|
|
696
|
+
Object.assign(CombosDevelopmentToolSystem, {
|
|
697
|
+
packageName: "@combos-fun/plugin-development-tool",
|
|
698
|
+
packageVersion: "0.0.15",
|
|
699
|
+
});
|
|
293
700
|
|
|
701
|
+
exports.COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY = COMBOS_DEVELOPMENT_TOOL_APPLY_PROPERTY;
|
|
294
702
|
exports.COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED = COMBOS_DEVELOPMENT_TOOL_GAMEOBJECT_SELECTED;
|
|
703
|
+
exports.COMBOS_DEVELOPMENT_TOOL_READY = COMBOS_DEVELOPMENT_TOOL_READY;
|
|
295
704
|
exports.COMBOS_DEVELOPMENT_TOOL_REFRESH = COMBOS_DEVELOPMENT_TOOL_REFRESH;
|
|
296
705
|
exports.COMBOS_DEVELOPMENT_TOOL_SET = COMBOS_DEVELOPMENT_TOOL_SET;
|
|
297
|
-
exports.CombosDevelopmentToolSystem =
|
|
706
|
+
exports.CombosDevelopmentToolSystem = CombosDevelopmentToolSystem;
|
|
298
707
|
exports.CombosDevelopmentToolTarget = CombosDevelopmentToolTarget;
|
|
708
|
+
exports.applyPropertyValue = applyPropertyValue;
|
|
709
|
+
exports.applyPropertyWithHooks = applyPropertyWithHooks;
|
|
710
|
+
exports.buildGameObjectSnapshot = buildGameObjectSnapshot;
|
|
711
|
+
exports.readPropertyValue = readPropertyValue;
|
|
712
|
+
exports.readSourceAnchor = readSourceAnchor;
|
|
299
713
|
//# sourceMappingURL=plugin-development-tool.cjs.js.map
|